Was sind die wichtigsten Punkte beim effektiven Arbeiten mit Legacy-Code? [geschlossen]

133

Ich habe das Buch "Effektiv mit Legacy-Code arbeiten" einige Male empfohlen. Was sind die wichtigsten Punkte dieses Buches?

Gibt es viel mehr, um mit altem Code umzugehen, als Unit- / Integrationstests hinzuzufügen und dann umzugestalten?

Armand
quelle
2
Natürlich geht es darum, Tests hinzuzufügen und dann umzugestalten. In diesem Buch geht es hauptsächlich darum, wie Sie es schaffen, einen unmöglich gefalteten Code zu testen, und in diesem Punkt gibt es eine Menge Augenöffner. Sagen wir einfach, dass Feathers keine Gefangenen macht!
Kilian Foth
9
Vielleicht solltest du einfach das Buch lesen
HLGEM
Schöne Bewertung hier: andreaangella.com/2014/03/…
rohancragg

Antworten:

157

Das Hauptproblem mit Legacy-Code ist, dass es keine Tests gibt. Sie müssen also einige hinzufügen (und dann noch mehr ...).

Dies an sich würde, wie @mattnz feststellte, eine Menge Arbeit kosten. Aber das besondere Problem des Legacy - Code ist , dass es nie testbar wurde entwickelt . In der Regel handelt es sich also um ein gewaltiges Durcheinander von Spaghetti-Code, bei dem es sehr schwierig oder gar nicht möglich ist, zu prüfende Kleinteile zu isolieren. Daher müssen Sie den Code vor dem Unit-Test überarbeiten , um ihn testbarer zu machen.

Um jedoch sicher umgestalten zu können, müssen Sie Unit-Tests durchführen, um sicherzustellen, dass Sie mit Ihren Änderungen nichts angestellt haben ... Dies ist der Haken 22 des Legacy-Codes.

Das Buch zeigt Ihnen, wie Sie aus diesem Haken ausbrechen, indem Sie die absolut minimalen und sichersten Änderungen am Code vornehmen, nur um die ersten Komponententests zu ermöglichen. Diese sollen das Design nicht schöner machen, sondern nur Unit-Tests ermöglichen. In der Tat machen sie manchmal das Design hässlicher oder komplexer. Mit ihnen können Sie jedoch Tests schreiben - und sobald Sie Komponententests durchgeführt haben, können Sie das Design verbessern.

Es gibt viele Tricks, um den Code testbar zu machen - einige sind offensichtlich, andere überhaupt nicht. Es gibt Methoden, an die ich niemals gedacht hätte, ohne das Buch zu lesen. Noch wichtiger ist jedoch, dass Feathers erklärt, was eine Code-Einheit genau testbar macht. Sie müssen Abhängigkeiten reduzieren und Barrieren in Ihren Code einführen, jedoch aus zwei verschiedenen Gründen:

  • Erkennen - um die Auswirkungen der Ausführung eines Codes zu überprüfen und zu verifizieren, und
  • Trennung - um das spezifische Stück Code zunächst in ein Testgeschirr zu bekommen.

Das sichere Trennen von Abhängigkeiten kann schwierig sein. Das Einführen von Interfaces, Mocks und Dependency Injection ist ein sauberes und ansprechendes Ziel, das zu diesem Zeitpunkt jedoch nicht unbedingt sicher ist. Daher müssen wir manchmal auf die Unterklasse der getesteten Klasse zurückgreifen, um eine Methode zu überschreiben, die normalerweise z. B. eine direkte Anforderung an einen DB startet. In anderen Fällen müssen wir möglicherweise sogar eine Abhängigkeitsklasse / jar in der Testumgebung durch eine gefälschte ersetzen ...

Das wichtigste Konzept von Feathers sind für mich die Nähte . Eine Naht ist eine Stelle im Code, an der Sie das Verhalten Ihres Programms ändern können, ohne den Code selbst zu ändern . Nähte in Ihr Code - Aufbau ermöglicht trennt das Stück im Test befindlichen Code, aber es ermöglicht Ihnen auch zu spüren , das Verhalten des Codes im Test auch dann , wenn es schwierig oder unmöglich ist , direkt zu tun (zB weil der Anruf tätigt Änderungen in einem anderen Objekt oder Subsystem , deren Status nicht direkt aus der Testmethode heraus abgefragt werden kann).

