2016-12-17 3 views
0

zum Beispiel Nehmen wir an, dass ich zwei Funktionen haben, die fast genau die gleichen sind, die einen Engpass des Systems darstellen, das in etwa so aussehen, (viel komplizierter):Keeping-Code DRY ohne Einbußen beim Wirkungsgrad

void f1(int s) 
{ 
    for(size_t i = 0, END = m_v.size(); i < END; ++i) 
    { 
     int bin_id = binId(m_v[ i ], s); 
     m_result[ bin_id ] += m_w[ i ]; // 
    } 
} 

void f2(int s) 
{ 
    for(size_t i = 0, END = m_v.size(); i < END; ++i) 
    { 
     int bin_id = binId(m_v[ i ], s); 
     m_result[ bin_id ] += 1.f; // 
    } 
} 

Alles ist gleich, nur dass Sie entweder eine Variable oder eine Konstante in einer Zeile des Codes verwenden. Wie bereits erwähnt, ist der tatsächliche Code sehr viel komplexer. Es wäre schön, es nicht zweimal mit dem geringfügigen Unterschied zu duplizieren, da es einen erfordert, um sicherzustellen, dass jeder identisch bleibt. Ich könnte so etwas tun, sie in eine verschmelzen:

void f3(bool use_weight, int s) 
{ 
    if(use_weight) 
    { 
     for(size_t i = 0, END = v.size(); i < END; ++i) 
     { 
      int bin_id = binId(v[ i ], s); 
      result[ bin_id ] += m_w[ i ]; // 
     } 
    } 
    else 
    { 
     for(size_t i = 0, END = v.size(); i < END; ++i) 
     { 
      int bin_id = binId(v[ i ], s); 
      result[ bin_id ] += 1.f; // 
     } 
    } 
} 

Dies ist aber immer noch den Code zu duplizieren, nur innerhalb einer einzigen Funktion. Wir könnten dies tun, aber es wäre eine schlechtere Leistung geben:

void f3(bool use_weight, int s) 
{ 
    for(size_t i = 0, END = v.size(); i < END; ++i) 
    { 
     int bin_id = binId(v[ i ], s); 
     if(use_weight) 
     { 
      result[ bin_id ] += m_w[ i ]; // 
     } 
     else 
     { 
      result[ bin_id += 1.f; // 
     } 
    } 
} 

Und der Aufruf-Code sieht wie folgt aus:

bool use_weight = something.use_weight(); 
const int N = very_large_number; 
for(int s = 0; s < N; ++s) 
{ 
    f3(use_weight, s); 
} 

Auch hier ist der Code unter der Annahme, viel komplizierter, so dass f3, zum Beispiel tatsächlich viel Logik duplizieren.

+2

Ausschließen des Codes in eine 'Inline'-Funktion, die einen Parameter übernimmt und entweder eine Variable oder eine Konstante eingibt, sollte die Codeverdopplung vermeiden und den Compiler jedes Mal den entsprechenden Code ausgeben lassen. –

+0

Wäre es ein Unterschied, dass Sie den 'bool' als Vorlagenparameter übergeben haben? – qxz

+0

Sie könnten lambdas für den Code verwenden, der sich in den zwei Varianten unterscheidet, und eine Variable auf den entsprechenden Rückruf vor der Schleife festlegen. Der Funktionsaufruf-Overhead ist jedoch wahrscheinlich belastend, wenn dies eine Engpassfunktion ist. – Barmar

Antwort

1

Ehrlich gesagt, kann manchmal die Optimierung der Code-Wiederverwendbarkeit oft aus der Tür gehen, aber in Ihrem Beispiel wäre es wahrscheinlich besser, Polymorphie zu verwenden. Klassen und Funktionen sollten Argumente verwenden, an denen sie arbeiten, und nicht Mitgliedervariablen. Eine 'Uber'-Funktion oder Klasse zu machen, die "alles macht" ist normalerweise ein Fehler. Diese Art von Klassen und Funktionen werden mit der Zeit immer mehr aufgebläht.

Also würde der Code idealerweise eine Schnittstelle verwenden, und der benötigte Parser würde injiziert werden. :)

var parser1 = new HotSauceParser(); 
parser.parse(arrayData); 

var parser2 = new WeightParser(); 
parser2.setWeights(m_w); // in many langages you can chain this. 
parser.parse(arrayData); 

Dies folgt die Single responsibility principle und leicht überprüfbar. Dann könnten Sie eine Klasse schreiben, die entscheidet, wann die eine oder die andere Klasse verwendet wird. Die Logik von WIE man analysiert, ist in den Parsern selbst eingekapselt.

Soweit es Effizienz betrifft, in der Regel, wenn Sie ein Array analysieren die Leistung Bedenken sind, wie groß diese Array ist und müssen Sie die gesamte Struktur gehen.

Seien Sie vorsichtig mit 'DRY'ing Ihren Code, es ist einfach zu über DRY Ihren Code und fallen in allgemeine Fallstricke wie über die Verwendung von Vererbung und/oder Erstellen von Klassen und Funktionen mit' Feature Envy '.

Sie möchten vielleicht die Clean Code Buch und S.O.L.I.D..