Ich habe eine Methodensignatur geändert und habe jetzt über 25.000 Fehler. Was jetzt?

166

Ich habe vor kurzem einen neuen Job angefangen, bei dem ich an einer sehr großen Anwendung arbeite (15M loc). In meinem vorherigen Job hatten wir eine ähnlich große Anwendung, aber (im positiven oder im negativen Sinne) verwendeten wir OSGi, was bedeutete, dass die Anwendung in viele Mikrodienste unterteilt war, die unabhängig voneinander geändert, kompiliert und bereitgestellt werden konnten. Die neue Anwendung ist nur eine große Codebasis mit möglicherweise ein paar DLLs.

Also muss ich das Interface dieser Klasse ändern, weil mein Chef mich darum gebeten hat. Sie haben es anfangs mit einigen Annahmen geschrieben, die sich nicht allzu gut verallgemeinern ließen, und eine Weile haben sie das Problem des Refactoring vermieden, weil es so eng miteinander verbunden ist. Ich habe die Benutzeroberfläche geändert und jetzt gibt es über 25000 Fehler. Einige der Fehler sind in Klassen mit wichtigen klingenden Namen wie "XYZPriceCalculator" die reaaallysollte nicht brechen. Ich kann die Anwendung jedoch nicht starten, um zu überprüfen, ob sie funktioniert, bis alle Fehler behoben sind. Viele der Unit-Tests verweisen entweder direkt auf diese Schnittstelle oder sind an Basisklassen gekoppelt, die auf diese Schnittstelle verweisen. Daher ist es eine ziemlich große Aufgabe, diese zu beheben. Außerdem weiß ich nicht wirklich, wie all diese Teile zusammenpassen, und selbst wenn ich anfangen könnte, weiß ich nicht wirklich, wie es aussehen würde, wenn die Dinge kaputt wären.

Bei meinem letzten Job war ich noch nie mit einem solchen Problem konfrontiert. Was mache ich?

user788497
quelle
7
Sie müssen uns mehr Informationen über die Art der Fehler geben und was "diese Klasse" ist, wir haben nichts dagegen, Leser.
Whatsisname
137
"Über 25000 Fehler" solche in VS angezeigten Zahlen sind oft falsch. Es gibt ein paar Fehler, aber wenn der Build einer häufig verwendeten DLL kaputt geht, schlagen auch andere Builds fehl, was zu astronomischen Fehlern führt. Ich beginne immer mit der ersten Fehlermeldung in der Build-Ausgabe, nicht in der Fehlerliste.
Bernhard Hiller
13
Ich würde gerne die Vorher- und Nachher-Signaturen der von Ihnen geänderten Methode sehen. Übrigens - 25k-Fehler klingen nicht wirklich nach zu vielen, um damit fertig zu werden. Langweilig ja, entmutigend, ja, unüberschaubar, nein.
Jmoreno
46
Eine öffentliche Schnittstelle ist ein Vertrag. Brich solche Verträge nicht - erstelle neue.
Matthew Read
6
25000 Fehler !? Houston, wir haben ein Problem. Machen Sie die Änderung auf jeden Fall rückgängig und sprechen Sie mit Ihrem Manager, und erklären Sie ihm, dass Sie möglicherweise eine neue Benutzeroberfläche erstellen müssen.
Code Whisperer

Antworten:

349

25000 Fehler bedeuten im Grunde genommen "Fass das nicht an". Ändere es zurück. Erstellen Sie eine neue Klasse mit der gewünschten Schnittstelle und verschieben Sie die Konsumenten der Klasse langsam auf die neue. Abhängig von der Sprache können Sie die alte Klasse als veraltet markieren, was möglicherweise alle möglichen Compiler-Warnungen auslöst, Ihren Build jedoch nicht beschädigt.

Leider passieren diese Dinge in älteren Codebasen. Es gibt nicht viel, was Sie dagegen tun können, außer die Dinge langsam zu verbessern. Stellen Sie beim Erstellen der neuen Klassen sicher, dass Sie sie ordnungsgemäß testen und mit SOLID-Prinzipien erstellen, damit sie in Zukunft leichter geändert werden können.

