it-swarm.dev

Warum ist DRY wichtig?

Ganz einfach, warum sollte ich Code schreiben wollen, der für alle Fälle und skalierbaren Daten funktioniert, wenn ich den gleichen Vorgang nur ein paar Mal mit ein paar kleinen Änderungen wiederholen muss?

Es ist unwahrscheinlich, dass ich dies bald wieder bearbeiten muss.

Es sieht nach viel weniger Arbeit aus, einfach zu gehen ...

function doStuff1(){/*.a.*/}
function doStuff2(){/*.b.*/}
function doStuff3(){/*.c.*/}

Und wenn ich jemals etwas hinzufügen muss ...

function doStuff4(){/*.d.*/}

Und wenn ich es entfernen muss, entferne ich es.

Es ist schwieriger herauszufinden, wie man all diese zu einem einfachen Muster macht, in das ich einfach Daten einspeisen und mit allen Fällen umgehen kann, und eine Reihe von Änderungen vornehmen kann, von denen ich nicht glaube, dass ich sie jemals haben werde machen.

Warum DRY sein, wenn es so aussieht, als würde ein schnelles Ausschneiden + Einfügen so viel weniger Arbeit bedeuten?

83
Incognito

Wenn Sie sich wiederholen, können Sie Wartbarkeitsprobleme verursachen. Wenn doStuff1-3 alle einen ähnlich strukturierten Code haben und Sie ein Problem in einem beheben, können Sie leicht vergessen, das Problem an anderen Stellen zu beheben. Wenn Sie einen neuen Fall hinzufügen müssen, können Sie einfach verschiedene Parameter an eine Funktion übergeben, anstatt sie überall zu kopieren.

DRY wird jedoch häufig von cleveren Programmierern auf die Spitze getrieben. Manchmal müssen Sie Abstraktionen erstellen, die so stumpf sind, dass Ihre Teamkollegen ihnen nicht folgen können. Manchmal ist die Struktur zweier Dinge nur vage ähnlich, aber unterschiedlich genug. Wenn doStuff1-4 so unterschiedlich sind, dass Sie unnatürlichen Code schreiben oder sich cleveren Codierungs-Backflips unterziehen müssen, die Ihr Team dazu bringen, Sie anzustarren, ist es möglicherweise in Ordnung, dies zu wiederholen Ich habe mich nach hinten gebeugt, um mich nicht ein paar Mal auf unnatürliche Weise zu wiederholen, und das Endprodukt bereut.

Ich irre mich immer auf der Seite von DRY und wiederhole mich in dem seltenen Fall, wenn ich denke, dass die Vorteile der Lesbarkeit das Risiko wert sind, dass jemand vergisst, einen Fehler an mehreren Stellen zu beheben.

Wenn Sie diesen Rat berücksichtigen, klingt es wie in Ihrem Fall

wiederholen Sie den Vorgang einige Male mit ein paar kleinen Änderungen

Ich würde definitiv hart arbeiten, um mich in Ihrem Fall nicht zu wiederholen. Unter der Annahme minimaler "Optimierungen" können sie mit verschiedenen Parametern behandelt werden, die sich auf das Verhalten auswirken, oder sie können abhängig gemacht werden, um verschiedene Unteraufgaben auszuführen.

Warum DRY sein, wenn es so aussieht, als würde ein schnelles Ausschneiden + Einfügen so viel weniger Arbeit bedeuten?

Berühmte letzte Worte. Sie werden es bereuen zu denken, dass ein Junior-Ingenieur, wenn er einen doStuff optimiert/repariert/umgestaltet, nicht einmal merkt, dass der andere existiert. Es kommt zu Heiterkeit. Meist tritt kein Sodbrennen auf. Jede Codezeile kostet mehr. Wie viele Codepfade müssen Sie mit so vielen wiederholten Funktionen testen? Bei einer Funktion müssen Sie nur einen Hauptpfad mit einigen Verhaltensänderungen testen. Beim Kopieren müssen Sie jeden doStuff separat testen. Wahrscheinlich verpassen Sie eine und ein Kunde hat möglicherweise einen unerwünschten Fehler und möglicherweise einige unerwünschte E-Mails in Ihrem Posteingang.

121
Doug T.

Weil DRY später weniger Arbeit sein wird.


TROCKEN: (Wiederholen Sie sich nicht)

Eine Funktion, die ein Argument annimmt.

def log(arg):
    print(arg)

C & P: (Kopieren & Einfügen)

26 Millionen Funktionen machen im Wesentlichen dasselbe, aber mit einem Unterschied von 2 Zeichen.

def logA():
    print('a')

def logB():
    print('b')

