it-swarm.com.de

Was sind die wichtigsten Punkte für eine effektive Arbeit mit Legacy-Code?

Ich habe das Buch Effektiv mit Legacy-Code arbeiten ein paar Mal empfohlen gesehen. Was sind die wichtigsten Punkte dieses Buches?

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

141
Armand

Das Hauptproblem bei Legacy-Code besteht darin, dass keine Tests vorhanden sind. Sie müssen also einige hinzufügen (und dann noch mehr ...).

Dies an sich würde viel Arbeit kosten, wie @mattnz feststellte. Aber das besondere Problem des Legacy-Codes ist, dass er niemals testbar war . In der Regel handelt es sich also um ein riesiges Durcheinander von Spaghetti-Code, bei dem es sehr schwierig oder absolut unmöglich ist, zu testende Kleinteile zu isolieren. Daher müssen Sie vor dem Unit-Test den Code umgestalten, um ihn testbarer zu machen.

Um jedoch sicher umzugestalten, müssen Sie Unit-Tests durchführen, um sicherzustellen, dass Sie mit Ihren Änderungen nichts kaputt gemacht haben ... Dies ist der Haken 22 des Legacy-Codes.

Das Buch zeigt Ihnen, wie Sie aus diesem Haken ausbrechen können, indem Sie die absolut minimalen und sichersten Änderungen am Code vornehmen, um die ersten Komponententests zu ermöglichen. Diese sollen das Design nicht schöner machen - nur um Unit-Tests zu 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 Unit-Tests 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 nie gedacht hätte, ohne das Buch gelesen zu haben. Noch wichtiger ist jedoch, dass Feathers erklärt, dass was Eine Codeeinheit genau testbar macht. Sie müssen Abhängigkeiten reduzieren und Barrieren in Ihren Code einführen, jedoch aus zwei unterschiedlichen Gründen:

  • Sensing - um die Auswirkungen der Ausführung eines Codeteils zu überprüfen und zu verifizieren, und
  • Trennung - um den spezifischen Code zunächst in ein Testkabel zu bekommen.

Das sichere Schneiden von Abhängigkeiten kann schwierig sein. Das Einführen von Interfaces, Mocks und Dependency Injection ist sauber und als Ziel nett, aber an dieser Stelle nur nicht unbedingt sicher. Daher müssen wir manchmal auf die Unterklasse der zu testenden Klasse zurückgreifen, um eine Methode zu überschreiben, die normalerweise z. Starten Sie eine direkte Anforderung an eine Datenbank. In anderen Fällen müssen wir möglicherweise sogar eine Abhängigkeitsklasse/ein Abhängigkeitsglas durch eine gefälschte in der Testumgebung ersetzen ...

Für mich ist das wichtigste Konzept von Feathers 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 . Das Einfügen von Nähten in Ihren Code ermöglicht Trennen den zu testenden Code, aber es ermöglicht Ihnen auch, zu erfassen das Verhalten des zu testenden Codes, selbst wenn dies der Fall ist schwierig oder unmöglich direkt durchzuführen (z. B. weil der Aufruf Änderungen an einem anderen Objekt oder Subsystem vornimmt, dessen Status nicht direkt aus der Testmethode heraus abgefragt werden kann).

Mit diesem Wissen können Sie die Keime der Testbarkeit im schlimmsten Codehaufen erkennen und die minimalen, am wenigsten störenden und sichersten Änderungen finden, um dorthin zu gelangen. Mit anderen Worten, um zu vermeiden, dass "offensichtliche" Refactorings durchgeführt werden, bei denen die Gefahr besteht, dass der Code beschädigt wird, ohne dass Sie es bemerken - weil Sie nicht noch die Unit-Tests haben, um dies zu erkennen.

168
Péter Török

Schnelle Wege, um die wichtigsten Punkte von Effektives Arbeiten mit Legacy-Code zu ermitteln

104
MarkJ

Ich arbeite an einer Codebasis mit Millionen von Codezeilen, von denen einige aus den 1980er Jahren stammen. Es ist nur Software, es geht also nur darum, ein paar Unit-Tests zu schreiben, damit Sie sie einfach umgestalten und so viel besser machen können.

Das Schlüsselwort hier ist nur - es ist ein Wort aus vier Buchstaben, das nicht in das Vokabular eines Programmierers gehört, geschweige denn eines, das an Legacy-Systemen arbeitet.

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

Wie viel Zeit wird in dieses 20 Jahre alte Legacy-System mit Millionen Zeilen investiert? Nehmen wir an, 20 Entwickler haben 20 Jahre lang 2000 Stunden pro Jahr gearbeitet (sie haben ziemlich hart gearbeitet). Lassen Sie uns nun eine Zahl auswählen - Sie haben neue Computer und neue Werkzeuge und Sie sind so viel schlauer als die Leute, die dieses Stück $% ^^ überhaupt geschrieben haben - sagen wir, Sie sind 10 davon wert. Hast du 40 Mannjahre, na ja, oder?

Die Antwort auf Ihre Frage lautet also, dass es noch viel mehr gibt. 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 Routinen mit 100 Zeilen und ein paar weitere Helfer mit 20 Zeilen umzuwandeln, oder? FALSCH. In diesen 1000 Zeilen sind 100 Fehlerkorrekturen verborgen, von denen jede eine undokumentierte Benutzeranforderung oder einen undurchsichtigen Edge-Fall darstellt. Es sind 1000 Zeilen, weil die ursprüngliche 100-Zeilen-Routine den Job nicht erledigt hat.

Sie müssen mit der Denkweise " wenn es nicht kaputt ist, reparieren Sie es nicht " arbeiten. Wenn es kaputt ist, müssen Sie sehr vorsichtig sein, wenn Sie es reparieren - wenn Sie es verbessern, müssen Sie nicht versehentlich etwas anderes ändern. Beachten Sie, dass "pleite" möglicherweise Code enthält, der nicht gewartet werden kann, 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 es tun, und Sie müssen dem Chef des Chefs sagen, 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, eine Zeitleiste, was auch immer. Wenn Sie nicht - gehen Sie und machen Sie eine. Hör auf, es besser zu machen, wenn das Geld/die Zeit aufgebraucht ist. Fügen Sie eine Funktion hinzu und geben Sie sich Zeit, um sie ein wenig zu verbessern. Beheben Sie einen Fehler - verbringen Sie erneut etwas mehr Zeit und verbessern Sie ihn. Liefern Sie es niemals schlechter als zu Beginn.

41
mattnz

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

  1. Legacy-Code ist jeder Code, der keine Testabdeckung aufweist.
  2. Wann immer Sie alten Code ändern müssen, sollten Sie sicherstellen, dass er abgedeckt ist.

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

20
Michael Brown

In einer Nuss-Shell ist das wahr - das Hinzufügen von Tests und Refactoring ist das, worum es geht.

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

7
Oded