Codewartung: Behalten Sie ein schlechtes Muster bei, wenn Sie neuen Code erweitern, um konsistent zu sein, oder nicht?

45

Ich muss ein bestehendes Modul eines Projekts erweitern. Ich mag es nicht, wie es gemacht wurde (viele Anti-Patterns, wie zum Beispiel kopierter / eingefügter Code). Ich möchte aus vielen Gründen keinen kompletten Refactor durchführen.

Sollte ich:

  • Neue Methoden unter Verwendung bestehender Konventionen erstellen, auch wenn ich das für falsch halte, um Verwirrung für den nächsten Betreuer zu vermeiden und mit der Codebasis konsistent zu sein?

oder

  • versuchen Sie zu verwenden, was ich besser finde, auch wenn es ein anderes Muster im Code einführt?

Präzisionsbearbeitung nach ersten Antworten:

Der vorhandene Code ist kein Chaos. Es ist leicht zu folgen und zu verstehen. ABER es wird eine Menge Boilerplate-Code eingeführt, der mit gutem Design vermieden werden kann (der resultierende Code ist möglicherweise schwieriger zu folgen). In meinem aktuellen Fall handelt es sich um ein gutes altes JDBC-DAO-Modul (Spring Template Inboard), aber ich bin bereits auf dieses Dilemma gestoßen und suche nach anderem Entwickler-Feedback.

Ich möchte nicht umgestalten, weil ich keine Zeit habe. Und selbst mit der Zeit wird es schwer zu rechtfertigen sein, dass ein perfekt funktionierendes Modul überarbeitet werden muss. Refactoring-Kosten sind schwerer als die Vorteile. Denken Sie daran: Code ist nicht unübersichtlich oder überkomplex. Ich kann dort nicht wenige Methoden extrahieren und hier eine abstrakte Klasse einführen. Es ist eher ein Fehler im Design (Ergebnis des extremen "Keep It Stupid Simple", denke ich)

Die Frage kann also auch so gestellt werden:
Ziehen Sie es als Entwickler vor, einen einfachen, dummen, langweiligen Code beizubehalten, ODER haben Sie einige Helfer, die den dummen, langweiligen Code an Ihrem Platz ausführen?

Der Nachteil der letzten Möglichkeit ist, dass Sie einige Dinge lernen müssen und möglicherweise auch den einfachen, dummen, langweiligen Code beibehalten müssen, bis ein vollständiges Refactoring durchgeführt ist.)

Guillaume
quelle
Sehr interessante Frage!
Philippe
1
Es ist per Definition einfach, langweiligen, dummen Code zu pflegen. Ich möchte lieber ein einfaches Leben haben und jeden Tag früh gehen.
quick_now
Ja, aber ich bin zu faul, um langweiligen, dummen Code zu schreiben.
Guillaume
1
Wann wurde dumm oder langweilig leicht verwirrt?
Erik Reppen
Hallo Erik, manchmal ist ein Code, der hätte faktorisiert werden können, einfacher zu lesen: Es ist ein Dutzend Mal dasselbe und der Code ist unkompliziert. Sie können es nacheinander lesen, ohne darüber nachzudenken, und Sie können linear debuggen. Es gibt keine versteckte Komplexität.
Guillaume

Antworten:

42

Refactoring wird am besten in kleinen Schritten durchgeführt, und zwar vorzugsweise nur, wenn Sie Unit-Tests durchgeführt haben, um den Code abzudecken. (Wenn Sie also noch keine Tests haben, versuchen Sie, diese zuerst zu schreiben, und halten Sie sich bis dahin an die einfachsten, narrensichersten, vorzugsweise automatisierten Refactorings. Eine große Hilfe dabei ist das effektive Arbeiten mit Legacy-Code von Michael Feathers.)

Versuchen Sie im Allgemeinen, den Code ein wenig zu verbessern, wenn Sie ihn berühren. Folgen Sie der Pfadfinder-Regel ( geprägt von Robert C. Martin ), indem Sie den Code sauberer lassen, als Sie ihn gefunden haben. Wenn Sie neuen Code hinzufügen, versuchen Sie, ihn vom vorhandenen fehlerhaften Code zu trennen. Vergrabe es zB nicht in der Mitte einer langen Methode, sondern füge einen Aufruf zu einer separaten Methode hinzu und füge deinen neuen Code dort ein. Auf diese Weise können Sie innerhalb der vorhandenen Codebasis schrittweise größere Inseln mit sauberem (er) Code erstellen.