Mit diesem Wissen können Sie die Keime der Testbarkeit im schlimmsten Haufen Code erkennen und die minimalen, am wenigsten störenden und sichersten Änderungen finden, um dahin zu gelangen. Mit anderen Worten, zu vermeiden „offensichtlich“ Refactorings zu machen , die ein Risiko des Brechens des Codes haben , ohne dass Sie es merken - weil Sie nicht noch die Unit - Tests haben , dass zu erkennen.

Péter Török
quelle
5
Wenn in der obigen Antwort "Komponententests" steht, bedeutet dies "automatisierte Tests" . Bei einer älteren App handelt es sich bei einem großen Teil der anfänglich nützlichen automatisierten Tests tatsächlich um Integrationstests (bei denen die Testlogik einen größeren Teil des Gesamtcodes ausführt und Fehler aufgrund von Fehlern an vielen verschiedenen Stellen verursachen kann) und nicht um echte Einheiten Tests (die darauf abzielen, nur ein Modul zu analysieren und jeweils weitaus kleinere Teile des Codes auszuführen).
Lutz Prechelt
99

Schnelle Möglichkeiten, um die wichtigsten Punkte des effektiven Arbeitens mit Legacy-Code zu erreichen

MarkJ
quelle
3
Der MP3-Link auf dieser Hanselminutes-Seite ist defekt, der auf hanselminutes.com/165/… jedoch nicht - s3.amazonaws.com/hanselminutes/hanselminutes_0165.mp3 .
Peter Mortensen
Vielen Dank, Rosston, für die Korrektur des PDF-Links. Sieht so aus, als wäre objectmentor.com verschwunden - vielleicht hat "Onkel Bob" das Geschäft eingestellt?
MarkJ
Ich bin mir nicht sicher, was mit dem Objekt-Mentor passiert ist, aber heutzutage arbeitet Onkel Bob für 7th Light.
Jules
40

Ich arbeite auf einer Codebasis von Millionen von Codezeilen, von denen einige aus den 1980er Jahren stammen. Es ist nur Software, also müssen Sie nur ein paar Unit-Tests schreiben, damit Sie es überarbeiten und so viel besser machen können.

Das Schlüsselwort hier ist einfach - es ist ein aus vier Buchstaben bestehendes Wort, das zu keinem Programmierer-Vokabular gehört, geschweige denn zu einem, der an Legacy-Systemen arbeitet.

Wie lange dauert es Ihrer Meinung nach, einen Komponententest zu schreiben, um den Entwicklungsaufwand von einer Stunde zu testen? Sagen wir zur Diskussion noch eine Stunde.

Wie viel Zeit wird in dieses 20 Jahre alte Legacy-System mit einer Million Leitungen investiert? Sagen wir 20 Entwickler für 20 Jahre mal 2000 Stunden / Jahr (sie haben ziemlich hart gearbeitet). Lassen Sie uns jetzt eine Zahl auswählen - Sie haben neue Computer und neue Werkzeuge und Sie sind so viel schlauer als die Leute, die dieses Stück von $% ^^ geschrieben haben - sagen wir, Sie sind 10 von ihnen wert. Hast du 40 Mannjahre, oder ...?

Die Antwort auf Ihre Frage lautet also: Es gibt noch viel mehr. Zum Beispiel ist diese Routine, die 1000 Zeilen umfasst (ich habe einige, die über 5000 sind), übermäßig komplex und ein Stück Spaghetti. Es würde nur ein paar Tage dauern (noch ein Wort mit vier Buchstaben), um es in ein paar 100 Zeilen Routinen und ein paar weitere 20 Zeilen Helfer zu zerlegen, oder? FALSCH. In diesen 1000 Zeilen sind 100 Fehlerkorrekturen verborgen, von denen jede eine undokumentierte Benutzeranforderung oder einen dunklen Randfall darstellt. Es sind 1000 Zeilen, weil die ursprüngliche 100-Zeilen-Routine den Job nicht erledigt hat.

Sie müssen mit der Einstellung arbeiten, " wenn es nicht kaputt ist, reparieren Sie es nicht ". Wenn es kaputt ist, müssen Sie sehr vorsichtig sein, wenn Sie es reparieren - während Sie es verbessern, ändern Sie nicht versehentlich etwas anderes. Beachten Sie, dass "pleite" möglicherweise Code enthält, der nicht verwaltbar ist, aber ordnungsgemäß funktioniert. Dies hängt vom System und seiner Verwendung ab. Fragen Sie "Was passiert, wenn ich das vermassle und es noch schlimmer mache?", Denn eines Tages werden Sie dem Chef der Bosse sagen müssen, warum Sie sich dafür entschieden haben.