Stephen
quelle
79
Es muss nicht unbedingt eine neue Klasse sein . Je nach Sprache und Umständen kann es sich um eine Funktion, eine Schnittstelle, ein Merkmal usw. handeln.
Jan Hudec
33
Es hilft auch, wenn die alte Schnittstelle durch einen Kompatibilitätswrapper um die neue ersetzt werden kann.
Jan Hudec
79
Manchmal bedeuten 25000 Fehler tatsächlich, dass wir es nie gewagt haben, das zu berühren, aber jetzt, da ein Neuling eingetroffen ist, geben wir ihm die Aufgabe, die Ställe im August zu säubern.
Mouviciel
13
@theDmi: Ich stimme zu, 1 Änderung und 25.000 Fehler bedeuten höchstwahrscheinlich höchstens 2.5.000 Änderungen, und ich wäre nicht überrascht, wenn ich feststellen würde, dass es sich um 250 handelt. Viel Arbeit in beide Richtungen, aber machbar.
Jmoreno
33
Diese 25000 Fehler können möglicherweise alle durch eine einzige Änderung behoben werden. Wenn ich die Basisklasse einer riesigen Heirarchie unterbreche, gibt jede der abgeleiteten Klassen Fehler über ungültige Basisklassen aus, jede Verwendung dieser Klassen gibt Fehler über die nicht vorhandene Klasse aus usw. Stellen Sie sich vor, es wäre "getName", und ich fügte hinzu ein Argument. Das Überschreiben in der Implementierungsklasse "HasAName" funktioniert jetzt nicht (Fehler) und alles , was daraus erbt, erzeugt jetzt Fehler (alle 1000 Klassen) sowie jedes Mal, wenn ich eine Instanz von einer von ihnen erstelle (24x pro Klasse) Durchschnittlich). Das Update ist ... eine Zeile.
Yakk
80

Teile und erobere mit Refactorings

Oft hilft es, die Änderungen, die Sie vornehmen müssen, in kleinere Schritte aufzuteilen, da Sie dann die meisten kleineren Schritte so ausführen können, dass die Software überhaupt nicht beschädigt wird. Refactoring-Tools helfen bei solchen Aufgaben sehr.

Teilen

Identifizieren Sie zunächst die kleinstmöglichen Änderungen (in Bezug auf logische Änderungen, nicht in Bezug auf geänderte LoC), die sich zu der Änderung summieren, die Sie erreichen möchten. Versuchen Sie insbesondere, Schritte zu isolieren, die reine Refactorings sind und von Werkzeugen ausgeführt werden können.

Erobern

In komplizierten Fällen wie Ihrem kann es sinnvoll sein, jeweils ein kleines Refactoring durchzuführen und das Problem dann zu beheben, damit alle Systeme für die kontinuierliche Integration die Änderung überprüfen können. Vielleicht hat sich auch das Testteam darum gekümmert. Dadurch werden die von Ihnen ausgeführten Schritte überprüft.

Um ein bestimmtes Refactoring durchführen zu können, benötigen Sie unbedingt Tool-Unterstützung für einen Fall, in dem Sie 25.000 Aufrufseiten der zu ändernden Methode haben. Vielleicht funktioniert das Suchen und Ersetzen auch, aber für einen so kritischen Fall hätte ich Angst davor.

Beispiel

In C # ist es beispielsweise möglich, mit Resharper die Signatur einer Methode zu ändern . Wenn die Änderung einfach genug ist, z. B. das Hinzufügen eines neuen Parameters, können Sie angeben, welcher Wert an Aufrufstandorten verwendet werden soll, an denen andernfalls ein Kompilierungsfehler auftreten würde.

Sie haben dann sofort eine fehlerfreie Codebasis und können alle Unit-Tests durchführen, die bestehen bleiben, da es sich nur um ein Refactoring handelte.

Sobald die Signatur der Methode gut aussieht, können Sie die Werte ersetzen, die Resharper als Argumente für den neu eingeführten Parameter hinzugefügt hat. Dies ist kein Refactoring mehr, aber Sie haben eine fehlerfreie Codebasis und können die Tests nach jeder Zeile, die Sie ändern, ausführen.

Manchmal klappt das nicht

Dies ist ein sehr nützlicher Ansatz für Fälle wie Ihren, in denen Sie viele Anrufseiten haben. Und Sie haben jetzt eine funktionierende Software, so dass es möglich sein kann, kleine Umgestaltungsschritte durchzuführen, um die Signatur nur ein wenig zu ändern, und dann noch einen zu machen.

Leider funktioniert es nicht, wenn die Signaturänderung zu komplex ist und nicht in kleinere Änderungen unterteilt werden kann. Das ist aber selten; das Problem in kleinere Probleme Spaltung in der Regel zeigt , dass es ist möglich.

theDmi
quelle
12
Diese. Refactor, wenn Sie können (sicher), sonst benötigen Sie eine ordnungsgemäße Migration.
sleske
3
Und für alle Fälle sollten Sie die integrierten Refactoring-Tools Ihrer IDE verwenden, anstatt nur die Signatur der (z. B.) -Methode lokal zu ändern und dann die daraus resultierenden Fehler zu beheben.
KlaymenDK
36

Klären Sie Ihre Aufgabe mit Ihrem Chef, damit dieser das Problem und Ihre Bedürfnisse als professioneller Softwareentwickler versteht.

Wenn Sie Teil eines Teams sind, suchen Sie den Hauptentwickler und fragen Sie ihn um Rat.

Viel Glück.

mmehl
quelle
15
Dies ist der erste Schritt, den ich machen würde - "Ich bin ein Junior und mein Chef hat mir gesagt, dass ich etwas tun soll und jetzt bekomme ich eine wirklich große Fehlermeldung, aber mein Chef hat mir nichts davon erzählt." Schritt 1: "Hey Boss, ich habe das Ding gemacht, aber jetzt bekomme ich 25.000 Fehler. Soll das passieren oder ..."
Pimgd
28

Fass es nicht an. Mach nichts.

Setzen Sie sich stattdessen auf Ihren Stuhl und rufen Sie "Heeeeelp !!!!!" so laut du kannst.

Nun, nicht genau so, aber fragen Sie einen Ihrer älteren Kollegen um Rat. Wenn Sie 25.000 Fehler haben, beheben Sie die Fehler nicht, sondern die Fehlerursachen. Und ein leitender Kollege sollte Sie beraten können, wie Sie die von Ihrem Chef gewünschten Änderungen vornehmen können, ohne dass 25.000 Fehler auftreten. Es gibt verschiedene Möglichkeiten, dies zu tun, aber was ein guter Weg ist, hängt von Ihrer spezifischen Situation ab.

Und es könnte sein, dass der Chef Ihren älteren Kollegen befohlen hat, die gleiche Änderung vorzunehmen, und sie sagten "Nein". Weil sie wussten, was passieren würde. Deshalb haben Sie den Job bekommen.

gnasher729
quelle
2
Dies ist auf jeden Fall eine wichtige Sache zu beachten. Wenn ein neuer Mitarbeiter in hohem Maße ehrgeizig ist, ist er möglicherweise fleißig (leichtgläubig) genug, um die wirklich große Aufgabe zu erledigen, die letztendlich nur einen 5-Byte-Speichervorteil bringt, oder logischer zu rekodieren und später zu warten.
The Great Duck
@TheGreatDuck: Sag mir, dass du noch nie eine Schnittstelle gesehen hast, die überall verwendet wird und überall falsch ist. Ich habe es sicher.
Joshua
@ Joshua, das ist nicht einmal relevant für das, was ich gerade gesagt habe. Es gibt Zeiten, in denen das Beheben eines kleinen Fehlers nicht immer die klügste Idee ist. Dazu müssen mehr als 10.000 Codezeilen neu geschrieben werden. Leider ist ein neuer Mitarbeiter möglicherweise leichtgläubig genug, um 10 Nachtschwärmer von der Arbeit abzuhalten, die diesen Code umschreiben, um ihren Chef zu beeindrucken und zu erledigen. Sicher, es ist eine großartige Sache, aber manchmal ist genug genug. Sie müssen nur die Existenz des Fehlers akzeptieren.
Die große Ente
1
@Joshua Übrigens, ich bin nur dieser Community beigetreten, weil diese Frage in meinem beliebten Fragen-Feed auftauchte. Ich habe keine Erfahrung mit großflächigem Design wie diesem. Ich stimmte nur der Ansicht dieser Person zu.
Die große Ente
22

Verankerte APIs können nicht einfach geändert werden. Wenn Sie sie wirklich ändern müssen, müssen Sie sie als veraltet dokumentieren (mit welchen Mitteln auch immer die Sprache dies zulässt) und dokumentieren, welche API stattdessen verwendet werden soll. Die alte API kann dann langsam auslaufen ... möglicherweise sehr langsam, abhängig von Ihrem Zeitbudget für das Refactoring.

Kevin Krumwiede
quelle
10

Bewerten

Prüfen Sie, ob diese Änderung erforderlich ist oder ob Sie eine neue Methode hinzufügen und die andere ablehnen können.

Nach vorne

Wenn ein Wechsel notwendig ist; dann ist ein Migrationsplan notwendig.

Der erste Schritt besteht darin, die neue Methode einzuführen und die Argumente der alten Methode zu massieren, damit sie die neue aufrufen kann. Möglicherweise müssen einige Dinge hartcodiert werden. das ist gut.