...ad infinitum...

Wie wäre es, wenn wir unseren Druck aktualisieren, um anzugeben, was genau gedruckt wird?

DRY :

def log(arg):
    print(arg + "Printed from process foo")

Erledigt.

C & P :

Sie müssen zurückgehen und jede einzelne Funktion ändern.


Was ist Ihrer Meinung nach einfacher zu debuggen?

48
John

Weil, angewendet auf Ihr Beispiel:

  • + Lesbarkeit

    Weniger Code bedeutet oft weniger Rauschen(nicht immer...)

  • + Flexibilität

    Wenn Sie jemals das Verhalten von doStuffX ändern mussten, möchten Sie sich selbst oder denjenigen, der es geschrieben hat, umbringen.

  • + Erweiterbarkeit

    Wenn Sie die einzelnen Teile in eine Datenstruktur Ihrer Wahl extrahiert und diese dann durch Aufrufen eines generischen doStuff durchlaufen haben, können Sie Ihrer Datenstruktur genauso gut eine Zeile hinzufügen, in der Sie einen neuen Eintrag wünschen Wenn Sie eines entfernen oder das Verhalten ändern, müssen Sie nur doStuff bearbeiten. Einfacher zu pflegen .

  • + Kosteneffizienz

    weniger Code bedeutet hier:

    • => weniger Entwicklung => reduzierte Kosten
    • => geringere Wahrscheinlichkeit für Fehler => weniger Supportzeit => reduzierte Kosten
  • + (mögliche) verwaltete Optimierung

    Abhängig von der Sprache hat der Compiler/Interpreter möglicherweise eine größere Chance zu bestimmen, dass generisches doStuff immer die nahezu identischen Dinge ausführt, oft ein Aufruf nach dem anderen, und inline es oder versuchen es zu optimieren . Wahrscheinlich nicht für X-Variationen von doStuffX.

  • + Prüfung und Qualität

    Testen ist einfacher: doStuff muss getestet werden, und das war's. Nun, nicht genau, aber das deckt bereits mehr ab. Nur seine IO Erwartungen variieren und müssen unter verschiedenen Bedingungen getestet werden, aber es ist immer noch viel einfacher zu testen und wartbarer als alle Variationen von doStuffX.

Insgesamt dies macht mehr aus wartbar Code und ein verbesserte Entwicklungseffizienz für Ihr Team, und es ist eine von vielen guten Praktiken bis Hilfe robustere und zuverlässigere Software erstellen.

16
haylem

Da alle anderen die Wartbarkeitsprobleme mit doppeltem Code hervorragend erklärt haben, sage ich nur Folgendes:

Ein Großteil der Programmierung erfordert, dass Sie über die Zukunft nachdenken, nicht nur über die unmittelbare Gegenwart. Sie haben Recht, dass das Kopieren und Einfügen jetzt einfacher ist, aber die Aussage es ist unwahrscheinlich, dass ich dies bald wieder bearbeiten muss " zeigt, dass Sie nicht richtig denken. Ja, Sie könnten kaufen Sie haben ein bisschen Zeit mit einem schnellen und schmutzigen Kopieren/Einfügen, aber dabei zeigen Sie, dass Sie nicht über Ihr unmittelbares Problem hinausblicken und an morgen denken können. Sind Sie sicher, dass Sie diesen Code nie wieder aufrufen müssen? Wissen Sie mit Sicherheit, dass es keine Fehler gibt? Können Sie zu 100% garantieren, dass Sie es nicht erneut besuchen müssen, wenn Ihre nächsten Funktionen implementiert werden müssen? Dies sind Probleme für morgen und müssen berücksichtigt werden, wenn Sie Heute neu gestalten.

Natürlich gibt es Zeiten, in denen Kopieren/Einfügen erforderlich ist. Als UI-Entwickler habe ich festgestellt, dass ich manchmal gegen das Prinzip DRY] verstoßen muss. Es ist scheiße, ich erschrecke jedes Mal, wenn es passiert, und zum Glück ist es selten. Aber es - passiert passiert.

Der Unterschied besteht darin, dass Sie bei Verstößen gegen DRY einen sehr zwingenden Grund dafür haben sollten, und die Aussage Es ist schwieriger herauszufinden, wie Sie all dies einfach zu einem einzigen machen können Muster ist nicht wirklich einer von ihnen. Ich denke nicht, dass dies eine gültige Begründung ist, es sei denn, Sie befinden sich in einer massiven Zeitkrise und Ihr Chef schreit, um in den nächsten Stunden etwas zu bekommen, oder Sie verlieren Ihren Job.

