Clean Code Developer - Warum CCD?

08.02.2018

Clean Code Developer - Warum CCD?

Dieser Beitrag widmet sich dem Thema Clean Code Developer (CCD) und der Möglichkeit, diese Prinzipien und Praktiken schrittweise in die tägliche Arbeit eines Entwicklungsteams einzubinden. Wie schon im einführenden Beitrag "CCD-Ausblick" erwähnt werde ich dies anhand von drei Fragen erläutern, die meist am Anfang einer neuen Vorgehensweise auftreten:

  • WARUM CCD?
  • WAS ist CCD?
  • WIE funktioniert CCD?

Als Grundlage dient die Bewegung Clean Code Developer, die im deutschsprachigen Raum unter clean-code-developer.de zu finden ist. Die Möglichkeit, durch das Werte-System in kleinen Schritten zu Fachwissen über eine saubere Code-Architektur zu gelangen, ist sehr hilfreich, um ein Wertegefühl für eine gute Code-Qualität zu entwickeln.

«WARUM CCD?»

In diesem Beitrag werden wir uns mit der Frage beschäftigen, warum es innerhalb eines Entwicklungsteams Prinzipien und Praktiken braucht, um qualitativ hochwertige Softwaresysteme zu erstellen. Dazu möchte ich eine provokative Aussage tätigen: Alle Prozessmodelle, seien es klassische wie V-Model oder Wasserfall oder aber speziell auch agile Modelle wie Scrum, Kanban und skalierte Modelle wie LeSS und SAFe, sind ohne die richtigen Entwicklungsmethoden nur Vorgehensmodelle, die letztendlich wieder ineffiziente und schwerfälligen Softwaresysteme ans Tageslicht befördern. Oft stehen Softwarearchitekten schon nach kurzer Zeit einem System gegenüber, das nur noch mit viel Aufwand und Kosten um Funktionalität erweitert werden kann. Meist ist die Codebasis schon nach kurzer Zeit in sich selbst verwoben und reagiert deshalb fragil und unberechenbar auf Änderungen und neuen Anforderungen. Obwohl ich betonen möchte das Clean Code unabhängig des Prozessmodels effizient eingesetzt werden kann, also auch in klassischen Prozessmodelle wie Wasserfall oder V-Model, möchte ich dies besonders anhand agiler Prozessmethoden darstellen.

Mit folgender Grafik soll anschaulich gemacht werden, welchen Platz Clean Code als Entwicklungsmethode in der Softwareentwicklung einnimmt:


Wie wir sehen können gibt es nur eine Stelle an der tatsächlich das eigentliche System produziert wird. Während die umliegenden Ebenen entweder die Grundlagen oder die unterstützenden Rahmenbedingungen für die Produktion des Systems bereitstellen, ist das Generieren des Codes der Kern der Softwareentwicklung. Gehen wir kurz die Bereiche durch und schauen wir uns deren Aufgaben an:

Agile Frameworks, Vorgehensmodelle, Prozesse (Scrum, Kanban, LeSS, SAFe usw.):

Heute werden oft agile Vorgehensmodelle als Fundament für die Softwareentwicklung benutzt. Aber schon ein kurzer Blick in die diversen Whitepapers und Cheatsheets lässt erkennen, dass es sich hier nicht um eine Definition des Entwicklerhandwerks handelt. Keiner der Modelle gibt uns ein Werkzeug für die Tätigkeit des Softwareentwicklers in die Hand. Vielmehr versuchen die Modelle uns eine möglichst optimale Umgebung für die Entwicklung zu schaffen. Somit hilft uns keiner dieser Modelle bei den vielen technischen Entscheidungen die wir täglich bei unserer Entwicklertätigkeit treffen müssen. Ohne jetzt im Detail den Versuch zu unternehmen, was denn nun die einzelnen Aufgaben von Scrum und Co sind, erkennen wir das etwas anderes brauchen, um eine saubere und stabile Codearchitektur zu erreichen. Versuchen wir es mit dem nächsten möglichen Bereich:

Übersetzungsprozesse (IIBA, Volere, CMMI, BDD usw.):

Mit Übersetzungsprozesse sind Vorgehensmodelle aus dem Bereich Requirements Engineering sowie weitergehende Methoden wie Behavior Driven Development gemeint. Diese Techniken sind dazu bestimmt, aus einer in natürlicher Form oder Sprache vorliegenden Anforderung eine technisch realisierbare Aufgabe zu erzeugen. Im Gegensatz zu klassischen Modellen wie IIBA und Volere berücksichtigt Behavior Driven Development sogar den gesamten Entwicklungsprozess. Also von der Anforderung bis zum Release. Und obwohl BDD sogar Entwicklungsmethoden wie TDD miteinbezieht, ist es doch wie auch das klassische Requirements Engineering hauptsächlich dazu gedacht die fachliche Korrektheit einer Software sicherzustellen. Eine Aussage können wir aber auf dieser Ebene mit Sicherheit treffen: Die fachlichen Anforderungen sind im Gegensatz zu früher keine einmalig definierte Konstanten, sondern sie ergeben sich laufend aus den Bedürfnissen der Anwender sowie der modernen Marktsituation. Schnelllebigkeit ist hier Programm. Aber auch hier finden wir keine Methoden um eine gute Codequalität oder eine agile Softwarearchitektur sicherzustellen. Wenden wir uns daher der nächst tieferliegenden Schicht innerhalb der Softwareentwicklung zu:

Architektur (DDA, DDD, MDA, SOA, Microservice usw.)

In dieser Schicht befinden wir uns in der technischen Architektur einer Software. Es macht auf den ersten Blick den Anschein als würden in diesem Bereich die Codequalität und die Codearchitektur ausgearbeitet und sichergestellt werden. Zumindest ist es doch naheliegend, dass mit der Entscheidung ob wir nun eine Domain Driven, Model Driven, SOA oder gar Microservice Architektur benutzen, die strukturelle Arbeit erledigt ist. Es scheint als könne man nach dem Entwurf die Implementierung den Entwicklern überlassen und bekommt genau das implementiert, was zuvor bis ins Detail spezifiziert wurde. Aber entspricht dies auch der Realität? Geben einen diese Architekturmodelle genügend Werkzeuge für die tägliche Entwicklungsarbeit in die Hand? Die Erfahrung zeigt schnell dass dies nur in Ausnahmefällen so einfach und erfolgreich abläuft. Vor allem bei Software für die einen längeren Lebenszyklus geplant ist, verändern sich die technischen Voraussetzungen sowie die Anforderungen an die Funktionalität mit der Zeit doch erheblich. Ersichtlich ist dies vor allem durch den Einsatz von Frameworks und Bibliotheken Drittanbieter. Während sich der Entwurf einer Architektur und die daraus resultierende Codearchitektur im Zusammenspiel mit diesen Frameworks und Bibliotheken über einen gewissen Zeitraum bewährt hat, führen Änderungen der Drittanbieter zu veränderten technischen Anforderungen, auf die meist nur mit viel Aufwand reagiert werden kann. Somit muss sich eine Softwarearchitektur immer wieder den neuen Bedingungen anpassen. Bestimmte Architekturentwürfe zeigen sich dabei etwas geeigneter für Anpassungen, andere dagegen sind ab einem gewissen Komplexitätsgrad kaum mehr für Änderungen geeignet. Vor allem in monolithisch gestalteten SOA Systemen steigt die Aufwandskurve innert kurzer Zeit sehr stark an. Es soll Systeme geben die schon vor ihrer Einführung kaum mehr wartbar waren.