Dies ist ein Festschreibungspunkt: Überprüfen Sie, ob alle Tests bestanden, festgeschrieben oder übertragen wurden.

Wandern

Die beschäftigte Arbeit migriert alle Aufrufer der alten Methode auf die neue. Zum Glück kann es dank des Spediteurs schrittweise erfolgen.

Also mach weiter; Zögern Sie nicht, Hilfsmittel zu verwenden (da sedes die grundlegendsten sind, gibt es andere).

Markieren Sie die alte Methode als veraltet (mit einem Hinweis auf die neue Methode). Es wird Ihnen helfen, festzustellen, ob Sie etwas vergessen haben, und es wird Ihnen helfen, wenn ein Mitarbeiter die alte Methode aufruft, während Sie daran arbeiten.

Dies ist ein Festschreibungspunkt (oder mehrere Festschreibungspunkte): Überprüfen Sie, ob alle Tests bestanden, festgeschrieben oder übertragen wurden.

Entfernen

Nachdem einige Zeit vergangen ist (vielleicht nur ein Tag), entfernen Sie einfach die alte Methode.

Matthieu M.
quelle
4
sedist wahrscheinlich eine schlechte Idee ... Etwas, das die Sprache "versteht" und keine unbeabsichtigten drastischen Änderungen vornimmt, ist besser.
wizzwizz4
1
@ wizzwizz4: Leider habe ich nur sehr wenige Tools gefunden, die die Sprache tatsächlich gut genug für C ++ verstehen . Die meisten Tools scheinen für das Umbenennen geeignet zu sein, und das war's. Zugegeben, nur die genauen Methodenaufrufe (und keine überladenen oder nicht verwandten, aber ähnlich benannten Methodenaufrufe) umzubenennen, ist bereits beeindruckend, aber für etwas Komplizierteres nicht ausreichend. Zumindest müssten Sie die Fähigkeit haben, (1) Argumente zu mischen, (2) eine Transformation auf ein gegebenes Argument anzuwenden ( .c_str()zum Beispiel einen Aufruf ) und neue Argumente einzuführen. sedirgendwie funktioniert, fängt der Compiler seine Probleme danach.
Matthieu M.
1
sed(oder ed) kann für diese Art von Dingen angemessen sein - vorausgesetzt, Sie überprüfen den Diff vor dem Festschreiben ordnungsgemäß.
Toby Speight
Das ist der TCRR von HTML, ja? :)
Daniel Springer
8

Wenn Ihre Änderung an der Methodensignatur lediglich eine Namensänderung ist, können Sie die Änderung in den 25.000 Klassen, die auf die betreffende Methode verweisen, mithilfe von Tools automatisieren.

Ich gehe davon aus, dass Sie den Code einfach manuell bearbeitet haben, was zu allen Fehlern geführt hat. Ich gehe auch davon aus, dass Sie mit Java vertraut sind (siehe Ihren Verweis auf OSGi). In Eclipse (ich weiß nicht, welche Programmierumgebung Sie verwenden, aber in anderen Umgebungen gibt es ähnliche Refactoring-Tools) können Sie also "Refactoring -> Umbenennen" verwenden. um alle Verweise auf die Methode zu aktualisieren, die Sie ohne Fehler verlassen sollten.

Falls Sie andere Änderungen an der Methodensignatur vornehmen, als nur umzubenennen (Ändern der Anzahl oder der Arten von Parametern), können Sie "Refactoring -> Methodensignatur ändern" verwenden. Es besteht jedoch die Möglichkeit, dass Sie vorsichtiger sein müssen, wie die anderen Antworten nahelegen. Unabhängig von der Art der Änderung kann es auch noch eine ziemliche Aufgabe sein, all diese Änderungen in einer ausgelasteten Codebasis durchzuführen.

MikkelRJ
quelle
2
OP sagte speziell, dass OSGi bei ihrem vorherigen Job war, also ist es hier nicht wirklich relevant.
ein Lebenslauf vom
3
@ MichaelKjörling Wenn das OP in seinem vorherigen Job ein Java-Programmierer war, besteht die Möglichkeit, dass sie auch in diesem Job ein Java-Programmierer sind.
Rich
@ MichaelKjörling Ich wollte eine konkrete Empfehlung geben, Eclipse für das Refactoring zu verwenden, da OP mit Java vertraut ist. Ob OP ​​tatsächlich Java für das aktuelle Projekt verwendet, ist weniger wichtig, aber ich sollte meine Antwort klarstellen. Vielen Dank.
MikkelRJ
6

Hier mein Beitrag.

Ich habe vor kurzem einen neuen Job begonnen, bei dem ich an einer sehr großen Anwendung arbeite (15 Millionen Codezeilen).

Sie kennen das Projekt und seine "Features" wahrscheinlich nicht. Bevor Sie eine einzelne Codezeile eingeben, müssen Sie mit dem Projekt vertraut sein. Machen Sie also Ihre Änderungen rückgängig und analysieren Sie zunächst den Code . (Zumindest der Betroffene)

Wenn Sie die vorhandene Lösung verstehen, erhalten Sie eine bessere Übersicht darüber, wo Sie sich befinden. Stellen Sie die Lösung und ihre Bedeutung in einen Kontext.

Wie @Greg hervorhob, sollten Sie in der Lage sein, den vorhandenen Code zu testen, um eine gültige Referenz zum Vergleich zu erhalten (Regressionstests). Ihre Lösung sollte in der Lage sein, dieselben Ergebnisse wie die vorhandene Lösung zu erzielen . Zu diesem Zeitpunkt haben Sie es egal , ob die Ergebnisse stimmen . Das erste Ziel ist die Umgestaltung und nicht die Behebung von Fehlern. Wenn die vorhandene Lösung "2 + 2 = 42" anzeigt, sollte dies auch Ihre Lösung sein. Wenn es keine Ausnahmen gibt, sollten Sie es auch nicht tun. Wenn es Nullen zurückgibt, sollte Ihr auch Nullen zurückgeben. Und so weiter. Andernfalls gefährden Sie 25.000 Codezeilen.

Dies dient der Nachrüstbarkeit.

Warum? Denn gerade jetzt ist es Ihre einzigartige Garantie für einen erfolgreichen Refactor.

Viele der Unit-Tests verweisen entweder direkt auf diese Schnittstelle oder sind an Basisklassen gekoppelt, die auf diese Schnittstelle verweisen.

Eine Möglichkeit, die Nachrüstbarkeit zu gewährleisten, ist für Sie dringend erforderlich. Hier also Ihre erste Herausforderung. Isolieren Sie die Komponente für den Komponententest.

Denken Sie daran, dass diese 25.000 Codezeilen unter der Annahme der möglichen Ergebnisse des vorhandenen Codes erstellt wurden. Wenn Sie diesen Teil des Vertrags nicht brechen, sind Sie auf halbem Weg zur endgültigen Lösung. Wenn du das tust, gut: Möge die Macht mit dir sein

Wenn Sie den neuen "Vertrag" entworfen und implementiert haben, ersetzen Sie den alten. Verwerfe es oder nimm es raus.

Ich habe vorgeschlagen, Fehler in Ruhe zu lassen, da das Refactoring und das Beheben von Fehlern unterschiedliche Aufgaben sind. Wenn Sie versuchen, sie gemeinsam voranzutreiben, schlagen Sie möglicherweise bei beiden fehl. Sie könnten denken, Sie hätten Fehler gefunden, diese könnten jedoch "Merkmale" sein. Also lass sie in Ruhe (für eine Minute).

25.000 Codezeilen scheinen mir genug Probleme zu sein, um mich auf nur eine Aufgabe zu konzentrieren.

Sobald Ihre erste Aufgabe erledigt ist. Zeigen Sie Ihrem Chef diese Bugs / Features auf.

Schließlich, wie @Stephen gesagt hat:

Es gibt nicht viel, was Sie dagegen tun können, außer die Dinge langsam zu verbessern. Stellen Sie beim Erstellen der neuen Klassen sicher, dass Sie sie ordnungsgemäß testen und mit SOLID-Prinzipien erstellen, damit sie in Zukunft leichter geändert werden können

Laiv
quelle
5

Probier es aus.

Alle anderen empfehlen die Umgestaltung, damit die Auswirkungen gering sind. Aber mit so vielen Fehlern haben Sie, selbst wenn es Ihnen gelingt, mit nur 10 Codezeilen umzugestalten (was Sie wahrscheinlich können), 25.000 Code-Flows beeinflusst , auch wenn Sie sie nicht neu schreiben mussten.

Als Nächstes müssen Sie sicherstellen, dass Ihre Regressionstestsuite mit Bravour bestanden wird. Und wenn Sie keine haben, dann machen Sie eine, die es will. Das Hinzufügen einer umfassenden Regressionstestsuite zu Ihrem monolithischen Projekt klingt langweilig, ist jedoch eine gute Möglichkeit, das Vertrauen in Release-Kandidaten zu erhöhen und sie schneller freizugeben, wenn die Suite gut automatisiert ist.

Greg
quelle