Diese Systeme können immer besser gemacht werden. Sie haben ein Budget, an dem Sie arbeiten können, einen Zeitplan, was auch immer. Wenn Sie nicht - gehen Sie und machen Sie eine. Hör auf, es besser zu machen, wenn das Geld / die Zeit abgelaufen ist. Fügen Sie ein Feature hinzu, und lassen Sie sich Zeit, um es ein wenig zu verbessern. Beheben Sie einen Fehler - noch einmal, nehmen Sie sich etwas mehr Zeit und verbessern Sie ihn. Liefern Sie es niemals schlechter als zu Beginn.

mattnz
quelle
2
danke für die Tipps! Sind das deine oder aus dem Buch?
Armand
3
Wahrscheinlich ein bisschen von beidem - ich habe das Buch nach ein paar Jahren gelesen und sollte es wahrscheinlich noch einmal lesen. Wie in jedem guten Buch können Sie damit einen Teil Ihrer aktuellen Aktivitäten ändern, den größten Teil Ihrer Aktivitäten noch einmal durchsetzen, haben aber nicht alle Antworten auf Ihre spezifischen Probleme.
Mattnz
7
"Es ist 1000 Zeilen, weil die ursprüngliche 100-Zeilen-Routine nicht den Job gemacht hat." Dies scheint also sehr selten der Fall zu sein. Meistens sind es 1.000 Zeilen, nur weil der ursprüngliche Entwickler die Ärmel hochgekrempelt hat und mit dem Programmieren begonnen hat, bevor er auch nur einen Moment für die Planung oder das Design gespart hat.
Stephen Touset
3
Nein. Ich sage, dass in den meisten Fällen (denen ich persönlich begegnet bin) 1.000 Zeilenroutinen ein klares Indiz dafür sind, dass die Leute angefangen haben, Code zu schreiben, bevor sie darüber nachgedacht haben, wie sie eine richtige Abstraktion schreiben sollen. Tausend-Zeilen-Routinen sind per Definition zu kompliziert - sagen Sie, dass eine Tausend-Zeilen-Routine mit Hunderten von versteckten, unkommentierten Bugfixes das Markenzeichen eines verantwortlichen Entwicklers ist?
Stephen Touset
16
Wenn Sie an jeden Beitrag auf dieser Website geglaubt haben, muss sich jeder mit 1000 Zeilen Spaghetti-Code auseinandersetzen, aber niemand hat ihn jemals geschrieben. Nach meiner Erfahrung sind 1000 (und 10000) Linienroutinen das Markenzeichen von Entwicklern, die mit dem, was sie haben, ihr Bestes geben, um das zu liefern, was der Chef von ihnen verlangt, der ihren Lohn zahlt. Ich finde es beleidigend und arrogant, dass sich so viele Entwickler frei fühlen, ohne Kenntnis der Umstände von der Seitenlinie aus Kommentare abzugeben, ohne ihre eigene Arbeit der Community zur Kritik stellen zu müssen.
Mattnz
19

Es gibt zwei wichtige Punkte, die aus dem Buch entfernt werden sollten.

  1. Legacy-Code ist ein Code ohne Testabdeckung.
  2. Wann immer Sie den Legacy-Code ändern müssen, sollten Sie sicherstellen, dass er abgedeckt ist.

Wie andere Antwortende bereits betont haben, ist der Versuch, Ihren vorhandenen Legacy-Code vorzeitig zu aktualisieren, ein Kinderspiel . Nehmen Sie sich stattdessen immer dann Zeit, wenn Sie Änderungen am Legacy-Code vornehmen müssen (für eine neue Funktion oder eine Fehlerbehebung), um den Legacy-Status zu entfernen.

Michael Brown
quelle
6
+1 Hervorragender Punkt: "Nehmen Sie sich immer Zeit, wenn Sie Änderungen am Legacy-Code vornehmen müssen, um den Legacy-Status zu entfernen."
John
3
Entfernen Legacy-Status, bekomme meine Stimme :)
Rachel
7

Kurz gesagt, das stimmt - das Hinzufügen von Tests und Refactoring ist das, worum es geht.

Aber das Buch bietet Ihnen viele verschiedene Techniken, um dies mit Code zu tun, der nur sehr schwer zu testen und sicher umzugestalten ist.

Oded
quelle