Was ist guter Code für Software-Architekten?

Experten-Check: Was ist schöner Code?

Redaktion JAXenter

© shutterstock.com / patpitchaya

In unserem Themen-Schwerpunkt „Schöner Coden“ wollen wir uns der Frage stellen: Was ist eigentlich schöner Code? Kann man das auf ein bestimmtes Feature reduzieren? Hilft ein bestimmtes Tool oder Framework dabei, schöneren Code zu schreiben? Im ersten Experten-Check beantworten uns die Architektur-Experten Milad Jason Daivandy, Stefan Zörner und Uwe Friedrichsen diese Fragen.

Die Architektur-Experten

Milad Jason Daivandy entwickelt seit sechzehn Jahren Software, am liebsten verteilte Systeme (Grid Computing, SOA mit SOAP und REST, Webanwendungen) in Interoperabilitäts-szenarien. Ob als Entwickler, Projektleiter oder Abteilungsleiter – in seinem Werkzeugkasten aus Java, PHP und Groovy ist immer Platz für Akronyme wie ATAM, FURPS oder arc42. Während Einsätzen als Software-Architekt und Berater in E-Science und Industrie hat er eine Leidenschaft für Messbarkeit von Softwarequalität entwickelt, die er (manchmal zu) begeistert mit seiner Umwelt teilt.

Uwe Friedrichsen

Uwe Friedrichsen ist ein langjähriger Reisender in der IT-Welt. Als Fellow der codecentric AG ist er stets auf der Suche nach innovativen Ideen und Konzepten. Seine aktuellen Schwerpunktthemen sind Skalierbarkeit, Resilience und die IT von (über)morgen. Er teilt und diskutiert seine Ideen regelmäßig auf Konferenzen, als Autor von Artikeln, Blog-Posts, Tweets und natürlich gerne auch im direkten Gespräch.

stefan_zorner

Von der Bayer AG über IBM und oose zu embarc. Stefan Zörner blickt auf zwanzig Jahre IT-Erfahrung zurück und stets gespannt nach vorn. Er unterstützt in Architektur- und Umsetzungsfragen mit dem Ziel, gute Architekturansätze wirksam in der Implementierung zu verankern. Sein Wissen und seine Erfahrung teilt er regelmäßig in Vorträgen, Artikeln und Workshops. Stefan ist aktives Board-Mitglied im iSAQB und Autor des Buchs „Softwarearchitekturen dokumentieren und kommunizieren“ (Carl Hanser Verlag, 2. Auflage 2015).

Was hilft dir (technisch) beim schöner Coden? Welche Tools/Frameworks machen Code schön?

Milad Jason Daivandy: Erst einmal: die passende Musik. Stimmungsaufhellend und entspannend soll sie sein – aber nicht zu anregend. SomaFM ist da genau richtig. bezüglich „schöner Coden“ gebe ich Tools den Vorzug vor Frameworks, denn sie weisen mich effektiver darauf hin, wo mein Code potenziell hässlich ist. Und helfen mir besser dabei, aus hässlichem Code schönen Code zu machen. Kontinuierlich. Teilweise sogar mit quantitativer Unterstützung: die Rede ist natürlich von statischer Code-Analyse. Aus Platzgründen werde ich nicht auf Microservices und Versionsverwaltung eingehen können – möchte beides aber wenigstens erwähnt haben. 😉

Structure 101: mein Favorit, da es die Welten von Code und Modellierung kombiniert. Erstellt Softwarearchitekturmodelle auf Basis von Quellcode. Diese können interaktiv verändert werden, z. B. kann die Modularität verbessert werden. Dabei gibt’s Refactoring-Empfehlungen. Schließlich kann das graphisch erfolgte Refactoring auf Modellebene in die Code-Basis übernommen werden. Erleichtert das Management von Softwarearchitektur und Code-Qualität ungemein.

