Archiv

Artikel getaggt mit ‘Clean Code’

Buch-Rezension zu “Working Effectively with Legacy Code”

Legacy Code Viele Bücher zeigen wie man mittels TDD sauberen Code schreiben kann. Michael Feathers geht in “Working Effectively with Legacy Code” einen anderen Weg. Er zeigt wie man aus Legacy Code Schritt für Schritt und mit viel Arbeit eine saubere Codebasis schaffen kann.

Dieser Weg ist alles andere als leicht, startet dafür aber dort wo wohl die meisten Software-Projekte sind: Bei einer grossen Menge Code mit nur wenigen (oder gar keinen) Tests und der dennoch geschäftskritische Funktionen erfüllt. Wie erhält man dessen Funktionalität und schafft es gleichzeitig flexibel auf neue Anforderungen zu reagieren?

 

Schritt für Schritt

Wichtig ist das man nicht gleich zu Beginn alles hinwirft. Nur weil der Code noch über keinen einzigen Test verfügt bedeutet dies nicht dass dies so bleiben muss. Im Buch findet man für sehr viele Situationen Tipps und Tricks um mit dem Testen zu beginnen.

Allerdings kann man nicht von einem Extrem in andere springen. Wo noch keine Tests vorhanden sind gleich mit TDD alles machen zu wollen wird sehr schnell scheitern. Besser ist es mit wohlüberlegten und gezielten Tests zu beginnen. Vor der geplanten Änderung erst einmal den Code anschauen und mit Tests auf einer höheren Ebene (wie Integrations- oder Akzeptanztests) beginnen. Oft braucht es auch Mut erst einmal ein Loch aufzureissen um überhaupt einen Test scheiben zu können. Denn wenn man vor dem ändern von Code erst einen Test haben will und für diesen Test erst eine Anpassung am Code braucht steht man vor einem Henne-Ei Problem.

Soll sich die Situation verbessern muss man bereit seit für eine gewisse Zeit mit Code zu leben der nicht allen OO-Regeln folgt. Zusätzliche Konstruktoren nur um Abhängigkeiten zu übergeben sind oft nötig bis dies „korrekt“ gelöst werden kann. Bleibt man dran und geht konsequent den eingeschlagenen Weg kann man auch das grösste Gestrüpp entwirren – dies geschieht aber nicht über Nacht.

 

Einstellung ändern

Aber was ist eigentlich Legacy Code genau und warum ist dies etwas Schlechtes? Feathers hat in seinem Buch zwei Definitionen, von denen man in der Regel nur die weniger freundlich formulierte in Erinnerung behält:

Legacy Code is Code Without Tests

In dem Sinne liegt es bei jedem einzelnen Entwickler aufzuhören vorneweg Legacy Code zu schreiben und sich über die Qualität und Testbarkeit seines Codes Gedanken zu machen. Andernfalls sind all die im Buch aufgezeigten Ansätze für nichts und man ist in kurzer Zeit wieder da wo man begonnen hat.

Was Michael Feathers in seinem Buch leider nicht anspricht ist wie man sein Team von der Notwendigkeit von wartbarem Code überzeugen kann. Genau dies aber dürfte in vielen Projekten wohl das grösste Hindernis sein.

 

Characterization Tests

Von all den verschiedenen Ansätzen die in diesem Buch vorgestellt werden fand ich die Characterization Tests am hilfreichsten. Bei diesen Tests fängt man nicht wie bei TDD mit dem gewünschten Verhalten an und folgt dem Red-Green-Refactor Mantra. Stattdessen beginnt man den Test in dem man beim Assert-Aufruf das Resultat der Methode mit dem Default-Wert des entsprechenden Datentyps vergleicht. Der Test wird in den meisten Fällen fehlschlagen und die Fehlermeldung liefert einem den korrekten Wert. Dieser setzt man dann im Assert-Aufruf ein und hat so einen erfolgreich bestandenen Test.

Ohne den Code anzupassen kann man so recht schnell die einzelnen Eigenschaften einer Methode oder einer ganzen Klasse durch Tests fixieren. Dieses Korsett an Tests dient einem nach dem Refactoring zu verifizieren das die Verbesserungen das Verhalten des Codes nicht verändert haben.

Um Legacy Code mit Tests zu versehen macht man also genau das was bei TDD verpönt ist: Den Test so zu schreiben das der aktuelle Code diesen besteht ohne sich Gedanken über die wirklichen Anforderungen zu machen. Aber genau dies macht diese Art von Tests für mich so praxisrelevant. Hat man Legacy Code muss man auf diesen eingehen und eine Lösung finden die den aktuellen Code beschreibt. Hat man einmal so viele Tests dass man wirklich weiss was der Code macht gilt es wieder den Schalter umzulegen und zu prüfen ob dies auch wirklich korrekt ist. Bis es so weit ist muss man die liebgewordenen Regeln aber auch einmal zurückstellen können.

 