Verstehe das nicht falsch: Ich versuche nicht, dich zu züchtigen oder zu bestrafen, sondern versuche dich dazu zu bringen, zu sehen, wo deine Mentalität falsch ist. Programmierer investieren in zukünftige Faulheit; DRY ist ein Weg, dies zu erreichen. Die Arbeit, die Sie heute zur Lösung eines schwierigen Designproblems leisten, wird sich morgen auszahlen.

13
bedwyr

Es ist unwahrscheinlich, dass ich dies bald wieder bearbeiten muss.

Wenn dies wirklich der Fall ist, können Sie möglicherweise damit durchkommen, aber meistens werden Sie an Code arbeiten, der gewartet werden muss. Das bedeutet, die Funktionalität zu erweitern, Fehler zu beheben und andere Verbesserungen vorzunehmen. Wenn Sie an 10 verschiedenen Stellen kleine Variationen desselben Codes haben und eines Tages zu diesem Code zurückkehren und eine Änderung vornehmen müssen, haben Sie jetzt die fehleranfällige Aufgabe, dieselbe Änderung an 10 verschiedenen Stellen vorzunehmen (Entschuldigung, dort waren 11 Plätze, du hast einen vergessen und jetzt hast du einen Bug).

Wenn Sie verallgemeinern können, welches Problem Sie lösen möchten, können Sie Ihren Code einfacher erweitern und beheben, wenn Fehler auftreten.

7
Alex

Wie ich in der Antwort auf eine andere Frage angegeben habe, ist mein Ansatz der folgende:

  1. Wenn ich ein bestimmtes Problem zum ersten Mal löse, erledige ich es einfach.
  2. Beim zweiten Mal (d. H. Wenn ich ein ähnliches Problem löse) denke ich: hm, vielleicht wiederhole ich mich, aber ich werde vorerst schnell kopieren und einfügen.
  3. Das dritte Mal denke ich: hm, ich wiederhole mich -> mach es allgemein!

Das heißt, Bis zu 2 gewinnt ein anderes Prinzip (YAGNI) über DRY. Aber ab 3 (oder 4, wenn ich wirklich faul bin!) Scheint ich es zu brauchen und folge DRY.

pdate

Einige weitere Ideen aus meiner jüngsten Erfahrung. Ich musste zwei von einem anderen Team entwickelte Komponenten A und B anpassen/in unser Produkt integrieren. Erstens: Die beiden Komponenten A und b B sind einander sehr ähnlich, so dass ich bereits durch die Tatsache gestört wurde, dass sie eine etwas andere Architektur hatten. Zweitens: Ich musste sie anpassen, damit ich gerne Unterklassen verwendet und nur das überschrieben hätte, was ich wirklich brauchte.

Also habe ich angefangen, diese beiden Komponenten (von denen jede aus ungefähr 8 C++ - Klassen besteht) umzugestalten: Ich wollte eine gemeinsame Architektur für A und B haben und dann die Funktionen hinzufügen, die wir benötigen, indem wir Unterklassen definieren. Auf diese Weise wären unsere beiden neuen Komponenten A 'und B' von den vorhandenen abgeleitet worden.

Nachdem ich zwei Wochen lang versucht hatte, eine gemeinsame und klar definierte Struktur aus dem vorhandenen Code herauszuholen, und während unserer täglichen Besprechungen erklären musste, dass ich wenig Fortschritte gemacht habe, weil der ursprüngliche Code zu chaotisch war, sprach ich mit meinem Chef. Wir stellten fest, dass wir nicht mehr als diese beiden neuen Komponenten A 'und B' benötigen würden (es würden nicht vier oder sechs davon sein, nur diese beiden).

Ok, so sei es: Ich habe eine massive Kopie erstellt und Klassen von A und B umbenannt und begonnen, die Kopie des Codes anzupassen. Ich habe es in zwei weiteren Wochen zum Laufen gebracht (ich mache jetzt noch einige Fehlerbehebungen).

Vorteile: Wir haben die Funktionalität jetzt fast fertig und wenn wir alle Fehler behoben haben, sind wir fertig. Wir haben alle Umgestaltungen und Tests von A und B gespeichert.

Nachteile: Vor zwei Wochen hat das andere Team eine andere Komponente C geändert, die von A und B verwendet wird. Sie haben A und B angepasst, aber A 'und B' waren ebenfalls defekt und wir mussten sie selbst ändern. Dies führte zu einem neuen Fehler, den wir beheben mussten. Diese zusätzliche Arbeit wäre wahrscheinlich unnötig gewesen, wenn A 'und B' den größten Teil ihres Codes mit A und B geteilt hätten.