SonarQube: der große Analyse- und Reporting-Baukasten mit nützlichen Visualisierungen. Einfach in den CI-Flow einzubinden. Preview-Analysen aus der IDE heraus können mittelfristig die Produktivität steigern. Code-Reviews mit SonarQube-Unterstützung können effektiver sein. Und: einige Report-Typen sind auch für Nicht-Entwickler interessant und daher ein gutes Kommunikationsmittel. Allerdings ändert sich SonarQube häufig: Mit Version 5.2 ist das Feature der Dependency Structure Matrix weggefallen. Schade!

SourceMeter: ein sehr effektives Analyse-Werkzeug, das eine große Bandbreite relevanter Code-Metriken unterstützt – das SOLID-Herz wird sich freuen. Eine breite Unterstützung verschiedener Programmiersprachen und Metrik-orientierte Analysen auf Schwellwertbasis sind weitere Mehrwerte. PMD-Support ist auch dabei. Ich verwende es zwar noch nicht lange, finde aber die unterstützten Metriken und Analyse-Features vielversprechend!

Mein Tipp für die Einführung von SonarQube bzw. SourceMeter: die Bedeutung der unterstützten Code-Metriken und Features gut verstehen. Und diese begründet, priorisiert sowie stufenweise in die Softwareentwicklung einbinden.

Uwe Friedrichsen: Ich halte den Begriff „Schöner Code“ für sehr gefährlich, denn ich habe ihn häufig als Rechtfertigung für beliebige persönliche Präferenzen erlebt, die aus meiner Wahrnehmung den Code schlechter und nicht besser gemacht haben. Deshalb möchte ich hier als Gegenentwurf eine bewusst nüchterne Sicht auf Code vertreten. Guter Code muss grundsätzlich mindestens zwei Anforderungen erfüllen: Er muss die vorhandenen fachlichen und nicht-fachlichen Anforderungen implementieren. Er muss gut verständlich sein. Schlecht verständlicher oder gar unverständlicher Code lässt sich nur sehr schwer und meistens nur fehlerhaft ändern. Wichtig hierbei: Verständlichkeit wird von den Lesern des Codes definiert und nicht von dem, der den Code erstellt.

Leider habe ich bislang nur selten Code gesehen, der diese beiden Minimaleigenschaften ordentlich erfüllt, sodass Diskussionen über schönen Code meistens müßig sind. Aber angenommen, die genannten Minimaleigenschaften seien erfüllt, wäre schöner Code für mich Code, der die folgenden zusätzlichen Eigenschaften erfüllt:

Er muss leicht nutzbar sein (externe Sicht), d. h. die Schnittstellen, die er anbietet, müssen nutzungsorientiert sein. Häufig orientieren sich Schnittstellen an der internen Implementierung, d.h. sie exponieren einfach nur die Implementierung, ohne sich Gedanken um die Nutzer zu machen. Besser ist es aber, wenn man sich an den Nutzungsszenarien orientiert und man die Schnittstellen möglichst gut darauf ausrichtet – also UX-Design auf Code-Ebene.

Er muss leicht änderbar und erweiterbar sein – aus interner Sicht. Da Änderungen und Erweiterungen primär von (zum Zeitpunkt der Code-Erstellung zukünftigen) fachlichen Änderungen getrieben sind, bedeutet das, dass der Code ein gutes fachliches Design benötigt. Dann ist es nämlich in der Regel möglich, die zu ändernden Stellen schnell zu identifizieren und Änderungen lokal zu halten.

Für beide Eigenschaften braucht man keine besonderen Tools oder Frameworks. Papier, Bleistift und Hirnschmalz reichen dafür.

Stefan Zörner: Ich steige ab und an bei Projekten ein und will mitentwickeln. Dann orientiere ich mich an dem, was das Team als schön empfindet. Dabei hilft mir, wenn es das kommunizieren kann. In Form von Prinzipien, Checklisten etc. Im Idealfall unterstützen Werkzeuge dabei. Checkstyle-Regeln etwa oder IDE-Konfigurationen. Gern integriert in Versionsverwaltung und Build.

Bei welchem Fehler rollen sich bei dir die Fußnägel hoch? Was ist schlechter Code?