Mag es für einige Architekturmuster auch geeignete Sammlungen an Entwurfspattern geben, eine umfassende Hilfestellung bei der täglichen Entwicklungsarbeit stellen sie Aufgrund der fehlenden Praktiken und Prinzipien nicht dar. Dafür bewegen sie sich inhaltlich auf einem zu hohen Abstraktionsniveau. Ein oft bemühter Vergleich hilft uns hier dies etwas besser zu verstehen: Ein Arbeiter auf einer Baustelle, so gut er auch in seiner Arbeit ist, wird mit einer Architekturzeichnung alleine kein Haus bauen können. Denn er benötigt für den Hausbau viele Informationen die ein Architekt bei keinem Entwurf je angeben wird. In welchem Verhältnis wird Beton gemischt? Wie müssen die Rohrleitungen verlegt werden? Die Bodenplatten sind um 5 Millimeter zu breit, was nun?

Genau so muss auch der Entwickler immer wieder Entscheidungen treffen bei denen ein Architekturentwurf keine Hilfe sein kann.


Agile Entwicklungsmethoden (Pairprogramming, TDD, CI/CD, Codereviews usw.)

Widmen wir uns den innerhalb von Agile Frameworks oft benutzten Entwicklungsmethoden. Um einer Begriffsverwirrung vorzubeugen möchte ich kurz den Begriff "Entwicklungsmethode" für diese Serie an Blogbeiträgen definieren. Oft wird der Begriff "Methode" mit Prozess oder Ablauf gleichgesetzt. Nach dieser Definition wäre Scrum eine agile Entwicklungsmethode. Ich möchte den Begriff hier aber für etwas anderes gebrauchen. Daher werde ich Scrum, Kanban und Co. in diesen Blogbeiträgen durchwegs als Modelle, Prozesse oder besser noch als Frameworks benennen. Somit bleibt der Begriff "Entwicklungsmethode" den täglichen Handlungen oder Praktiken des Entwicklers vorbehalten. Vor allem durch den Vormarsch der agilen Modelle haben sich einige Praktiken als sehr geeignet herausgestellt, um die Qualität von Softwaresystemen sicherzustellen. Bevor die agilen Modelle ein Synonym für "Fast Delivery" wurden, gab es in der agilen Welt einen Ansatz der seinen Stellenwert nur noch schwer in der agilen Entwicklung behaupten kann: Quality First!

Wir treffen immer wieder auf drei Kräfte die bei der Realisierung einer Software aufeinander einwirken: Qualität, Budget und Zeit. Klassische Vorgehensmodelle mussten Aufgrund ihres Planungscharakters oft der Zeit den wichtigsten Platz einräumen. Frei nach dem Motto: "Egal was es kostet (Budget) und egal wenn es noch nicht ganz funktioniert (Qualität), wir müssen bis zu diesem Zeitpunkt liefern (Zeit)". Die versteckten Folgekosten durch die niedrige Qualität sowie die oft masslos überzogenen Budgets dieser Projekte führten trotz grossen Einsatzes aller Beteiligten zu beschönigten aber in Wahrheit katastrophalen Projektergebnissen. Somit war klar dass mehr Aufmerksamkeit der Qualität einer Software geschenkt werden muss. Test Driven Development stellt sicher das Funktionen eine klar definierte Qualität besitzen, schon bevor sie implementiert werden. Continous Integration / Delivery stellt sicher das Software in kleinen nachvollziehbaren Schritten entwickelt wird und jederzeit voll funktionstüchtig und auslieferbar ist. Pairprogramming beschreibt den Vorgang das schon während der Implementierung das Vier-Augen-Prinzip zu mehr Qualität führt, sofern es nicht spätestens bei einem Codereview zum Einsatz kommt.

Wir sehen also auf dieser Ebene für die Softwarequalität einige hilfreiche Praktiken. Etwas genauer betrachtet ist aber keiner dieser Praktiken eine Hilfestellung bei der Implementierung. Pairprogramming gibt uns keine Anweisungen wie verschiedene Klassen miteinander agieren sollen. TDD hilft uns nicht wenn es darum geht das passende GOF-Pattern für die Implementierung zu wählen. Und CI /CD stellt nicht sicher das der Code auch noch spät im Projektzeitrahmen robust auf Änderungen der Anforderungen reagiert. Auch auf dieser Ebene fehlt uns also etwas um die gewünschten Eigenschaften einer agilen Codearchitektur zu erreichen.

Schlussfolgerung:

Ich bemühe hier nochmals einen Vergleich der auzeigen soll warum die zuvor beschriebenen Ebenen der Softwareentwicklung alleine keine Vorgehensweisen sind die eine qualitative sowie flexible Codebasis sicherstellen:

Wir können das sehr gut mit dem Prozess in einem Restaurant vergleichen: Auch wenn das Restaurant schön eingerichtet ist, die Preise günstig sind und das Servicepersonal freundlich und kompetent ist werden wir nicht zufrieden sein wenn das Essen nicht schmeckt, das uns so kompetent serviert wird! Uns so wie der Koch seine Rezepte und seine Erfahrung einsetzt um gutes Essen zu produzieren, sollten auch die Entwickler ihre Rezepte, die sie aufgrund ihrer Erfahrung für die jeweilige Anforderung angepasst haben, bewusst einsetzen und täglich befolgen. Und die Prinzipien und Praktiken des Clean Code Developer sind eben solche Rezepte.

Damit sollte klar sein warum wir etwas brauchen was uns dabei hilft Software in der erforderlichen Qualität zu erstellen. Wie könnte ein Versuch aussehen Codequalität zu definieren? Einigen der folgenden Eigenschaften werden wir im CCD-Wertesystem wieder begegnen:

  • Evolvierbarkeit bei stabiler Aufwandskurve
  • Korrektheit
  • Testbarkeit (Qualität)
  • Robustheit (Neues Feature produziert keine neuen Defekte)
  • Lesbarkeit. (Verständlichkeit der Implementierung ohne Kenntnis technischer Details)

Warum sollte Code diese Eigenschaften aufweisen?

Gute Code-Qualität ist das Fundament einer flexiblen und stabilen Software!

Unabhängig vom gewählten Vorgehensmodell ist die Code-Qualität die Grundlage für den Erfolg eines Entwicklungsprojektes. Sie stellen sicher, dass die Vorteile eines Architekturentwurfs auch tatsächlich im Code vorhanden sind. Um dies zu erreichen ist es für ein Team aus Entwicklern notwendig ein gemeinsames Vorgehen bezüglich dieser Ziele zu definieren. Im Gegensatz zu älteren Handwerkstätigkeiten hat sich in der Softwareentwicklung noch kein gemeinsames Verständnis für diese Eigenschaften herausgebildet.

Dadurch lassen sich unter anderem folgende Ansprüche an CCD ableiten:

  • Iterative Verbesserung der Code-Qualität in Bezug auf die vorherig genannten Eigenschaften.
  • Synchronisierung und Erweiterung des technischen Know-How im Entwicklungsteam.
  • Kleine aber beständige Fortschritte im gesamten Team.
  • Laufendes Monitoring des Fortschritts.
  • Transparente Darstellung von erreichten und noch zu erreichenden Zielen.
  • Intuitives Einhalten von Entwickler-Regeln ohne dass für die tägliche Arbeit viel Dokumentation notwendig ist.
  • Spass am Handwerk der Softwareentwicklung!

Ich hoffe ich konnte euch die Notwendigkeit einer Methode wie wir sie mit Clean Code Developer vorfinden aufzeigen und freue mich wenn ihr auch beim nächsten Beitrag dabei seid. Dann werden wir uns der Frage widmen: WAS IST CCD?

Gerne verweise ich hier auf viele spannende Blogbeiträge zu den unterschiedlichsten Themen der Softwareentwicklung auf der Seite der adesso Schweiz AG!

Markus Wagner


FollowMe