Refactoring



  • Ich beherrsche zwar noch keine Programmiersprache (lerne seit ca. 1,5 Monaten C++), deshalb ist die Antwort vielleicht nicht so hilfreich, aber z.B. um den Code für andere klarer (verständlicher, nachvollziehbarer) zu gestalten.



  • Es mag einmal so gewesen sein, dass Programmierung vor allem darin bestand, einer Maschine bestimmtes Verhalten beizubringen. Inzwischen ist das keine tragbare Maxime mehr.

    Disclamer: Alles, was ich hier schreibe, ist zunächst mal meine persönliche Meinung.

    Moderne Programmierung erfordert in erster Linie ein gewisses Organisationsvermögen; dies ist der zunehmenden Komplexität der Anwendungen geschuldet. Man muss sich drei Wahrheiten stellen:

    1. Menschen machen Fehler. Auch du.
    2. Anforderungen ändern sich im Laufe der Zeit.
    3. Beides ist nicht vorhersagbar.

    Ersteres mag unangenehm, sollte aber jedem klar sein. Jeder Programmierer macht in seiner Arbeit Fehler, und diese sind einfacher zu korrigieren, wenn logisch gleiche Teile des Codes nicht an ein paar Dutzend verschiedenen Stellen mit den gleichen Fehlern auftauchen - da könnte man leicht mal eine übersehen. Benutze ich in beispielsweise an zwei Dutzend Stellen in meinem Code die Newton-Iteration, vertippe (oder verdenke) mich aber bei der ursprünglichen Implementation und stelle dies ein halbes Jahr später fest, und habe ich den Algorithmus per copy&paste im gesamten Programm verteilt, so ist die Korrektur ausgesprochen mühsam. Habe ich sie dagegen in eine Funktion oder Funktionsvorlage ausgelagert, muss ich sie nur an einer Stelle vornehmen, und sie gilt danach für alle Anwendungen.

    Ähnliches gilt für Änderungen der Anforderungen. Angenommen, ich will in meiner Anwendung Strings auf Verhalten mappen, meinetwegen auf Interpolationsarten über eine Punktmenge, und ich will ein halbes Jahr nach dem ersten Release eine weitere Implementationsart für die nächste Version implementieren (beispielsweise Splines), so ist dies einfacher umzusetzen, wenn ich sowohl das Mapping als auch die Schnittstelle des Verhaltens an zentraler Stelle definiert habe, anstatt es per copy&paste an verwendenden Stellen einzufügen.

    Der dritte Punkt bedeutet, dass man sich diesen Umständen auch nach ihrer ursprünglichen Implementation anpassen muss. Es kommt durchaus vor, dass man zunächst unter der Annahme arbeitet, dass bestimmte Dinge nur in bestimmten Kontexten von Bedeutung seien, dies sich aber später ändert - dies kann Missverständnissen, höherer Gewalt oder auch Inkompetenz geschuldet sein; Punkt 1 bezieht sich nicht nur auf Programmierer. Die Annahme, dass etwas für alle Zeit unverändert gilt, ist in so ziemlich allen Kontexten höchst unklug. Wenn eine solche Änderung eintritt, kann (wird!) sich dein ursprüngliches Design als suboptimal herausstellen, und dann muss es im Interesse der Nachhaltigkeit verändert werden - Refaktorisierung.

    Auch macht es wenig Sinn, alle zukünftigen Änderungen quasi per Kristallkugel voraussagen zu wollen; Voraussagen sind, so sagt es der Volksmund, schwer zu machen, insbesondere, wenn sie die Zukunft betreffen. Gelegentlich ist es zunächst einfacher (sowie schneller und übersichtlicher), Programmteile, die nur für einen bestimmten Programmteil benötigt werden, dort an Ort und Stelle zu implementieren, anstatt jeden Kleinkram, von dem man nicht weiß, ob man ihn je irgendwo anders braucht, in eigene Funktionen/Klassen auszulagern. Wird der entsprechende Teil aber später doch an anderer Stelle benötigt, macht es aus den oben genannten Gründen mehr Sinn, ihn auszulagern, als Kopien davon im gesamten Code zu verteilen. Daher auch das DRY-Prinzip (DRY = Don't Repeat Yourself), die 1-2-3-Regel und das KISS-Prinzip (KISS = Keep It Simple, Stupid). Das sind natürlich alles nur Faustregeln, aber es ist durch exzessive Abstraktion ebenso möglich, Code unverständlich und unwartbar zu machen wie durch einen Mangel an Abstraktion.



  • was heißt Code Wartung nochmal

    -Fehlverhalten der Software korrigieren ?
    - noch was ?



  • blurry333 schrieb:

    - noch was ?

    - Erweiterbarkeit sicherstellen
    - Code auf andere Plattformen übertragen -> Portabel machen
    - Compilezeiten und -abhängigkeiten reduzieren



  • @blurry333:
    Wartung heisst eben Wartung.

    * Fehler ausbessern
    Nicht alle Fehler treten von Anfang an auf.
    Nicht alle Fehler die Auftreten sind Fehler im eigentlichen Programm - viele Bugs sind im OS veraknert und man muss bei neuen OSen Workarounds basteln.

    * Zusätzliche Features einbauen.
    Speziell: Konfigurations-Änderungen für neue Kunden/Produkte/Länder/Sprachen/...
    Configuration-Management gehört zu den biestigsten Dingen in der Software-Entwicklung.

    * Performance verbessern
    Oft werden Programme am einer Bestimmten Menge Daten einfach langsam.
    Oder ein OS Update sorgt dafür dass etwas was vorher ausreichend schnell war auf einmal 10x so lange dauert

    Und alles was schon geschrieben wurde bzw. ich vergessen habe 🙂



  • Renaming finde ich auch noch wichtig. Kommt ab und zu vor, dass eine Klasse oder Funktion doch besser einen anderen Namen hat (um Verwirrung, Mehrdeutigkeit usw. zu verhindern).

    Ggf. möchte man auch älteren Code zur Vereinheitlichung an neurere Coding Standards anpassen.



  • @drakon: ich glaube die Frage war weniger was man beim Refactoring macht, sondern warum man überhaupt Refactoring macht.

    Renaming gehört ja eher zum was und weniger zum warum 😉



  • hustbaer schrieb:

    @drakon: ich glaube die Frage war weniger was man beim Refactoring macht, sondern warum man überhaupt Refactoring macht.

    Renaming gehört ja eher zum was und weniger zum warum 😉

    Naja. Kam bei mir auch schon vor, dass ich eine Funktion (selbstgeschrieben) gesehen habe und mich gefragt, was die jetzt wirklich tut. Das war dann ein Indiz, dass ich so wohl besser umbenenne. Ist für mich ein guter Grund für das "warum". 😉

    Gehört aber wahrscheinlich zu "lesbareren Code", was schon genannt wurde.



  • @drakon:
    Das zahlt sich IMO nur aus, wenn der Code entweder noch gewartet werden muss, oder damit gearbeitet wird, z.B. weil es sich um eine Library handelt die in Programmen verwendet wird die entweder noch entwickelt oder noch gewartet werden.

    Läuft also alles irgendwie auf den Punkt Wartung raus finde ich.



  • Da ich schon oft in meinem Berufsleben Code warten musste, der eigentlich nie dafür bestimmt war, länger als 3 Tage zu existieren, gehe ich mittlerweile prinzipiell davon aus, dass meine Software länger lebt als gedacht und dementsprechend gewartet werden muß. Das spart einem graue Haare.

    Gruß Kimmi



  • Bei (erfolgreicher) Software sind ca. 80% des Aufwandes der in die Software hineingesteckt wird, Wartungsaufwand (Korrekturen, Anpassungen, zusätzliche Funktionalität, Performanceverbesserungen, ...)

    Hinzu kommt, dass bei einem existierenden System, die Entwickler en größten Teil der Zeit mit dem Lesen und Verstehen existierenden Codes verbringen.

    Daher lohnt sich Refactoring - die Umstrukturierung des Codes - um die Wartbarkeit zu erhöhen. Und es lohnt sich, Zeit und Energie in das Erstellen von gut lesbarem, leicht zu verstehendem Code zu stecken.


Anmelden zum Antworten