DRY-Code ohne Bezug, aber nahezu identisch

34

Ich habe einen Code, der fast identisch ist, aber absolut unterschiedliche Typen ohne Vererbung zwischen ihnen für die Hauptvariable verwendet. Insbesondere schreibe ich einen Analysator mit Roslyn für C # und VB.NET mit den folgenden Typen:

Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax

Ich frage mich, ob ich, weil der Code dasselbe tut, ihn so trocken wie möglich halten soll, indem ich ihn so wenig wie möglich in separate (aber mit Ausnahme des Typs identische) Methoden aufspalte oder ihn vollständig trenne, weil die beiden Methoden identisch sind Nicht verwandte und zukünftige Änderungen könnten eine Version zur Änderung zwingen, aber nicht die andere (obwohl dies unwahrscheinlich ist)?

Bearbeiten: Etwa ein Jahr später stieß ich auf dasselbe Problem, und das Roslyn-Team half mir bei der Lösung: Schreiben Sie eine Basisklasse, die Generika verwendet und einen TAttributeSyntaxParameter hat, der die meiste Arbeit leistet. Schreiben Sie dann abgeleitete Klassen mit dem Minimum an Daten, die einen bestimmten Typ benötigen.

Hosch250
quelle
Würde es funktionieren, Ihre eigene AttributeSyntax-Schnittstelle zu erstellen, die die vorhandenen Klassen umschließt, Ihnen aber die Vererbung gibt, die konzeptionell vorhanden sein sollte?
Winston Ewert
7
Es tut uns leid, wenn dies offensichtlich ist, aber es gibt Generika, sodass Sie sich nicht für identischen Code, sondern für Typ wiederholen müssen. Wenn Sie das nicht gemeint haben, ignorieren Sie es bitte.
Davislor
@Lorehead Normalerweise würde ich das tun, aber dies ist eine einzelne Methode, die einem Typ übergeben wird, der den Knoten als Nutzlast einer internen Methode enthält, über die ich keine Kontrolle habe.
Hosch250
@ WinstonEwert Ich werde das untersuchen. Ich bin mir jedoch nicht sicher, ob ich das für alle C # / VB.NET-Typen tun möchte.
Hosch250
1
Refactoring birgt viele Kompromisse und manchmal sogar Widersprüche. ZB lose Kopplung gegen DRY oder kurze Funktionen, aber viele davon gegen längere Funktionen und wenige davon. Am Ende ist es ein schwieriges Biest: Ihr Ziel ist die Lesbarkeit und Wartbarkeit. Sie müssen als Avatar denken, der Ihren Code zum ersten Mal sieht. Und manchmal versuchen Sie einfach, um zu sehen , was besser ist. Ein perfektes Refactoring ist leider nicht möglich.
Phresnel

Antworten:

111

Du machst DRY nicht, weil jemand es in ein Buch geschrieben hat, das es gut macht. Du machst DRY, weil es tatsächlich greifbare Vorteile hat.

Speziell aus dieser Frage:

Wenn Sie sich wiederholen, können Sie Wartbarkeitsprobleme erstellen. Wenn doStuff1-3 alle ä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 einzufügen.

Allerdings wird DRY von geschickten Programmierern oft als extrem empfunden. Um sich nicht zu wiederholen, müssen Sie manchmal 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 durch das Umgestalten nicht wiederholt werden, unnatürlichen Code schreiben oder clevere Codierungs-Backflips ausführen müssen, durch die Ihr Team Sie anstarrt, ist es möglicherweise in Ordnung, sich selbst zu wiederholen. Ich habe mich nach hinten gebeugt, um mich nicht ein paarmal unnatürlich zu wiederholen, und das Endprodukt bereut.

Also denke im Grunde nicht "oh man, dieser Code ist ziemlich ähnlich, vielleicht sollte ich mich überarbeiten, um mich nicht zu wiederholen". Denken Sie, "macht das Umgestalten, um diese Codebasis wiederzuverwenden, gemeinsame Elemente den Code wartbarer oder weniger wartbar ?" Wählen Sie dann den, der die Wartung erleichtert.


Angesichts der SRP und der Tatsache, dass Sie nur versuchen, kleine, flexible Klassen zu haben, ist es möglicherweise sinnvoll, Ihren Code aus diesem Grund zu analysieren und Verhaltensmerkmale zu zerlegen, in die generische Typen (Sie sagten, dass sie von Typ verschieden sind) verwendet werden kleine Klassen. Dann werden Sie feststellen, dass einige dieser Klassen tatsächlich völlig identisch sind (nicht nur größtenteils identisch), und dann können Sie ein Toolkit erstellen, falls Sie es hinzufügen möchten Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntax.

durron597
quelle
32
TL; DR - DRY ist ein Mittel zum Zweck. Konzentrieren Sie sich auf das Ziel, nicht auf die Mittel. Wenn ich den Lego Man zweimal verbessern könnte, würde ich es tun.
Ein wichtiger Hinweis: Wenn Sie sich wiederholen, erwähnen Sie im Kommentar immer alle anderen Stellen, die besucht werden müssen, wenn sich der wiederholte Code ändert. Dies verringert nicht nur die Wahrscheinlichkeit einer Desynchronisierung, sondern zeigt auch an, wie viel Wartungsschmerz die Wiederholung bei Ihnen verursacht.
Xion