Ich suche nach Anleitungen zur Kopplung von DRY und Code. Ich dupliziere meinen Code nicht gerne und ich mag auch keine Codekopplung zwischen nicht verwandten Modulen. Ich refaktoriere also doppelten Code, wenn ich ein Jahr nach Einführung der Vervielfältigung identischen Code finde. Ich habe jedoch zunehmend Situationen erlebt, in denen die reale Welt viel unvorhersehbarer ist, und nach der Umgestaltung des Codes treten Situationen auf, die ein erneutes Herauslösen des Codes erfordern.
Wenn ich beispielsweise Code für den Umgang mit Benzinfahrzeugen, Benzin-SUVs, Elektroautos und Elektro-SUVs hätte, würde ich doppelten Code in die "Benzin" -Hierarchie und die "Elektro" -Hierarchie umgestalten, die beide von der "Fahrzeug" -Hierarchie abstammen. So weit, ist es gut. Und dann führt mein Unternehmen ein Hybridauto und ein Hybrid-Semi ein - das würde grundlegende Änderungen an meiner ursprünglichen Hierarchie erfordern. Möglicherweise würde es "Zusammensetzung" zwischen dem Benzin und den elektrischen Hierarchien erfordern.
Zweifellos ist die Codeduplizierung schlecht, da sie die Zeit verlängert, die für die Implementierung einer Änderung erforderlich ist, die allen oben genannten Produkten gemeinsam ist. Das Umgestalten von allgemeinem Code macht es jedoch ebenso schwierig, produktspezifische Variationen einzuführen, und führt zu viel "Klassensprung", wenn man die Codezeile finden muss, um einen Fehler zu beheben - eine Änderung in einer übergeordneten Klasse könnte dies bewirken Trigger lösen Regressionsfehler bei allen Nachkommen aus.
Wie erreicht man ein optimales Gleichgewicht zwischen DRY und unerwünschter Codekopplung?
Antworten:
Ich denke, dies ist einer der Hauptgründe, warum die Leute sich der Komposition und der Vererbung zuwenden.
Vererbung zwingt Sie zu großen Umstrukturierungen, wenn Sie eine konzeptionelle Änderung wie die von Ihnen beschriebene vornehmen.
Wenn die Umstrukturierung zu umfangreich ist, wird doppelter Code geschrieben, um dies zu vermeiden.
Anstatt das Duplikat zu entfernen, indem Sie den Code in der Vererbungskette nach oben verschieben, können Sie ihn in eine Hilfsklasse oder einen Hilfsdienst verschieben und diese Klasse dann bei Bedarf als Teil einer Komposition einfügen.
Ob das resultierende Design OOP ist, ist offen für Debatten
quelle
Wenn Sie dem DRY-Prinzip folgen, können Sie die Kopplung zwischen ansonsten unabhängigen Modulen erhöhen. Insbesondere in größeren Softwaresystemen kann dies zu Situationen führen, in denen die Nichtverfolgung von DRY die bessere Alternative sein kann.
Leider ist Ihr Beispiel nicht gut , dies zu demonstrieren geeignet - die beschriebenen Probleme durch klassische Fehler bei verursacht dort sind
falschsuboptimalen Verwendung der Vererbung verursacht. Für das, was ich oben geschrieben habe, spielt es jedoch keine Rolle, ob Sie allgemeinen Code in eine allgemeine Basisklasse oder in eine Hilfsklasse (Komposition) umgestalten. In beiden Fällen könnte man gezwungen sein, den gemeinsamen Code in eine Bibliothek L einzufügen und auf diese Bibliothek aus zwei zuvor nicht verwandten Programmen A und B zu verweisen.Nehmen wir an, A und B hatten zuvor keinerlei Beziehung zueinander und können unabhängig voneinander versioniert, freigegeben und bereitgestellt werden. Durch das Einfügen von gemeinsamem Code in eine gemeinsam genutzte Bibliothek L können jedoch neue Anforderungen für A Änderungen an L hervorrufen, die nun zu Änderungen an B führen können. Daher sind zusätzliche Tests und möglicherweise ein neuer Release- und Bereitstellungszyklus für B erforderlich.
Wie können Sie mit dieser Situation umgehen, wenn Sie nicht bereit sind, vom DRY-Prinzip abzuweichen? Nun, es gibt einige bekannte Taktiken, um dies zu erreichen:
Behalten Sie entweder A, B und L als Teil desselben Produkts bei, mit einer gemeinsamen Versionsnummer, einem gemeinsamen Erstellungs-, Freigabe- und Bereitstellungsprozess mit einem hohen Automatisierungsgrad
oder machen Sie L zu einem eigenständigen Produkt mit Nebenversionsnummern (keine inkompatiblen Änderungen) und Hauptversionsnummern (möglicherweise mit aktuellen Änderungen), und lassen Sie A und B jeweils auf eine andere Versionszeile von L verweisen.
Stellen Sie L so FEST wie möglich und achten Sie auf Abwärtskompatibilität. Je mehr Module in L ohne Änderung wiederverwendet werden können (OCP), desto unwahrscheinlicher ist es, dass Änderungen vorgenommen werden. Und die anderen Prinzipien in "SOLID" tragen dazu bei, dieses Ziel zu unterstützen.
Verwenden Sie automatische Tests speziell für L, aber auch für A und B.
Seien Sie vorsichtig mit dem, was Sie in L. einfügen. Eine Geschäftslogik, die nur an einer Stelle in einem System existieren sollte, ist ein guter Kandidat. Dinge, die nur "gleich aussehen" und in Zukunft anders aussehen könnten, sind schlechte Kandidaten.
Beachten Sie, dass bei der Entwicklung, Wartung und Weiterentwicklung von A und B durch unterschiedliche, nicht miteinander verbundene Teams das DRY-Prinzip an Bedeutung verliert. Bei DRY geht es um Wartbarkeit und Weiterentwickelbarkeit. Es kann jedoch manchmal effektiver sein, wenn zwei verschiedene Teams einen individuellen Wartungsaufwand erbringen, als ihre Produkte zu binden zusammen wegen ein bisschen Wiederverwendung.
Am Ende ist es also ein Kompromiss. Wenn Sie in größeren Systemen dem DRY-Prinzip folgen möchten, müssen Sie viel mehr Aufwand in die Erstellung robuster, wiederverwendbarer Komponenten investieren - in der Regel mehr als erwartet. Sie müssen Ihrem Urteil vertrauen, wann es sich lohnt und wann nicht.
quelle
DRY ist eine weitere strukturelle Regel. Das heißt, wenn Sie es extrem nehmen, ist es so schlimm, als würden Sie es ignorieren. Hier ist eine Metapher, die Sie aus der strukturellen Denkweise herausholt.
Liebe deine Zwillinge. Töte die Klone.
Wenn Sie blind kopieren und einfügen, um Tastatureingaben zu vermeiden, erstellen Sie sinnlos Klone. Sicher, sie tun, was Sie wollen, aber sie beschweren Sie, weil es jetzt so teuer ist, dieses Verhalten zu ändern.
Wenn Sie identisches Verhalten mit identischem Code reproduzieren, weil eine andere Verantwortung dafür besteht, dass Sie das gleiche Bedürfnis haben, aber das kann Sie von anderen Änderungen abhängig machen, haben Sie einen Zwilling, der sich im Laufe der Zeit frei verändern und als Individuum wachsen sollte.
Sie können ihre DNA (Code) nach Belieben scannen. Klone und Zwillinge sind schwer zu unterscheiden, wenn man sie nur ansieht. Sie müssen den Kontext verstehen, in dem sie leben. Warum sie geboren wurden. Was ihr letztendliches Schicksal sein wird.
Angenommen, Sie arbeiten für die Firma ABC. Es wird von den drei Unternehmensleitern A, B und C geleitet. Alle möchten, dass Sie ein Softwareprodukt erstellen, aber sie haben jeweils ihre eigenen Abteilungen. Sie alle möchten, dass Sie klein anfangen. Gib einfach eine einfache Nachricht aus. Sie schreiben also "Hallo Welt".
A hasst es, wenn Sie den Firmennamen dort eintragen.
B liebt es, möchte, dass Sie es in Ruhe lassen und den Firmennamen einem Begrüßungsbildschirm hinzufügen.
C möchte nur einen Taschenrechner und dachte, die Nachricht sei nur eine Möglichkeit für Sie, loszulegen.
Sie sind sich sicher, dass diese Leute sehr unterschiedliche Vorstellungen davon haben, worum es in diesem Projekt geht. Manchmal werden sie zustimmen. Manchmal ziehen sie dich in verschiedene Richtungen.
Wenn Sie Code duplizieren, weil Sie die Möglichkeit schaffen, dass dieser Code unabhängig voneinander variiert, erstellen Sie einen Zwilling. Wenn Sie Code duplizieren, weil das Tippen mühsam ist und das Kopieren und Einfügen einfach ist, erstellen Sie böse Klone.
A, B und C sind verschiedene Master, denen Ihr Code dienen muss. Keine Codezeile kann für lange Zeit mehr als einen Master bedienen.
quelle