Also: Codeduplizierung ist immer gefährlich. Ich denke, es geht immer darum, Kompromisse zu finden, und oft ist es nicht einfach.

6
Giorgio

Nur zur Klarstellung, da ich dies in keiner der anderen Antworten finde:

DRY ist ein Prinzip der Softwareentwicklung, das darauf abzielt, die Wiederholung von Informationen von aller Art zu reduzieren.

Jedes Wissen muss eine einzige, eindeutige und maßgebliche Darstellung innerhalb eines Systems haben.

Das DRY -Prinzip, wie es von Andy Hunt und Dave Thomas erwähnt wird, beschränkt sich nicht nur darauf, das Duplizieren von Code zu verhindern. Es befürwortet auch Codegenerierung und alle Automatisierungsprozesse. Ironischerweise könnten die Ergebnisse der Codegenerierung sogar doppelter Code sein ...

Der Grund dafür wurde bereits in den anderen Antworten ausführlich erklärt, aber Falcons Kommentar fasst es meiner Meinung nach gut genug zusammen:

Ein einzelner Änderungspunkt ist einfacher zu warten.

5
Steven Jeuris

Es gibt so etwas wie zu viel TROCKEN. In diesem Fall können sich zwei Konzepte, die irgendwann ähnlich genug erscheinen, um Factoring-Code (1) zu rechtfertigen, später als so unterschiedlich herausstellen, dass sie separate Implementierungen verdienen.

Mit anderen Worten, DRY und lose Kopplung stehen manchmal in Konflikt. Wenn Sie erwarten, dass doStuff1 und Freunde bei jeder neuen Version der Software voneinander abweichen, ist es in Ordnung, ihren Code zu duplizieren.

Nach meiner Erfahrung kann es schwierig sein zu beurteilen, wohin Ihre Software in Zukunft gehen wird, und aus diesem Grund ist DRY oft eine sichere Wahl.

Code, der übermäßig "getrocknet" wurde, hat normalerweise einen komplexen Kontrollfluss und zu viele Parameter. Was ursprünglich eine einfache Funktion war, wurde später erweitert, um eine neue Funktionalität zu unterstützen, die durch einen zusätzlichen Parameter gesteuert wird. Nach zwei oder drei Iterationen kann die Funktion nicht mehr gewartet werden. Beheben Sie einen Fehler, der in einer Einstellung auftritt, und Sie führen neue Fehler in anderen Einstellungen ein.

Es ist verständlich, dass die Codequalität häufig mit der Entwicklung des Codes abnimmt, aber ich habe Fälle gesehen, in denen eine Multiparameterfunktion mit Wenn-Dann-Sonst-Spaghetti im Körper das Ergebnis einer gut gemeinten, aber schlecht durchgeführten Umgestaltung war.

(1) Ich verwende den Wort "Code", dies gilt jedoch auch für das Design.

3
Joh

Ich muss die Probleme mit DRY in der relationalen Datenbankwelt erwähnen. Datenbanken sind so konzipiert, dass sie mit satzbasierter Logik und durch sargable Abfragen schnell und gut funktionieren. DRY = Prinzipien führen häufig dazu, dass der Entwickler nicht Sargable-Abfragen schreibt oder Row-by-Agonizing-Row-Logik verwendet, um vorhandenen Code in mehreren Situationen zu nutzen. DRY und Leistungsoptimierung sind häufig uneins und in der In der Datenbankwelt ist die Leistung in der Regel weitaus kritischer als die Wartbarkeit. Dies bedeutet nicht, dass Sie die Prinzipien DRY überhaupt nicht verwenden sollten, sondern nur wissen sollten, wie sich dies auf die allgemeine Benutzerfreundlichkeit auswirkt Anwendungsentwickler-Sache DRY erstens und Leistung zweitens, Datenbankentwickler denken zuerst an Datenintegrität, zweitens an Leistung, drittens an Sicherheit der Daten (Leistung und Sicherheit können in einigen Systemen die Plätze tauschen) und somit DRY ist ein weit entfernter 4 ..

Ich habe im Allgemeinen festgestellt, dass je mehr Abstraktionsebenen Sie in Datenbankabfragen einfügen, desto langsamer werden sie. Ich sage nicht, dass ich nicht wünschte, dass die Leute, die die Datenbankprogramme selbst entwerfen, es Entwicklern nicht besser machen würden, DRY] zu verwenden, ohne die Leistung der Datenbank zu beeinträchtigen, aber ich Entwerfen Sie keine Datenbanksoftware auf dieser Ebene, daher ist der Konflikt zwischen Abstraktion und Leistung in der Datenbank möglicherweise schwieriger zu beheben als ich vermute. Wir müssen jedoch mit den Systemen arbeiten, wie sie derzeit erstellt werden. Wir können eine bessere Implementierung von fordern DRY Prinzipien in zukünftigen Versionen, die nicht auch die Leistung beeinträchtigen (und im Laufe der Jahre besser geworden sind, aber immer noch problematisch sind), aber in der Zwischenzeit müssen wir überlegen, ob DRY ist derzeit der richtige Schritt für diese Datenbank.

Aber oft sind es genau die Funktionen, die Sie verwenden möchten, um sicherzustellen, dass das DRY -Prinzip erfüllt wird), die enorme Probleme für die Datenbank verursachen. Ich sage nicht, dass Sie niemals DRY aber geh nicht über Bord.

Beispiele für das, wovon ich spreche. Sie müssen einmal im Monat einen Datenimport von einer Million Datensätzen durchführen. Datensätze können bereits manuell über die Benutzeroberfläche hinzugefügt werden, indem ein gespeicherter Prozess aufgerufen wird. Da dieser Prozess für den Import einzelner Datensätze konzipiert wurde, wird jeweils nur ein Datensatz hinzugefügt. Wenn Sie DRY) verwenden, um zu vermeiden, dass der Einfügecode an zwei Stellen angezeigt wird, schreiben Sie einen Cursor, um den Prozess wiederholt aufzurufen, anstatt die erforderlichen satzbasierten Importe zu schreiben. Die Zeit für den Import beträgt 30 Minuten Die Verwendung einer satzbasierten Logik würde bis zu 18 Stunden dauern. In diesem Fall besteht der richtige Weg zur Einhaltung von DRY in diesem Fall darin, den Prozess für die Verarbeitung mehrerer Datensatzimporte zu reparieren. Leider ist dies häufig nicht möglich oder es ist sehr schwierig, ein Array an einen Prozess zu senden (abhängig vom DB-Back-End). Wenn Sie den Prozess ändern, wird die Anwendung beschädigt.

Skalarfunktionen und Tabellenwertfunktionen werden auch zum Implementieren von DRY -Prinzipien) verwendet. Auch hier können sie die Leistung ernsthaft beeinträchtigen, insbesondere wenn Sie sie so verwenden müssen, dass die Indizes nicht nützlich sind.

Ansichten sind auch gut für die Implementierung von DRY. Wenn Sie jedoch DRY durch die Verwendung von Ansichten implementieren, die Ansichten aufrufen, die andere Ansichten aufrufen, gelangen Sie schnell zu dem Punkt, an dem die Abfragen unter Last eine Zeitüberschreitung aufweisen um Datensätze von Millionen von Datensätzen zu generieren, wenn Sie am Ende nur drei benötigen. Eine einstufige Ansicht eines komplexen Satzes von zu implementierenden Verknüpfungen kann also hervorragend sein DRY kann ausgezeichnet sein (ich habe selbst einen) Wir stellen sicher, dass alle Finanzberichte denselben Basissatz von Tabellen und Berechnungen für bestimmte Dinge verwenden (mehr als zwei Ebenen), und Sie müssen berücksichtigen, ob Sie ein Leistungsproblem verursachen.

2
HLGEM

Ich sehe die wichtigsten Punkte meiner Antwort oben nicht, also geht es weiter. Schauen Sie sich DRY in der Regel nicht so sehr an gegen etwas zu tun. Es mag so formuliert sein, aber es kann wirklich einem ganz anderen und positiven Zweck dienen Ein Signal zum Anhalten, Nachdenken und Finden einer besseren Antwort. Es fordert mich heraus, nach Möglichkeiten zu suchen, um eine bessere Lösung zu entwerfen. Es ist die gute Seite eines schlechten Geruchs in meinem Code, die mich dazu veranlasst, mein Design zu überdenken und mich dazu zu bringen, es zu tun viel besser. DRY handelt nicht nur von einer kleinen Syntaxverletzung. Es fordert mich zum Modularisieren auf. Es fordert mich zum Komponieren heraus. Es signalisiert Wiederholungen, die mich daran erinnern, über die Verwendung von Vorlagen und Code nachzudenken Generation statt roher Gewalt und Ignoranz. Es hilft mir herauszufinden, dass ich etwas Zeit finden sollte, um meine Automatisierung zu automatisieren. Es führt Sie zu einem sparsamen Lebensstil! Es hilft Ihnen, mehr Zeit damit zu verbringen, coolere neue Sachen zu machen, als pingelige alte Langeweile Details. Und es gibt Ihnen gute Manieren, guten Atem und einen gesunden Lebensstil! Nun, vielleicht irre ich mich ein bisschen ....

1
John Tobler

