Unclean Code

Unclean Code

Clean Code kennt jeder. Bestimmt hat man schonmal irgendwo davon gehört, davon gelesen, oder evtl. sogar schonmal mit jemandem diskutiert, ob einige der Vorschläge des Clean Code nicht doch so weit gehen, daß schon wieder Cluttered Code entsteht (wenn Funktionen nur noch Dreizeiler sind – man überlege, ob es dann nicht Verwirrung wegen der Anzahl der Funktionen gäbe).

Unclean Code hingegen kennen wir oft bestens.

Nicht notwendigerweise, wenn wir in unseren eigenen Code schauen, aber zumindest, wenn wir in dieses viele Jahre alte Stück Code unseres Vorgängers schauen, und uns das kalte Grauen kommt.

Da zeigen sich dann ein paar schöne Vorzüge – zumindest zeigen sie sich dadurch, daß wir sie vermissen.

Keep it simple, stupid! – die schönste Lösung besitzt die minimale Komplexität

Früher war ein neuer Case-Fall, den wir vorher übersehen haben, oder der durch neue Anforderungen mit hinzugefügt werden muß, schnell eingefügt. Heute sind es manchmal Dutzende von Policies oder ähnlichem Schnickschnack, die geändert werden müssen. Die schönste Lösung ist – immer – nicht die komplizierteste, sondern die einfachste. Mit einer Ausnahme: wir haben bereits gekündigt, wissen, daß wir den Code nie wieder sehen werden, und wollen nochmal ein schönes Geschenk hinterlassen und ein paar Techniken ausprobieren, die wir schon immer mal angehen wollten.

Ansonsten ist Einfachheit Trumpf. Einfachheit ist immer gut erweiterbar: wer heute Erweiterbarkeit einplant wird oft von den Geschehnissen überholt und stellt fest, daß er genau den Fall, der jetzt eingetreten ist, nicht vorbereitet hat.

Ferner ist Technologie keine Selbstzweck. Sie sollte nur da eingesetzt werden, wo sie einen Nutzen bringt.

Convention over Configuration – alles ist genau da, wo man es erwartet

Auch macht Einfachheit den Code oft verständlicher. Hier sei Convention over Configuration von z. B. RoR gelobt. Die weggefallenen Möglichkeiten wird niemand ernsthaft vermissen – dafür weiß jeder, auch andere, die ein fremdes Projekt übernehmen, direkt, wo die Views sind, oder daß es ein MVC Muster gibt, das benutzt wurde. Oder..

Zu wissen, wo eine bestimmte Funktionalität erwartet werden kann macht die Einarbeitung in fremden Code oh-so-viel schneller.

Wer sich an Konventionen hält verhindert auch ein Problem, das ich neulich hatte: anstelle die schönen Click-Events von Windows Forms zu nutzen ist jemand auf die Idee gekommen, einen großen Event-Handler zu bauen, der anschließend die ID der Controls checkt und dementsprechend handelt. (Erinnert sich jemand an die Win-Procs unter nacktem Win32?) Dadurch funktionieren natürlich auch die zahlreichen Vereinfachungen, die die IDE bietet nicht mehr. Durch einen Klick auf das Control kommen wir nicht mehr zur Implementation, sondern erzeugen eine neue Funktion, die dann parallel aufgerufen wird.

Don’t repeat yourself – was es nur 1x gibt kann nicht mit sich inkonsistent werden

Funktionalität, die über mehrere Stellen verteilt ist, wird über kurz oder lang zum Wartungsalbtraum. So habe ich z. B. schon Beispiele gesehen, wo 2 direkt hintereinanderstehende Zeilen inkonsistent waren, z. B. wenn eine der Zeilen ein Kommentar oder eine Log-Nachricht waren. So etwas läßt sich z. B. durch die Benutzung von Konstanten verhindern: direkt vor beide Zeilen eine Konstante setzen, an der wir drehen können, wenn wir feststellen, daß dies ein Wert ist, den wir öfter anfassen müssen.

Sind zusammengehörige Stellen über ein Projekt oder gar über mehrere Projekte verteilt wird das ganz ungleich schwieriger und kaum noch nachvollziehbar. Ein gutes Design erkennt man klar daran, daß eine spätere Änderung (solche kommen erfahrungsgemäß immer) nur an minimal wenigen Stellen Anpassungen nach sich zieht.

Single Responsibilty – jeder tut genau das, was er behauptet, und nur das

Schön ist es auch, wenn Funktionen schlecht benamt und unsinning kommentiert sind. Manchmal können durch schlechte Englischkenntnisse (wenn in Englisch kommentiert wird) Kommentare so fehlerhaft und mehrdeutig sein, daß nicht einmal mehr eine Funktionalität abgeleitet werden kann – zumindest nicht für die spannenden Corner Cases. Einher geht das dann oft mit schlechten Benamungen von Funktionen und einer mangelhaften Kenntnis des Single Responsibility. Eine Funktion sollte nur eine Aufgabe haben, und dann auch so benannt sein. Kaufen wir eine „Busreise nach Nürnberg” und laufen dann nach Konstanz und schwimmen durch den Bodensee, so würden wir uns auch wundern. Doch genau das passiert oft im Code: es steht eine Sache drauf, und es passiert eine ganz andere – oder gerne auch mehrere andere. So etwas ist Gift, wenn jemand anders sich den Code noch einmal anschaun muß.

Lösung

Es gibt 2 einfache Dinge, mit denen sich all diese Probleme dauerhaft verhindern lassen. Das erste ist der gesunde Menschenverstand. Leider funktioniert dieser jedoch viel zu oft nicht, und Menschen gehen ihren eigenen Produkten gegenüber nicht so kritisch um, wie es evtl. angemessen wäre. Und – in diese Falle läuft man immer wieder, obwohl nach jedem Horrorprojekt der feste Vorsatz ausgesprochen wird „Das nächste Mal wird anders!”

Es bleibt also noch das zweite. Jeder sollte zumindest einmal so lange an einem Projekt gesessen haben, daß er am Ende nicht mehr wußte, was er am Anfang gemacht hat, und sich dann durch Dokumentation und Code in seine eigene Arbeit wieder neu eingedacht haben – und dann noch eine ganze Weile diesen Code gewartet haben. Dann wird er anfangen, für so einen Fall vorzubauen. Und die Früchte werden sich auch alsbald zeigen, wird der eigene Code doch besser verständlicher und wartbarer, und das nicht erst in einer fernen Zukunft, sondern bereits morgen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.