Weiterführende Bücher

Nach dem der Code mit Tests versehen ist geht es ans Aufräumen. Dazu verweist Feathers oft auf Martin Fowlers “Refactoring“. Das Standardwerk zu diesem Thema sollte man kennen, da man ansonsten den Ausführungen kaum folgen kann.

Wer mittels Refactoring grössere Ziele verfolgt sollte auch einen Blick auf “Refactoring to Patterns” von Joshua Kerievsky werfen. Dies baut ebenfalls auf Fowlers Buch auf und erklärt wie man mit einer Kombination von Refactorings grössere Strukturverbesserungen erreichen kann.

 

Fazit

Michael Feathers zeigt einem in diesem Buch wie man von einer durchschnittlichen Codebasis zu einer kommt die dank Tests auf geänderte Anforderungen reagieren kann. Der Weg dorthin ist aber nicht zu unterschätzen und man muss auch einmal bereit sein eine gewisse Unordnung zu akzeptieren. Will man sich darauf einlassen liefert einem dieses Buch viele wertvolle Tipps.

 

Zum Buch

Working Effectively with Legacy Code” von Michael Feathers, 2004 Prentice Hall, ISBN: 978-0-1311-7705-5, 434 Seiten, Englisch

Buch-Rezension zu “Domain-Driven Design”

3. Februar 2013 1 Kommentar

Domain-Driven DesignWenn man sich mit Behavior Driven Development (BDD) und dem Schreiben von Akzeptanztests beschäftigt stösst man immer wieder auf ein Buch:
Domain-Driven Design: Tackling Complexity in the Heart of Software” von Eric Evans.

Dieses Buch gilt weit herum als Standardwerk das man unbedingt kennen muss. Beim Lesen merkt man schnell das Evans sehr viel Erfahrung hat und weiss wovon er schreibt. Leider macht er dies so ausführlich dass man kaum vorwärts kommt. “Man müsse die Informationen herausschürfen” ist eine Bemerkung über dieses Buch die man beim Lesen im Hinterkopf behalten sollte.

 

Kernpunkte

Von all den Themen die Evans behandelt stechen für mich diese Punkte besonders hervor:

Mit Hilfe einer Ubiquitous Language (einer einzigen gemeinsamen Sprache) sollen alle am Projekt beteiligten Personen kommunizieren. Dadurch das alle die gleichen Begriffe benutzen können Missverständnisse und Übersetzungsprobleme (im Sinne von Fachspezifisch zu Technisch) früh erkannt werden oder entfallen ganz. Auch ist es für Entwickler einfacher sich an die Spezifikationen zu halten wenn die Objekte im Code gleich heissen wie in den Anforderungen und den Testszenarios.

Bei Refactoring denkt man meistens an einen technischen Vorgang um Code besser zu strukturieren. Neben diesem technischen Aspekt gibt es aber auch einen fachlichen. Evens zeigt bei „Refactoring Toward Deeper Insight“ auf wie man nach und nach das Domänenmodell um neue Erkenntnisse verfeinern kann.

Entwickelt man nach Model Driven Design darf das Modell nicht in einem Vakuum erstellt werden. Ist dieses Modell technisch nicht umsetzbar wird in der Entwicklung gezwungenermassen eine Lösung gefunden die davon abweicht. Damit verliert man alle Vorteile und muss ständig zwischen mehreren Modellen hin und her wechseln. Neben höheren Kosten leidet dabei auch die Kommunikation.

Bounded Context: Das eigene Domänenmodell kann noch so gut sein, wenn man es nicht abgrenzt fliessen die unterschiedlichen Konzepte der Umsysteme hinein. Evens zeigt eine ganze Reihe von Ansätzen um dies zu verhindern (wie das Pattern “Anticorruption Layer”).

Software-Entwicklung ist mehr als das Schreiben von Code. Es geht um das Lösen von Problemen. Damit man die passende Lösung finden kann ist eine Zusammenarbeit mit allen beteiligten Parteien nötigt.

 

Kritik

Die gleichen Namen und Bezeichnungen zu verwenden ist ein grosser Schritt in die richtige Richtung. Nur ist es damit nicht getan. Mir fehlt wie man auch zu einer gemeinsamen Bedeutung kommt und überhaupt die Wiedersprüche aufdecken kann. (Wenn alle von Autos sprechen, wie merkt man das der eine einen Golf meint und der anderen einen Ferrari?)