Ja, kümmere dich nicht um DRY wenn du schreibst Wegwerfcode.

Aber DRY ist natürlich wichtig, wenn Sie den Code behalten möchten.

1
Pacerier

Ich habe ein altes Legacy-Projekt, bei dem sich einige der früheren Entwickler überhaupt nicht um DRY) gekümmert haben. Die gesamte Codebasis war also mit Hilfsmethoden wie GetSystemTimeAsString (), LogToFile () und vielen überfüllt Einige Methoden wurden leicht an spezielle Bedürfnisse angepasst, aber die meisten waren nur Kopieren und Einfügen.

Leider hatten einige der Methoden subtile Fehler wie char array, die in einigen Fällen nicht lang genug waren, und verwendeten unsichere Dinge wie strcpy () usw.

Es war also eine echte PITA, alle Codefragmente zu finden, zu harmonisieren und die Fehler zu beheben. Und wir harmonisieren und reparieren immer noch Dinge.

Sie wissen nie, ob Sie bei Ihrer ersten Methode einen Fehler gemacht haben und ihn dann mehrmals beheben müssen, weil Sie ihn gerade kopiert haben. Und wenn Sie einige der Methoden später verwenden möchten, woher wissen Sie, welche der 5 Methoden in der Codebasis derzeit für Ihren Fall geeignet ist? Sie kopieren einfach eine, passen sie an und hier beginnt sie erneut ...

1
Simon

Die Ausdrucksweise "Wiederhole dich nicht" ist etwas zu simpel. Wichtig ist: "Vermeiden Sie, dass eine potenziell veränderbare Information an zwei nabhängigen Stellen eingekapselt wird."

Wenn ein Programm Widgets mit jeweils drei Woozles verarbeiten soll und viele Schleifen des Formulars enthält

for (i=0; i<3; i++)
  thisWidget.processWoozle(i);

dann würde die Erwartung, dass die Widgets voraussichtlich drei Woozles enthalten, in jeder dieser Schleifen eingekapselt sein, und die Aktualisierung des Codes, um eine andere Anzahl von Woozles pro Widget aufzunehmen, könnte schwierig sein. Im Gegensatz dazu, wenn man sagen würde

#define WOOZLES_PER_WIDGET 3

und jede Schleife wurden neu geschrieben

for (i=0; i<WOOZLES_PER_WIDGET; i++) ...

ein solches Design könnte macht es sehr einfach, die Anzahl der Woozles pro Widget zu ändern.

Es ist jedoch wichtig zu beachten, dass es zwar wünschenswert ist, Informationen wie die Anzahl der Woozles pro Widget auf einen einzigen Punkt zu konsolidieren, dies jedoch nicht immer praktikabel ist. Manchmal kann es notwendig sein, die Logik hart zu codieren, was nur funktioniert, wenn die Dinge eine bestimmte Größe haben. Wenn zum Beispiel jede Woozle einen Wert hat und man den Median finden möchte, der einem bestimmten Widget zugeordnet ist, kann es möglich sein, die Werte zu sortieren und die mittlere zu nehmen, und ein solcher Ansatz würde mit einer beliebigen Anzahl von Woozles funktionieren, aber mit Logik Die Handschrift, die speziell für den Median von drei Elementen geschrieben wurde, könnte erheblich schneller sein.

Während eine WOOZLES_PER_WIDGET-Konstante den Code lesbarer machen kann, sollte sie kommentiert werden, um zu verdeutlichen, dass ihr Wert nicht geändert werden kann, ohne andere Anpassungen an der Programmlogik vorzunehmen. In diesem Fall würde die Logik, die für drei Elemente fest codiert ist, und die Konstante WOOZLES_PER_WIDGET beide die Informationen "Jedes Widget hat drei Woozles" duplizieren, aber die Vorteile einer solchen Duplizierung (höhere Ausführungsgeschwindigkeit) könnten die Kosten überwiegen.

1
supercat

Während ich den anderen Postern tatsächlich zustimme, sind Kommentare zur Wartbarkeit usw. gültig.

Ich möchte der Debatte eine kleine Gegenstimme hinzufügen.

  • Es ist nur für Programmierer wichtig. Die Leute, die Ihren Lohn bezahlen, könnten sich nicht weniger darum kümmern, solange die Software UAT besteht.
  • In Bezug auf die Wichtigkeit liegt es weit unter den Punkten wie die richtigen Anforderungen zu erhalten, den Projektsponsoren zuzuhören und pünktlich zu liefern.
0
James Anderson

<tl;dr>

Ich konnte nicht alle wiederholten Antworten lesen, daher habe ich möglicherweise etwas verpasst (und werde es selbst wiederholen <= sehen, was ich hier getan habe?).

Hier ist die Liste der Dinge, die großartig sind, um das Duplizieren von Code zu verhindern!

  1. Einfacher zu testen: Sie müssen nur eine Kopie des Codes testen.
  2. Einfacher zu beheben: Sie müssen den Fehler nur in einer "Kopie" des Codes finden und einmal beheben.
  3. Einfacher zu aktualisieren (wie oben): Erforderliche Änderungen können häufig durch Ändern des Codes an sehr wenigen Stellen vorgenommen werden, da Sie sich die Zeit genommen haben, den Code ordnungsgemäß wiederzuverwenden, und nicht dieselben Zeilen an Hunderte oder Tausende verschiedener Stellen in der Quelle kopiert haben.
  4. Einfacher wiederzuverwenden: Wenn (an einigen Stellen nicht dupliziert) und in generischen, treffend benannten Methoden aufbewahrt wird, ist es einfach, sie zu finden und zu verwenden, anstatt eigene zu schreiben.
  5. Einfacher zu lesen: Duplizierter Code ist schwer zu lesen, da er unnötig ausführlich ist. Es enthält viele Zeilen, die nicht Teil der Logik und der spezifischen beabsichtigten Funktionalität sind (z. B. generische Befehle zum Einrichten der Bühne für die auszuführende Aktion oder generische einfache wiederholte Aufgaben, die an vielen Stellen benötigt werden). Sauberer Code lässt die Logik und Funktionalität herausspringen, da keine Wiederholung den Code-Raum verschmutzt.
  6. Einfacher zu debuggen aufgrund von (1) und (5).
  7. Spart Ihnen Zeit und Geld und macht in Zukunft mehr Spaß. Erstellen Sie speziell robusteren Code. Dies ist das Endergebnis und eine Zusammenfassung von so ziemlich allen oben genannten Punkten. Wenn viele Leute dieselbe Funktion doFoo1(a, b) verwenden, besteht eine bessere Chance, dass viele der lästigen Fehler und Edge-Fälle aufgedeckt und behoben werden. Wenn jeder den Code kopiert und doFoo2(specialA) ... doFuu2^n(a, b, c) erstellt, haben sie die Probleme in doFoo1 Dupliziert und konkret viel mehr Arbeit erstellt.

</tl;dr>

Lange Version:

Das Problem bei der Codeduplizierung besteht darin, dass sie "exponentiell wächst" (mit anderen Worten, sie dehnt sich schnell aus), da Sie beim Duplizieren von Code unwissentlich anderen die Erlaubnis erteilen (zum einen sind Sie nicht mehr in der Lage, sie zu beurteilen) und Sie ermutigen sie, dasselbe zu tun. Sie machen es auch schwieriger, dies nicht zu tun, da es schwieriger ist, nützlichen Code zu erkennen und wiederzuverwenden, wenn die Quelle viele verwirrende redundante Wiederholungen enthält. Insbesondere, wenn der Code noch nicht in eine treffend benannte Funktion extrahiert wurde. Wenn Sie also vor einem häufig auftretenden, einfach zu lösenden Problem stehen, werden Sie wahrscheinlich selbst einen Code schreiben, der das Problem löst. Und Sie werden wahrscheinlich nicht nach einigen Edge-Fällen suchen und mehr fehlerhaften, nicht getesteten Code hinzufügen.

Eine andere Sache ist, dass dies für einen Anfänger wie ein Problem klingt, das nur große Unternehmen betrifft, aber ich fand, dass es winzige Startups nur schwer trifft (wie in 10.000 Zeilen duplizierten serverseitigen Codes). Es ist ein Geisteszustand. Sie sollten nicht nur DRY beherrschen, sondern auch andere dazu ermutigen, dasselbe zu tun; sonst werden Sie sich dazu verurteilen, Code größtenteils zu duplizieren. Wenn die Mittel von DRY zur Hand sind und durchgesetzt werden, ist es viel einfacher, sie anzuwenden. Wenn es viel duplizierten Code gibt, ist es viel einfacher, Copy-Paste-Lösungen anzuwenden.

