Seite 1 von 1
Umgang mit grausigen Codebasen
Verfasst: Mittwoch 4. Mai 2011, 23:59
von Dauerbaustelle
Wie geht ihr mit der Situtation um, mit einer Codebasis arbeiten zu müssen, von der man am liebsten 95% neu schreiben würde? Und gar nicht so viel essen kann, wie man beim Anblick kotzen möchte? Die dazu noch keine Tests hat, Refactoring also unmöglich macht?
Um die Sache nicht zu einfach zu machen ist für'n Rewrite natürlich keine Zeit... ;-) Scheint mir ja das typische Softwarebusinessproblem zu sein.
Mir-doch-alles-egal-ich-krieg'-mein-Geld-Haltung ist auch ausgeschlossen. Das erlaubt der Schöncodenazi in mir nicht.
Überlebenshilfe jeglicher Art willkommen ;)
Re: Umgang mit grausigen Codebasen
Verfasst: Donnerstag 5. Mai 2011, 00:34
von derdon
Gegen 95% neu schreiben spricht ein Zeitlimit, rate ich jezt mal? Oder TDD und dann Schritt für Schritt (d.h. Funktion für Funktion) "schön" und korrekt schreiben. Ist Dokumentation vorhanden? Wenn nicht, kann auch damit angefangen werden. Vorteil: viele mögliche Missverständnisse werden aus dem Weg geräumt und spätere "Opfer" wie du bekommen einen leichteren Einstieg. Mit einer(halbwegs) fertigen Doku fällt das refactoring auch leichter (das eben nicht unmöglich ist). Ich denke insgesamt, dass TDD in dem Fall ein guter Weg ist.
Re: Umgang mit grausigen Codebasen
Verfasst: Donnerstag 5. Mai 2011, 07:27
von Dauerbaustelle
mhm, das war bisher auch der Plan. Test-Driven-Development wird halt ein bisschen schwer mit null Doku und wenig Verständnis -- wenn man immer nur annäherungsweise versteht, was der Code tut, kann man auch nur annäherungsweise vollständige Tests schreiben und hat nach dem Refactoring nur "ähnlichen" Code, aber nicht "identischen"...
Re: Umgang mit grausigen Codebasen
Verfasst: Donnerstag 5. Mai 2011, 07:49
von snafu
Vielleicht könntest du auch erstmal eine neue Schnittstelle zu den für dich relevanten Teilen schreiben. Ich sehe da den Vergleich zum Anbinden von C-Bibliotheken in Python, wo man oft auch erstmal die Funktionen in Rohform wrappt und anschließend so C-typische Dinge wie Größenangaben für den verwendeten Puffer automatisiert. Um mal konkreter zu werden: Wenn jetzt beispielsweise im Originalcode viele ``getFoo()``-Methoden bestehen, dann könnte man diese in ein ``foo``-Property wrappen. So hat man dann am Ende zumindest schon mal eine gut aussehende Benutzerschnittstelle, die man idealerweise dokumentiert. Wenn man dann noch Zeit und Lust hat, kann man sich an den dahinterliegenden Code wagen. Voraussetzung für dieses Vorgehen ist natürlich, dass der Gruselcode zwar bescheiden aussieht, aber grundsätzlich korrekt funktioniert.
Re: Umgang mit grausigen Codebasen
Verfasst: Donnerstag 5. Mai 2011, 08:12
von sma
Der erste Implus ("Das muss alles neu") ist in der Regel falsch, denn man berücksichtigt nicht, das Wissen, was in dem Code von gemachten und korrigierten Fehlern steckt, weil sich diese nicht in "lines of code" niederschlagen.
Die Abwesenheit von Tests oder Dokumentation ist hingegen ein Programmfehler, den es zu korrigieren geht.
Aussagen wie "dafür haben wir keine Zeit" sind Zeichen für ein grobes Unverständnis für Software-Entwicklung, unprofessionell und fahrlässig. Wer als Entwickler diesem Wunsch nachgibt, macht sich mitschuldig. Wer Software-Entwicklung professionell betreibt, wird beschäftigt, weil er ein Experte auf seinem Gebiet ist und da hat niemand reinzureden, wenn es um das konkrete Vorgehen geht. Das sollte eine Frage der Berufsehre sein. Einem Chirurg sagt ja auch niemand er möge das Desinfizieren vor der Operation lassen, weil das nur unnötig Zeit kostet.
Das bessere Vorgehen ist daher, mit Tests die vorhandene Funktionalität abzusichern und damit anzufangen, dass erlangte Verständnis durch Refactoring des Codes sichtbar zu machen. Sich durchzubeißen, aber selbst nichts zu ändern, ist auch keine Lösung, denn dann hat der nächste Entwickler in einigen Monaten oder Jahren das selbe Problem. "Never change a running program" gehört aus dem Wortschatz eines professionellen Entwicklers verbannt.
Ich würde als ersten Schritt - idealerweise mit einer guten IDE - erst mal den Quelltext neu und einheitlich formatieren. Geht das nicht automatisch, würde ich immer die Stellen, die ich mir anschaue, anpassen. Als nächstes würde ich Namen ändern, damit sie einheitlich und beschreibend sind. Das mache ich auch 4x nacheinander mit der selben Funktion, wenn ich immer besser verstehe, was diese eigentlich macht. Große Funktionen, von denen ich Teile verstanden habe, würde ich entsprechend aufteilen. In Java würde ich mir dies alles auch ohne Tests herausnehmen, weil ich weiß, dass eine IDE bei diesen Refactorings nichts kaputt machen kann. In Python muss man etwas aufpassen und prüfen, dass nicht zu clevere Metaprogrammierung eingesetzt wird. Spätestens dann sind Tests wichtig, die sicherstellen, dass das, was ging auch später nicht geht. Wenn mir keiner beschreiben kann, was die Software überhaupt machen soll, nagel ich eben (ohne Gewähr) den Istzustand mit Tests fest.
Das wird Anfang echt kompliziert werden und der "WTF-Faktor" wird extrem hoch sein, denn in der Regel wird sich der Code mit Händen und Füßen wehren, in Teilen Testbar zu sein. Doch da muss man durch, mocken hilft, auch wenn ich das sonst als Methode für Tests ablehne. Man wird hier viel darüber lernen, wie der Code strukturiert sein müsste, damit man ihn in "units" testen könnte. Tests müssen in jedem Fall automatisiert funktionieren. Ist man doppelt gekniffen und muss sich mit einer GUI-Anwendung auseinander setzen, hilft nur ein (wahrscheinlich kommerzielles) Testtool, mit dem man von außen ein GUI scripten kann. Für Webanwendungen gibt es bessere Lösungen. Für Akzeptanztests etwa böte sich Cucumber an.
Mit einem Code-Coverage-Tool würde ich die Testüberdeckung messen und so den Fortschritt und die Qualitätsverbesserung messen. In Java habe das natürlich alles in meiner IDE eingebaut und dort würde ich 100% anstreben. Doch für Python gibt es auch entsprechendes als Kommandozeilenprogramme. Dabei lösche ich alles, was unbenötigt scheint. Selbstverständlich nutze ich eine Versionsverwaltung, über die ich jede noch so kleine Änderung dokumentiere.
Idealerweise mache ich alle Änderungen im Team, denn 4 Augen sehen meist mehr und die Wahrscheinlichkeit für Fehler ist geringer und man kann im Gespräch wesentlich effektiver und effizienter den Code verstehen und eine neue Architektur entwerfen, die modularer und testbarer ist.
Neuen Code entwickle ich dann testgetrieben.
Stefan