Aktualisieren

Refactoring-Kosten sind schwerer als die Vorteile. [...] Sie als Entwickler bevorzugen es, einen einfachen, dummen, langweiligen Code beizubehalten ODER einige Helfer zu haben, die den dummen, langweiligen Code an Ihrem Platz ausführen?

Ich habe betont, was meiner Meinung nach der entscheidende Punkt ist. Es lohnt sich immer, die Kosten und den Nutzen von Refactoring zu prüfen, bevor wir uns darauf einlassen. Wie in Ihrem Fall verfügen die meisten von uns über begrenzte Ressourcen für die Umgestaltung, sodass wir sie mit Bedacht einsetzen müssen. Verbringen Sie diese kostbare kleine Zeit mit dem Refactoring, wo es mit dem geringsten Aufwand die meisten Vorteile bringt.

Als kreativer Kopf würde ich es natürlich vorziehen, perfekten, schönen und eleganten Code zu produzieren und alles neu zu schreiben, was nicht meinen Idealen entspricht :-) In Wirklichkeit werde ich jedoch dafür bezahlt, Software zu produzieren, die echte Probleme für seine Benutzer löst, also ich sollten darüber nachdenken, auf lange Sicht das beste Preis-Leistungs-Verhältnis zu erzielen.

Der Vorteil des Refactorings wird nur sichtbar, wenn ausreichend Zeit und Aufwand eingespart werden, um den Code langfristig zu verstehen, zu warten, zu reparieren und zu erweitern . Wenn also ein Teil des Codes - so hässlich er auch sein mag - selten oder nie angerührt wird, sind darin keine Fehler bekannt, und ich kenne in absehbarer Zukunft keine Features, die es erforderlich machen würden, ihn anzufassen. Ich ziehe es vor, ihn zu verlassen es in Frieden.

Péter Török
quelle
7
Es ist so einfach, in die Falle zu tappen, dass "der Code schon scheiße ist, kann es auch so weitermachen ..." Gute Programmierer tun das nicht. Gute Antwort.
Sevenseacat
Obwohl dies wahrscheinlich der sicherste Ansatz ist (Code funktioniert dank der Tests garantiert), führt dies dennoch zu dem in der Frage genannten Problem. Ein anderes Muster wird in den Code eingefügt. Im Allgemeinen denke ich, dass Sie versuchen sollten, sich Zeit zu nehmen, um alles auf einmal umzugestalten (wenn Sie TDD machen, am besten mit Zwischenschritten), damit Sie diesen zwischenzeitlichen inkonsistenten Zustand nicht haben. Wenn Sie fertig sind, übergeben Sie Ihren Code an die Quellcodeverwaltung.
Steven Jeuris
2
@Steven, es ist in Ordnung, alles auf einmal umzugestalten, wenn du es dir leisten kannst . In den meisten realen Projekten kann man jedoch nicht einfach alles stoppen und mehrere Tage oder Wochen hintereinander verbringen, um nur eine Umgestaltung vorzunehmen. Auch wenn Sie das Glück haben, einen Manager zu haben, der es unterstützt, muss das Projekt fortgesetzt werden.
Péter Török
1
@Steven, es kommt darauf an - siehe mein Update oben.
Péter Török
1
@ Péter Török: Schönes Update! Perfekte Beschreibung der zu berücksichtigenden Faktoren der realen Welt.
Steven Jeuris
4

Da Sie keine Zeit zum Umgestalten haben und der Code wartbar ist, halten Sie ihn konsistent. Stellen Sie beim nächsten Mal sicher, dass das Refactoring in die Schätzung einbezogen wird.

kirk.burleson
quelle
3

Konsistenz hilft dem nächsten Entwickler nur dann, wenn der umgebende Code in einem guten Zustand ist. Überlegen Sie, wie lange Sie gebraucht haben, um den vorliegenden Code zu verstehen und die richtigen "Erweiterungspunkte" zu finden, um Ihre Änderungen hinzuzufügen. Wenn Sie dem aktuellen Trend folgen, muss der nächste den vorhandenen Code sowie Ihren neuen Code verstehen, wenn er Änderungen vornehmen muss.