Die ersten beiden Teile sind sehr schwerfällig geschrieben. Immer wieder springt Evans von einer Idee zur nächsten und wieder holt dieses hin und her mehrmals. Würde dies aus unterschiedlichen Perspektiven geschehen wäre dies ein Plus fürs Buch. Leider sucht man die ganze Zeit nach den Unterschieden zum bereits behandelten und findet meist keine. Dies bremst den Lesefluss und schlägt auf die Motivation.

Anstelle der vielen Wiederholungen wären Beispiele zur technischen Umsetzung hilfreich. Statt so viel über Code zu sprechen hätte Evens diesen zeigen können – dies ginge schneller und hätte einen Praxisnutzen. So bleibt zu viel eine schöne Idee ohne Hinweis auf deren Umsetzung.

 

Alternative

Abel Avram und Floyd Marinescu sahen ebenfalls einige Verbesserungsmöglichkeiten und schrieben 2006 das Mini-Book “Domain Driven Design Quickly“. Auf rund 100 Seiten gibt es all die Konzepte aus dem Buch von Evans, ein Interview mit ihm und es hat noch Platz für Ergänzungen aus “Applying DDD” von Jimmy Nilsson.

Wer ins Thema DDD einsteigen will sollte sich erst einmal das PDF bei InfoQ herunterladen.

 

Fazit

Mit Domain-Driven Design wurden viele wichtige Ideen erstmals in Buchform veröffentlicht. Die darin behandelten Themen sind auch heute noch aktuell und ein Umsetzen der von Evens vorgestellten Ansätze würde so manches aktuelle Problem lösen.

Leider verzettelt sich Evans mit seinen Erklärungen und macht es dem Leser äusserst schwer diese Konzepte zu verstehen. Als Einstiegslektüre ins Thema DDD kann ich dieses Buch daher nicht empfehlen. “Domain Driven Design Quickly” ist dafür die bessere Wahl, da die gleichen Konzepte viel besser auf den Punkt gebracht werden.
Kehrt man nach diesem Umweg zu Evens zurück versteht man seine Ideen viel besser und erkennt dann auch was sonst noch alles für Informationen in diesem Buch stecken.

 

Zum Buch

Domain-Driven Design: Tackling Complexity in the Heart of Software” von Eric Evans, 2003 Addison-Wesley, ISBN 978-0-3211-2521-7, 560 Seiten, Englisch

Kategorien:.Net, Bücher, Ruby, webRead Schlagworte: , , ,

Kopierten Code finden mit der Code Clone Analyse

Code wird gerne kopiert. Was einem zuerst hilft schnell ähnliche Anforderungen zu erfüllen wird in kurzer Zeit zu einem Problem. Nun ist es nicht mehr damit getan eine Stelle im Code zu korrigieren und der Fehler ist behoben – man muss jetzt immer auch noch alle Kopien korrigieren.

Das Problem dabei ist das man nicht weiss was für Code kopiert wurde und wo der in Modul X aufgetretene Fehler noch alles drin ist. Als Folge davon bleiben die Fehler meist unentdeckt und die Kunden fragen sich wieso sie immer wieder die gleichen Probleme melden müssen.

Seit Visual Studio 2012 hat man beim Aufstöbern dieser Klone eine Hilfe. Die Analysefunktionen wurden um die Funktion Code Clone Detection erweitert. Wie der Name vermuten lässt wird damit kopierter Code aufgespürt.

Führt man diese Auswertung aus muss man sich erst einmal gedulden. Der ganze Code wird in Tokens unterteilt und dann analysiert. Der erstmalige Durchgang ist je nach Codebasis und Geschwindigkeit des Rechners eine gute Gelegenheit für eine ausgedehnte Kaffeepause.

 

Nicht nur 1:1 Kopien

Code der 1:1 kopiert wurde wird von Code Clone als „Exact Match“ gefunden. Damit gibt sich Code Clone aber nicht zufrieden. Kleinere Anpassungen wie umbenannte Variablen werden ebenfalls erkannt und als „Strong Match“ oder als „Medium Match“ klassifiziert.

Richtig interessant wird es bei grösseren Änderungen die als „Weak Match“ eingestuft werden. Hier ist die Chance auf falsch erkannte Klone entsprechend grösser. Dafür findet man hier aber auch die Stellen, die man auf den ersten Blick nicht als Klon erkennen würde:

public void MethodA(string input)
{
    Console.WriteLine("input => ", input);

    string a = input.Trim().ToLower();
    string b = input.Trim().ToLower();
    string c = input.Trim().ToLower();
    string d = input.Trim().ToLower();
    string e = input.Trim().ToLower();

    Write(a);
    Write(a);
    Write(a);
    Write(a);
}

public void MethodB(string input)
{
    string b = input.Trim().ToLower();
    Write(b);
    Write(b);
    Write(b);

    string a = input.Trim().ToLower();
        
    string c = input.Trim().ToLower();
    Console.WriteLine("input => ", input);

    string e = input.Trim().ToLower();
    string d = input.Trim().ToLower();
    Write(b);
}

In diesem Beispiel wurde der gleiche Code anders aufgebaut. Gerade bei solchen Klonen spielt Code Clone seine Stärken aus und erweist sich als äusserst hilfreich.

 

Nebeneffekte

Nutzt man Code Clone in einem realen Projekt kann man damit noch mehr Probleme aufdecken als nur kopierten Code. Sind Methoden inhaltlich identisch aber mit ganz anderen Namen versehen (wie beispielsweise GetOrder und GetPerson) gibt es wohl grössere Probleme beim Verstehen der Domäne.

Im besten Fall löst sich das Problem mit einer genaueren Erklärung der Domänenbegriffe. Es kann aber gerade so gut auch ein Warnzeichen für eine falsche Abstraktion oder gröbere Architekturfehler sein.

 

Einschränkungen

Code Clone hat 2 wichtige Einschränkungen:

  1. Diese Analyse benötigt die Premium und der Ultimate Version von Visual Studio 2012.
  2. Es werden nur Code-Teile berücksichtigt die aus 10 oder mehr Befehlen bestehen.

 

Fazit

Mit der Code Clone Analyse kann man ohne grossen Aufwand kopierte Codestücke auffinden. Dabei werden nicht nur 1:1 Kopien gefunden, sondern auch Teile die ähnlich sind. Die so gewonnenen Erkenntnisse sind eine gute Ausgangslage für ein Refactoring oder eine teamweite Code Review.

Kategorien:.Net Schlagworte: ,

Buch-Rezension zu “The Art of Readable Code”

The Art of Readable Code” von Dustin Boswell und Trevor Foucher erschien Ende 2011 bei O’Reilly. Auf rund 200 Seiten bekommt man viele Tipps um den eigenen Code lesbarer zu machen. Dies dient nicht nur anderen Programmierern, sondern hilft einem auch selber – spätestens in einigen Wochen wenn man nicht mehr alle Details im Kopf hat.

Die vorgestellten Tipps & Tricks sind dabei nicht auf eine bestimmte Programmiersprache oder Framework-Version beschränkt. Wer in C# entwickelt wird genauso brauchbare Tipps finden wie derjenige der JavaScript verwendet.

 

Viele gute Empfehlungen

Durchs Buch hinweg wird jeweils mit einem kurzen Beispiel gezeigt wie massiv sich eine kleine Änderung auswirken kann. Das Codebeispiel zu Beginn ist dabei nicht extra unleserlich gemacht worden. Es könnte viel eher aus einem eigenen Projekt stammen.

Die im jeweiligen Kapitel behandelte Empfehlung wird für den Leser leicht nachvollziehbar in kleineren Teilschritten umgesetzt. So sieht man einerseits dass auch der eigene Code verbesserungspotential hat und andererseits wie wenig Veränderung es braucht um viel zu verbessern. Damit das gerade gelernte haften bleibt gibt es immer einen extra hervorgehobenen Satz (Key Idea) der die Empfehlung genau auf den Punkt bringt.

Die behandelten Themen lassen sich grob in diese Bereiche unterteilen:

  • Aussagekraft erhöhen (bei Namen, Kommentaren oder mittels Formatierung)
  • Vereinfachen (nicht nur die Logik an sich, sondern auch Schleifen und if-Bedingungen)
  • Reorganisieren (weil kleinere Teile einfacher zu verstehen sind)

Besonders gefallen haben mir die immer wieder eingeworfenen Beispiele aus der Praxis. Nur weil einem gerade kein perfekter Kommentar einfällt kann man ja nicht den ganzen Tag danach suchen. Irgendwie muss die Entwicklung ja voran gehen. Die beiden Autoren tragen dem Rechnung und zeigen wie man sich schrittweise einem besseren Kommentar nähern kann.

 

Nicht blind folgen

Auch wenn dieses Buch bei vielem richtig liegt, so gibt es auch einige Empfehlungen die einem recht schnell vor neue Probleme stellen können. Mich störte dabei vor allem die Empfehlung für statische Methoden. Im Einzelfall mag dies ein guter Tipp sein, bei zu intensiver Anwendung leidet aber die Testbarkeit. Daher führt auch bei diesem Buch kein Weg daran vorbei mitzudenken und eine Balance zwischen allen Anforderungen zu finden.

 

