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.)
quelle
Antworten:
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
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.
quelle
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.
quelle
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?
quelle
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.
quelle
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. :)
quelle
AcmeLockerBank
könnte eine einegetRow(int itemIndex)
Methode haben, die zurückgibt,index % 5
und eineAcmeButtonPanel
kö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 ...getRow
Methoden haben, kann jedoch schwieriger sein, wenn die Funktionen zu einer gemeinsamen Methode zusammengeführt wurden.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?
quelle
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.
quelle
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