Dinge, die ich bei der Codeduplizierung als schädlich empfinde:

  1. Ist diese Funktion verwendbar? Nehmen wir an, Sie finden eine Funktion, die das tut (oder zu tun scheint, was Sie brauchen), woher wissen Sie, ob sie überhaupt richtig funktionieren soll oder ob es sich nur um Code handelt, der dupliziert und aufgegeben wurde.
  2. Redundanter Code. Manchmal duplizieren Leute Code, verwenden ihn und vergessen ihn (sie können ihn in Zukunft immer wieder duplizieren). Irgendwann entfernt jemand die Aufrufe der duplizierten Funktion an einigen Stellen, um sie umzugestalten, aber die nicht verwendete Funktion bleibt bestehen, auch wenn sie nicht aktiv verwendet wird.
  3. Schwer zu finden, wonach Sie suchen. Duplizierter Code nimmt Platz ein und macht es schwieriger, nützliche und benötigte Dinge zu finden (mit Tools wie grep), als es sein muss, da Sie Dutzende oder Tausende von Ergebnissen erhalten, bei denen Sie nur eine Handvoll hätten erzielen sollen.
  4. (Wurde bereits erwähnt): Schwer zu warten, aber auch schwer zu Wartungs- und Regressionszwecken zu verwenden. Wenn Testcode dupliziert und nicht ordnungsgemäß in Funktionen extrahiert wird, wird er von anderen dupliziert. Wird sich jemand die Mühe machen, eine benutzerfreundliche, einfach zu lesende API zu schreiben, um die Lebensqualität zu verbessern? Nach meiner Erfahrung gibt es oft etwas, das die Leute für dringlicher halten, bis es außer Kontrolle gerät.
  5. Das Duplizieren von Code ist schwieriger zu lesen, da der Code dort wortreich ist, wo er nicht sein muss, an Orten, an denen die Ausführlichkeit keine Informationen über die beabsichtigte Funktionalität hinzufügt: zum Beispiel generische Methodenaufrufe, die [immer und immer wieder] verwendet werden Wenn Sie den Grundstein für mehrere Arten von beabsichtigten Funktionen legen, wird es für diese tatsächliche Funktionalität schwieriger, herauszukommen.
  6. Dies wurde viel erwähnt. Wenn der Code falsch ist, muss ein armes Mädchen oder ein armer Kerl jede Verwendung dieses Codes suchen und ändern. Wenn zum Beispiel jemand einen unsicheren SQL-Injection-Aufruf von mysql_query an sehr wenigen Stellen in einer organisierten Klasse verwendet, an denen er benötigt wird, ist es einfach, ihn zu beheben und stattdessen PHP PDO) zu verwenden, aber wenn er verwendet wird An über tausend Stellen, an denen der Anruf immer wieder kopiert und repariert wird, muss er praktisch ausgelagert werden oder manchmal gefährlicher. Der Code muss von Grund auf neu geschrieben werden.
  7. Das Duplizieren von Code ist eine schlechte Angewohnheit. Wenn Sie etwas üben, wird es langsam zu einer zweiten Natur und betrifft die Menschen um Sie herum. Junior-Entwickler sehen, wie Sie es tun und tun es auch. Sie sollten üben, was Sie predigen, und sich angewöhnen, das Richtige zu tun. Du lernst mehr. Das Schreiben von nicht dupliziertem Code ist schwieriger und schwieriger. Es ist eine lohnende Angewohnheit.

Letzte Anmerkungen zur Verhinderung von übereifriger Codeduplizierung und Zusammenfassung:

Dies wurde auch schon früher gesagt, aber manchmal führt das Vermeiden von Duplikaten dazu, dass Sie sich "nach hinten beugen" und Dinge tun, die für andere zu raffiniert (oder unwichtig) sind, um sie zu verstehen. Das Schreiben von unlesbarem Code (oder wie wir es scherzhaft als "Jobbewahrungscode" bezeichnen) ist an sich schon ein Problem, selbst wenn die Verhinderung von Codeduplizierungen nicht beteiligt ist. Ich finde jedoch, dass es viel einfacher ist, Codeduplizierungen zu verhindern, wenn von Anfang an die richtige Infrastruktur und die besten Vorgehensweisen eingeführt werden, und dass Menschen häufig nicht intuitive Dinge vermeiden können, um zukünftige unnötige und unlesbare Haufen von Arbeit zu verhindern, die zur Verhinderung von Codeduplikationen durchgeführt werden, wenn Sie machen von Anfang an alles richtig.

Was macht die Dinge richtig? Nun, das ist eine schwer zu beantwortende Frage, aber eine Sache ist, zu definieren, welche Methoden für das Projekt benötigt werden, zu sehen, was bereits von anderen (außerhalb und) innerhalb des Unternehmens implementiert wurde, und diese nach Möglichkeit wiederzuverwenden. Dokumentieren Sie alles, was Sie zur Codebasis hinzufügen, und versuchen Sie, sie um eine Stufe allgemeiner zu gestalten, als es sein muss, aber das war's. Übertreiben Sie Designmuster nicht, nur um den Code flexibel zu machen, wo er nicht sein muss.

0
AturSams