Fazit

Ein kompaktes Buch mit vielen Vorschlägen um Code lesbarer zu schreiben. Obwohl es an revolutionären Neuerungen fehlt so ist es erfrischend ein Buch zu diesem Thema zu finden das frei von Dogmen ist.

Gegenüber “Clean Code” findet man hier kaum Neues. Wem Clean Code aber zu theoretisch oder zu abgehoben war sollte es mit diesem Buch versuchen.

 

Zum Buch

The Art of Readable Code” von Dustin Boswell und Trevor Foucher, 2011 O’Reilly, ISBN 978-0596-8022-95, 206 Seiten, Englisch

Buch-Rezension zu “Professional Test Driven Development with C#”

Professional Test Driven Development with C#” von Jeff McWherter und James Bender erschien im Mai 2011 bei Wiley. Das Buch richtet sich an all die Entwickler, die ihre C#-Anwendungen nach Test-First entwickeln wollen.

Wer sich bisher noch nicht mit dem Thema Test Driven Development (TDD) beschäftigt hat findet in den ersten beiden Teilen des Buches eine gute und ausführliche Einführung ins Thema.

 

 

TDD Szenarien aus der Praxis

Der dritte Teil widmet sich den praxisorientierten TDD Szenarien. Im Gegensatz zu vielen anderen Büchern geht es hier um die schwerer zu testenden Teile:

  • ASP.Net WebForms
  • ASP.Net MVC
  • JavaScript
  • WPF
  • Silverlight
  • WCF

Im Buch wird zu jeder dieser Technologien aufgezeigt wo die besonderen Herausforderungen liegen und wie man diese Testen kann. Wann immer möglich sollte man die dazu passenden Patterns verwenden. Geht dies nicht ist man auf sich alleine gestellt: Das Buch erklärt leider nur genau einen Weg um die entsprechende Technologie zu testen.

 

Werkzeuge und Katas

Als Abschluss gibt es einen Teil der sich den Werkzeugen widmet. Bei der Vielzahl möglicher Test-, Mock- und DI-Frameworks ist es nicht leicht eine Auswahl zu treffen. Die Autoren vergleichen jeweils einige Werkzeuge aus dem gleichen Bereich und nennen die für sie wichtigsten Unterschiede. Auch wenn dies die eigene Recherche nicht ersetzt, so ist dies doch ein guter Ausgangspunkt um seinen Werkzeugkasten zusammen zu stellen.

Im Appendix wir noch auf das Thema (TDD-) Katas eingegangen. Kleinen Übungen sollen einem dabei helfen das gelernte zu verinnerlichen. Die Idee stammt aus dem Kampfsport und hilft dort die richtigen Aktionen und Bewegungen zur richtigen Zeit zu machen. Übertragen auf TDD bedeutet dies: Hat man immer und immer wieder geübt wie man erst einen Test und dann den produktiven Code schreibt, geht dies in einem über und man wendet die gleiche Technik auch mit dem Code direkt vor einem an.

 

Ein E-Book aber kein PDF

Wiley bietet für dieses Buch eine E-Book Version an, aber leider nur in den Formaten ePub und mobi. Gerade wenn ein Buch viele Code-Beispiele hat habe ich neben der Kindle-Version sehr gerne noch ein PDF. Nicht nur sieht der Code dort meist besser aus, er lässt sich auch einfach kopieren. Mir schein als ob Wiley der Konkurrenz in diesem Bereich noch weit hinterher hinkt.

 

Fazit

Den beiden Autoren ist in einem oft behandelten Themenbereich ein gutes Werk gelungen. Die beiden Einführungsteile liefern alles nötige Grundwissen damit man auch als Anfänger durchstarten kann. Die Auswahl eines Werkzeugkastens und das vermitteln der Ideen rund um TDD runden dieses Buch ab. Mir fehlen hier einzig noch einige alternative Ansätze zum Testen der behandelten .Net-Komponenten.

The Art of Unit Testing“ ist zwar immer noch mein Favorit zum Thema TDD, dieses Buch folgt aber mit einem sehr kleinen Abstand.

 

Zum Buch

Professional Test Driven Development with C#” von Jeff McWherter und James Bender, 2011 Wiley, ISBN: 978-0-470-64320-4, 360 Seiten, Englisch

Kategorien:.Net, Bücher, webDotNet, webRead Schlagworte: , , ,
Follow

Bekomme jeden neuen Artikel in deinen Posteingang.

Schließe dich 175 Followern an