Wenn Sie den Code in sinnvolle Funktionen umgestalten, kann der nächste Mitarbeiter leichter nachvollziehen, was gerade passiert, und er muss sich weniger Mühe geben, um seine Änderungen hinzuzufügen. Denk darüber so. Angenommen, der nächste Typ bist du. Was möchten Sie lieber sehen, wenn Sie diesen Codeblock erneut aufrufen, dasselbe Durcheinander, das Sie gerade sehen, oder etwas, das logischer aufgebaut ist?

Michael Brown
quelle
3

Konsistenz hat eine hohe Priorität. Offensichtlich würde jeder, der bei klarem Verstand ist, überall eine elegante DRY-Lösung vorziehen, anstatt überall eine kopierte Boilerplate zu verwenden, aber würden Sie wirklich zwei unterschiedliche Ansätze in derselben Codebasis vorziehen, anstatt eine einheitlich anzuwenden? Was ist, wenn jemand eine noch intelligentere Lösung erfindet und diese auch inkonsistent anwendet? Dann haben Sie drei verschiedene Möglichkeiten, dasselbe zu tun.

Ich habe viel chaotischen Code gesehen, als Entwickler einen "besseren Weg" fanden, etwas zu tun, aber ihn nicht konsistent über eine Codebasis anzuwenden. Wenn es Teil einer geplanten und koordinierten Strategie ist, ein neues Muster im Laufe der Zeit schrittweise anzuwenden, kann dies funktionieren, aber jedes implementierte Muster birgt das Risiko, das Gesamtsystem zu verschlechtern.

Möglicherweise können Sie in kleineren Schritten überlegen, ob Sie das Refactoring durchführen möchten, sodass jeder Schritt auf einmal auf die gesamte Codebasis angewendet werden kann. Z.B. Extrahieren eines kleineren Teils der Kesselplatte zu einer Hilfsfunktion in jeder Iteration. Im Laufe der Zeit landen Sie mit dem ganzen Boilerplate in einer Hilfsklasse. Es mag wirklich hässlich aussehen, weil es nicht entworfen, sondern gewachsen ist, aber Sie können das jetzt beheben, weil Sie den gesamten Code an einem Ort haben.

JacquesB
quelle
+1 "Dann haben Sie drei verschiedene Möglichkeiten, dasselbe zu tun." Ich habe das in jedem Unternehmensprojekt gesehen, an dem ich gearbeitet habe. Ich würde sagen, versuchen Sie nicht einmal eine Umgestaltung, bis Sie den Code durchsucht haben, um sicherzugehen, dass es noch keinen anderen Code gibt, der versucht, sich um den hässlichen Code zu kümmern, für den Sie sich entschieden haben, ihn umzugestalten. Manchmal ist es am besten, sich nur an die Boilerplate-Konvention zu halten, zumindest bis Sie den Code gründlich gelesen haben.
TK-421,
1

Jedes Refactoring, bei dem doppelter Code beseitigt wird, ist ein gutes Refactoring und sollte nur verschoben werden, wenn eine Frist unmittelbar bevorsteht. Die Zeit, die für die einmalige Umgestaltung aufgewendet wurde, kann leicht durch die Zeit ausgeglichen werden, die in zukünftigen Implementierungen gewonnen wurde. Dank des Refactorings sind die inneren Abläufe nicht mehr sichtbar, daher sollte es einfacher zu verstehen sein, nicht schwerer zu folgen.

Meiner Meinung nach ist es ein weit verbreitetes Missverständnis, dass überarbeiteter Code schwerer zu befolgen ist. Dies ist normalerweise ein Argument von Leuten, die nur wissen, was umgestaltet wird, und nicht das umgestaltete Ergebnis. Für Neueinsteiger wird das überarbeitete Ergebnis klarer.

Alle Fehler / Funktionen können zu einem späteren Zeitpunkt an einer zentralen Stelle behoben / implementiert werden und sind automatisch überall in Ihrer Anwendung verfügbar. Dies ist ein großer Gewinn, der normalerweise stark unterschätzt wird. Im Allgemeinen dauert ein vollständiges Refactoring einer Komponente nicht so lange. (Tage statt Monate) Wenn man dies mit der Zeit vergleicht, die durch Fehler verloren gegangen ist, und Code verstehen muss, der überarbeitet werden könnte, werden die Kosten für das Überarbeiten minimal.

Update zu Péter Töröks Antwort: Wird das Refactoring nicht verschoben, "weil es Zeit braucht", erhöht sich die Zeit, es zu einem späteren Zeitpunkt zu refactoring? Refactoring sollte nicht lange dauern, wenn es öfter durchgeführt wird.

Es ist schwierig und eine ganz andere Frage, Ihrem Chef zu erklären, dass Sie einige Tage damit verbringen werden, Code zu schreiben, der dem Produkt nichts hinzufügt. :)

Steven Jeuris
quelle
1
"Es ist schwierig und eine ganz andere Frage, Ihrem Chef zu erklären, dass Sie ein paar Tage damit verbringen werden, Code zu schreiben, der dem Produkt nichts hinzufügt." Netter Versuch ;-) Leider müssen wir das im wirklichen Leben auch lösen. Deshalb ist es praktischer, in kleinen Schritten vorzugehen. Eine halbe Stunde Refactoring kann als Teil einer zweistündigen Aufgabe durchgeführt werden, ohne dass Ihr Manager etwas darüber wissen muss. OTOH zwei volle Tage für Refactoring bleiben selten unbemerkt.
Péter Török
@ Péter Török: Ich habe den Beitrag etwas aktualisiert. Natürlich gibt es immer noch Situationen in der realen Welt, in denen Sie sich nicht die Zeit für das Refactoring nehmen dürfen. Aber ich glaube fest daran, dass es theoretisch immer Zeitgewinn ist. (es sei denn, Sie wissen, dass der Code, an dem Sie arbeiten, in naher Zukunft nicht mehr unterstützt wird)
Steven Jeuris
In der Theorie gibt es keinen großen Unterschied zwischen Praxis und Theorie. In der Praxis ... :-) In der Praxis erhalten Sie möglicherweise nicht immer die Kosten für das Refactoring zurück. Ich habe meine Antwort darauf erweitert.
Péter Török
1
Refactoring, das doppelten Code entfernt, ist nicht immer gut. Es ist möglich, dass zwei Methoden nach den heutigen Geschäftsregeln identisch sind, aber nicht die von morgen. Zum Beispiel AcmeLockerBankkönnte eine eine getRow(int itemIndex)Methode haben, die zurückgibt, index % 5und eine AcmeButtonPanelkönnte eine identische Methode haben, weil sowohl das Schließfach als auch die Schaltflächen die Dinge auf die gleiche Weise nummerieren. Wenn keine der heutigen Schließfachbanken über einen Index von mehr als 1000 verfügt, aber einige Schaltflächen dies tun, und zukünftige Schließfächer einen anderen Zeilenabstand für Indizes im Bereich 1000-1999 verwenden ...
Supercat,
1
... das Hinzufügen des zusätzlichen Verhaltens zu Schließfachbänken ist einfach, wenn Schließfachbänke und Knopfbänke unterschiedliche getRowMethoden haben, kann jedoch schwieriger sein, wenn die Funktionen zu einer gemeinsamen Methode zusammengeführt wurden.
Supercat
0

Können Sie keine neue Schnittstelle / Klasse erstellen, die als Fassade über dem alten Code funktioniert, während Sie Ihren neuen Code in einem eigenen Stil einführen, der leicht erweitert werden kann?

Darren Young
quelle
0

Mach es richtig in die Zukunft. Verwenden Sie Funktionen anstelle von Ausschneiden und Einfügen. Das erfordert kein Refactoring, gibt Ihnen aber den Startschuss für ein künftiges Refactoring.

Andy Lester
quelle
0

Sie als Entwickler bevorzugen es, einen einfachen, dummen, langweiligen Code beizubehalten, ODER möchten einige Helfer haben, die den dummen, langweiligen Code an Ihrem Platz ausführen?

Ich verstehe die überarbeitete Frage nicht. Ich denke, die meisten Leute, wie ich, würden es vorziehen, "dummen, langweiligen Code" nicht beizubehalten. Ich weiß nicht, was du mit Helfer meinst, sorry.

Das Plakat beantwortete ihre eigene Frage, indem es im Moment keine großen Änderungen vornahm. Gute Wahl. Ich habe Probleme mit der Arroganz eines Entwicklers, zu wissen, was für das Geschäft am besten ist. Ein großes Refactoring am Schlauen ... weil du es besser weißt als dein Boss? Jeder fähige Manager kann die Vorteile abwägen.

Wenn Refactoring keine Option ist, wird die Frage eher zu einer Diskussion über die richtige Zeit, den richtigen Ort usw., um dies zu tun. Konsistenz ist sehr wichtig. Doch langlebiger Code profitiert oft von "Erneuerung". Andere haben darüber gesprochen ...


quelle