Milad Jason Daivandy: Prinzipiell alles, was die Änderbarkeit von Code stark einschränkt, aber mit ein wenig Disziplin vermieden werden kann. Einige Beispiele: Verletzung von Dependency-Injection: Konstruktoren sollen ermöglichen, dass man Objektgraphen sowohl für den Produktionsbetrieb erzeugen kann, als auch für Testbarkeit (z. B. für Unit- und Integrationstests).

DO: in Konstruktoren auf Feldzuweisung von extern übergebenen Dependencies beschränken.

DON‘Ts: Feldzuweisungen, die injizierte Dependencies (teilweise) überschreiben bzw. ignorieren. Oder statische Methodenaufrufe. Böse, da kopplungstreibend: wenn der Konstruktor nach Typen fragt, die er gar nicht direkt verwendet.

Wiederverwendbarkeit: Vererbung ist nicht immer der beste Weg für Wiederverwendbarkeit. Wenn es um Testbarkeit und Kohäsion geht, ist Komposition häufig effektiver.

Gottklassen: Jeder kennt sie und weiß, dass sie Änderungs- und Testaufwände in die Höhe treiben. Dabei sind potenzielle Gottklassen automatisiert über Indikator-Metriken ermittelbar (z. B.Weighted Method Count, Access to Foreign Data, Tight Class Cohesion). Trotzdem kommen sie immer wieder vor – muss nicht sein, da leicht vermeidbar.

Vererbung ist nicht immer der beste Weg für Wiederverwendbarkeit.

Nomenklatur: Wer keine eindeutige bzw. nachvollziehbare Nomenklatur für Module, Packages und Klassen einhält (z. B. nach Fachlichkeit), der verwirrt andere Entwickler.

Pseudomodularisierung: Klassen einfach nur in verschiedene Packages zu schieben, ist noch keine Modularisierung, falls viele Abhängigkeiten zwischen Klassen unterschiedlicher Packages bestehen bleiben.

Pseudo-Eleganz und Pattern-itis: ein Stück Fachlogik in möglichst wenige Zeilen zu packen, ist nicht elegant, falls das auf Kosten von Änderbarkeit geht. Auch vermeidbar: die Verwendung von Entwurfsmustern ohne entsprechenden Mehrwert. Beispielsweise Singletons und ihre Auswirkung auf Testbarkeit. SOLID einzuhalten ist zwar weniger sexy, dafür aber wesentlich effektiver.

Uwe Friedrichsen: Mich stört jede Form schlecht verständlichen Codes, insbesondere:

  • wenn er „over-engineered“ ist
  • wenn er im Trial-and-Error-Verfahren zusammengeschustert und dann nie in Ordnung gebracht worden ist
  • wenn ein Entwickler auf Krampf versucht hat, Tastenanschläge einzusparen
  • wenn ein Entwickler mit dem Code seine eigene Genialität zum Ausdruck bringen wollte.

Ein paar Anmerkungen zu den genannten Punkten:

„Over-engineering“ bedeutet, unnötige Komplexität, d.h. Komplexität, die nicht für die Lösung benötigt wird, aber den Code schlechter verständlich macht. Wofür? Der beste Code ist einfacher Code, aber einfachen Code zu schreiben ist sehr schwer. Das ist leider häufig das eigentliche Problem: „Kompliziert“ kann jeder, aber „einfach“ bedeutet viel Nachdenken.

„Zusammengeschusterten Code“ trifft man häufig in Umfeldern an, in denen die möglichst schnelle Entwicklung von Code deutlich höher gewertet wird als alles andere. Da wird dann so lange herumprobiert und abgefälscht, inklusive „Programming by Stack Overflow“, also dem Googeln nach einer möglichen Lösung auf Stack Overflow, gefolgt von Copy-und-Paste und Anpassungen nach dem Trial-and-Error-Prinzip, bis der Code irgendwie läuft. Das ist je nach Umfeld bis zu einem gewissen Grad nachvollziehbar, aber Gift für verständlichen und wartbaren Code.

„Tastenanschläge einsparen“: Weniger Code ist nicht automatisch besser verständlich oder wartbarer. Genauso wie Over-Engineering keine gute Idee ist, ist auch übertriebene Kompaktheit keine gute Idee. Die optimale Lesbarkeit und Verständlichkeit von Code liegt irgendwo in der Mitte von ausufernder Geschwätzigkeit und übertriebener Kompaktheit. Es geht darum, dass ein beliebiger Leser den Code möglichst schnell erfassen kann und nicht darum, dass der Code so kurz wie möglich ist. Das sind zwei grundverschiedene Dinge! Leider findet man immer noch viele Entwickler, die das gleichsetzen.

Eitelkeit hat in professioneller Software- entwicklung nichts verloren!

Und zu genialem Code gibt es eigentlich nur eins zu sagen: Eitelkeit hat in professioneller Softwareentwicklung nichts verloren! Code wird einmal geschrieben und Dutzende oder hunderte Male gelesen. Damit ist es absolut essenziell, für eine möglichst gute Verständlichkeit des Codes zu sorgen. Das Bedürfnis, seine eigene Genialität unter Beweis zu stellen, steht da nur im Weg. Guter Code ist ego-frei.

Stefan Zörner: Ich setze schlechten Code mit schwer verständlich und als Konsequenz schwer wartbar und im Extremfall als Zumutung für den Leser gleich. Die Fußnägel rollen sich bei mir auf Quelltextebene selten hoch. Ich leide eher unter schlecht organisiertem Code. Krasses Beispiel war im Rahmen eines Architektur-Reviews ein umfangreiches C-Programm, wo die zahlreichen Funktionen nicht nachvollziehbar in vielen Dateien „a5tt4gf2.c“ u.ä. organisiert waren (die Funktionen selbst hießen ähnlich sprechend). Die Namen hatten ursprünglich angeblich eine Bedeutung, dieser Code war den aktuellen Entwicklern aber nicht überliefert. Hatte was von Hieroglyphen.

Wenn du eine Eigenschaft nennen müsstest, die für dich schönen Code ausmacht, welche wäre das und warum?

Änderbarkeit halte ich für eine der wichtigsten Eigenschaften von Code.

Milad Jason Daivandy: Änderbarkeit halte ich für eine der wichtigsten Eigenschaften von Code, denn praktisch alle Softwareprodukte eint eine Konstante: Sie müssen irgendwann geändert werden (Erweiterungen, Korrekturen, Refactoring). Änderbarkeit bedeutet konkret

  • Analysierbarkeit, also Lesbarkeit sowie den Aufwand für Fehlerdiagnose und zur Ermittlung änderungsbedürftiger Bereiche.
  • Modifizierbarkeit, sprich den Aufwand für Refactorings, Fehlerbeseitigung oder Anpassung an veränderte Umgebungen.
  • Stabilität, also keine bzw. nur wenige böse Überraschungen nach Durchführung von Änderungen.
  • Testbarkeit und ihre Beziehung zu gutem Softwareentwurf ist immer wieder ein interessanter Punkt. Damit meine ich den Aufwand, der zur sinnvollen Prüfung von geändertem Code notwendig ist. Beispielsweise die Einsetzbarkeit automatisierter Unit-Tests und Integrationstests. Dies erfordert aber eine ausreichend gute Code-Qualität.

Uwe Friedrichsen: Das geht schnell, denn die Frage hatte ich schon in meiner Antwort zur ersten Frage beantwortet … 😉

Stefan Zörner: „Schöner“ Code erschließt sich dem Interessierten leicht. Hilfreich sind hier zielgerichtete Informationen, die über den Quelltext hinausgehen. Wie ist der Code organisiert (fachlich, technisch)? Hier können Bilder helfen. Welche Dinge sind einheitlich gelöst? Warum hat das Team bestimmte Bibliotheken und Frameworks ausgewählt? Oder war das vorgegeben? … Der Quelltext erzählt nicht die ganze Geschichte.

shutterstock_107815670Schöner Coden
In unserer Reihe zum Thema „Schöner Coden“ stellen wir Experten verschiedener Disziplinen die Frage: Was ist eigentlich schöner Code? Welche Eigenschaft hat schöner Code aus der Sicht eines Software-Architekten? Und wie blicken Tester auf dieses Thema? Hier finden Sie eine Übersicht der bisher veröffentlichten Experten-Checks:

Geschrieben von
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: