Wer kennt das nicht, wenn Software-Schaffende – seien es Architekten, Berater, Entwickler, PO oder auch jeder andere am Projekt Beteiligter – abends bei einem Kaltgetränk oder auf einer Konferenz zwischen den Talks zusammenkommen, unterhalten sie sich gerne leidenschaftlich über ihre Projekte und Dinge, die gut oder eben auch nicht so gut laufen.
In dieser konkreten Gesprächskultur liegt eine große Stärke, und wenn man bereits ein paar mehr Projekte gesehen hat, zeigen sich oft Ähnlichkeiten zwischen den Projekten, auch wenn sie möglicherweise aus ganz verschiedenen Branchen kommen. Zoomt man ein wenig aus den konkreten Problemen heraus und abstrahiert sie etwas, so erkennt man Muster.
Diese Erkenntnis ist nicht neu. Spätestens seit dem Buch der "Gang of 4" [GoF] sind Entwurfsmuster (engl. Design Patterns) Basiswissen in der Softwareentwicklung. Da es Muster für positive Eigenschaften gab, brauchte man einen Namen für wiederkehrende ungewollte Eigenschaften, die meist als "Antipatterns" bezeichnet werden.
Vor etwa drei Jahren schlug (der leider letztes Jahr viel zu früh verstorbene) Stefan Tilkov bei einem internen Open-Space-Event vor, das Thema Antipatterns in der Softwarearchitektur genauer zu untersuchen. Er hatte hierzu einen hervorragenden Vortrag „Good enough Architecture“ ([Til20], Abbildung 1) gehalten.
Abb. 1: Stefan Tilkov, GOTO Conference 2020 [Til20]
Schnell konnte er uns mit der Idee anstecken, dass dies Thema viel größer ist und man eine Menge dieser Muster entdecken kann. Das Ergebnis ist eine Sammlung solcher Muster unter [AAP].
Diese Sammlung ist ein Anfang und bei Weitem noch nicht komplett – und wird es auch wohl nie sein, da sich mit der Weiterentwicklung der Softwareprojekte auch immer neue Probleme ergeben werden. Oft ist es auch so, dass durch technologische Veränderungen oder Änderungen der fachlichen Anforderungen die Entscheidungen, die in einer früheren Projektphase gut und angemessen waren, nun neu überdacht werden müssen. Diese evolutionäre Softwarearchitektur [For22] hat sich in den letzten Jahren zu einem Standardvorgehen entwickelt.
Architektur-Antipatterns können nun helfen, Anzeichen für notwendige Änderungen zu erkennen, und auch aufzeigen, wie andere Projekte damit erfolgreich oder auch nicht umgegangen sind. So wäre die Idealvorstellung, dass wir als Softwerker-Gemeinschaft schaffen, die Wiederholung der immer selben Fehler in verschiedenen Projekten zu vermeiden. Zudem können gut gewählte Namen für Antipatterns neues Vokabular schaffen, um auf schnelle Weise Architekturprobleme zu beschreiben, genauso wie dies bereits bei den gängigen Design-Patterns in der Softwareentwicklung schon heute Standard ist. Dies verkürzt Diskussionen und erleichtert gegebenenfalls auch Entscheidungen, wenn man auf bestehende Erfahrungen zurückgreifen kann.
Aufbau von Antipatterns
Aber was sind nun Architektur-Antipatterns? Alle Definitionen, die wir gefunden haben, spiegeln unsere Ansichten leider nicht komplett wider. Dies ist aber auch nicht so wichtig, solange man ein gemeinsames Verständnis dafür hat, was gemeint ist. Etwas salopp formuliert, sehen wir in Antipatterns alle Probleme vereint, die aufgrund technischer, organisatorischer oder menschlicher Eigenschaften über die Lebenszeit in einer Softwarearchitektur auftreten können.
Abb. 2: ChatGPT-Katalog Antipatterns
Am besten kann man dies an dem verkürzten Beispiel „Emotional Attachment“ aus dem Katalog kurz umreißen (das komplette Antipattern finden Sie online: architecture-antipatterns.tech/patterns/emotional_misattachment.html). Es wird nun kurz jeder Abschnitt beschrieben, gefolgt von einem kurzen Ausschnitt aus dem Antipattern in kursiver Schrift.
Abb. 3: ChatGPT zu „Emotional Attachment“
Name
Ein wichtiger Aspekt für ein Antipattern ist ein griffiger Name. Der Name soll die korrekten Assoziationen über dessen Inhalt wecken. Wie immer in der Softwareentwicklung kann und sollte man über Namen ausführlich diskutieren:
Emotional Attachment
Beschreibung
Hierauf folgt dann eine kurze klare Beschreibung, worin das Antipattern besteht und was die möglichen negativen Auswirkungen sein können:
Oft haben Softwareentwickler – oder auch einfach alle an einem Projekt beteiligten Menschen – Vorlieben für bestimmte Programmiersprachen, Architekturstile oder auch nur zu dem von ihnen entwickelten Stück Code. Es ist an sich eine gute Eigenschaft, positive Erfahrungen auf neue aktuelle Domänen zu übertragen. Es wird problematisch, wenn Entscheidungen aus emotionalen Gründen getroffen werden und dabei objektive Fakten außer Acht gelassen werden. Zum Beispiel, wenn der gewählte Ansatz oder einfach das Stück Code dem Problem nicht oder nicht mehr angemessen ist.
Beispiele
Der nächste wichtige Bestandteil sind die realen Projekterfahrungen, denn obwohl Antipatterns als Verallgemeinerung von ähnlichen Erfahrungen aus verschiedenen Projekten abgeleitet werden, sind die jeweiligen Kontexte der Projekte sehr unterschiedlich und spielen auch eine wesentliche Rolle. Das Ziel ist es, jedes Antipattern mit mehreren Praxiserfahrungen zu vergleichen. Ein Antipattern ist ohne Praxisbezug schwer zu verstehen. In dem Katalog hat jedes Antipattern mindestens eine Case-Study gegenübergestellt. Oft findet man auch mehr als ein Antipattern in einer Case-Study.
Beispiele kennt wahrscheinlich jeder aus der Praxis:
- Eine selbst entwickelte Bibliothek, die weiterverwendet wird, obwohl es (mittlerweile) bessere Open-Source-Lösungen gibt.
- Die Verwendung einer weiteren komplexen (funktionalen) Programmiersprache in einem Microservice, obwohl nur ein Entwickler diese beherrscht.
In den Antipatterns im Katalog wird auf eigene Case-Studys, aber auch auf externe verwiesen. Im Folgenden wird die Case-Study "BPMN Engine für ein Shop-Checkout-System" beschrieben. Es gibt aber auch sehr gut beschriebene Studien wie das Reengineering von Netscape oder die Venom-Studie von Gernot Starke [Sta20].
Abb. 4: ChatGPT zur Case-Study CORBA Do it yourself (DIY)
Warum ist es aufgetreten?
Die nächste interessante Frage ist, warum kam es dazu, dass in der bisher möglicherweise gut funktionierenden Architektur ein Antipattern auftrat. Denn in der Regel ist es nicht so, dass es einige schlechte Ideen waren, die das Antipattern verursachen, sondern meistens die Änderungen im Projektkontext. Manchmal gibt es bestimmte Kipppunkte, die dazu führen. Dieser Kipppunkt ist sehr wichtig, auch um zu verstehen, wann Handlungsbedarf besteht:
Man kann sehr leicht in diese Situation kommen, da wir als Menschen nicht immer rationale Entscheidungen treffen:
- So kann Angst eine Rolle spielen, eine falsche Entscheidung getroffen zu haben, oder die Befürchtung, die Zeit zu verlieren, die in alte Lösung geflossen ist.
- Oder auch einfach der Stolz auf die entwickelte Lösung, gepaart mit der Selbstüberschätzung, dass die eigene Lösung besser ist.
- Manchmal ist es auch die Ansicht, besser die Lösung eines bekannten Anbieters zu verwenden, bei dem man ein gutes Gefühl hat.
Lösung
Hat man die Ursache für das Antipattern gefunden, so bleibt die Frage, wie man es wieder auflösen kann, oder wie man noch besser erst gar nicht in das Antipattern hinein läuft:
So einfach, wie man in diese Falle gerät, kann man sie auch vermeiden und sich wieder lösen:
- Ein sicheres Projektumfeld mit einer ausgeprägten Fehlerkultur und wertschätzender Kritik hilft, Ängste abzubauen.
- Zudem eine neutrale, faktenbasierte regelmäßige Bewertung gegebenenfalls mit objektiver beziehungsweise neutraler Bewertungsvorlage.
- Und vor allem auch ein gutes Stück Selbstkritik, um auch eigene Präferenzen zu hinterfragen und Veränderungen als einen Weg zu begreifen, um Neues zu lernen.
Projekterfahrungen
Der wichtigste Bestandteil sind jedoch reale Projekterfahrungen (Case-Studys). Also Schilderung von Projekten, bei denen diese Antipatterns beobachtet wurden. Denn oft spielt gerade der konkrete Projektkontext, in dem Projektentscheidungen getroffen wurden oder eben auch nicht, eine zentrale Rolle für das Verständnis, warum es zu Fehlentwicklungen kam und wie damit umgegangen wurde.
Oft lassen diese Antipatterns sich nur schwer gegeneinander abgrenzen und treten in Kombination mit anderen Antipatterns auf. Auch Case-Studys sind in mehrere Abschnitte unterteilt, die sich ebenfalls am besten mit einer Case-Study – "DIY-Middleware" – aus dem Katalog beschreiben lassen, in dem das oben beschriebene Antipattern „Emotional Attachment“ auftritt.
Name
Auch hier hilft ein guter Name, schneller den Kontext zur Case-Study herzustellen. Daher sollte der Name beziehungsweise die Überschrift nicht zu lang sein:
DIY-Middleware in der Versicherungsbranche
Beschreibung, Kontext
Eine kurze Beschreibung des Kontexts und der Domäne:
Hierzu ein Beispiel aus der Vorzeit, als es noch eine Middleware namens CORBA (Common Object Request Broker Architecture) gab. Ohne genauer darauf eingehen zu wollen, ermöglichte CORBA die Kommunikation und Verknüpfung verteilter Services, die in unterschiedlichen Programmiersprachen entwickelt werden konnten, indem sie über einen zentralen Interface-Broker kommunizieren. Heute wird es kaum noch verwendet, damals war es aber eine wichtige Technologie. Auf der anderen Seite gab es einen proprietären Standard der Firma Microsoft namens DCOM, der half, ähnliche Anforderungen zu lösen.
Es handelte sich um eine Software für Versicherungsmakler. Die Kernkompetenz lag also nicht in der Middleware.
Die Firma war zu Zeiten der Dotcom-Blase stark gewachsen und Geld war in großen Mengen vorhanden. Oft wurden interne Framework-Teams aufgesetzt, die Basisbibliotheken schufen, die anderen Entwicklern deren Arbeit erleichtern sollten. Diese Teams hatten ein wenig das Gefühl von Eliteentwicklern. Die eigentliche Geschäftsdomäne spielte eine eher untergeordnete Rolle.
Die gute Idee
Dieser Abschnitt ist sehr wichtig, denn in der Regel gibt es für das Projektvorgehen gute Gründe. Diese Gründe zu verstehen, erlaubt die Einordnung in die eigene Projektsituation:
Kommerzielle Lösungen für CORBA hatten gefühlt hohe Lizenzkosten. Zudem mussten verschiedene Technologien verbunden werden, was immer hohen Aufwand bedeutete. Die anvisierte Lösung erschien ein guter Ausweg zu sein. Erste einfache Prototypen funktionierten gut und so wurde entschieden, dass sich künftig ein Team um diese Middleware kümmern sollte und alle anderen Projekte auf dieser Basis ihre Produkte entwickelten.
Zudem hatte man noch weitere gute Ideen für zusätzliche Features. Und wahrscheinlich hatten die Entwickler zudem Spaß daran, ein komplexes Stück Software zu bauen, statt sich mit der oft etwas trockenen Versicherungs-Domäne beschäftigen zu müssen.
Was waren die negativen Konsequenzen, was ist passiert?
Der zentrale Punkt – was war das konkrete Problem mit dem Vorgehen?
Allerdings war die Entwicklung einer so komplexen Middleware doch schwerer als vermutet, zumal keiner der Entwickler wirklich Erfahrungen mit einem solchen Projekt hatte. Es musste nicht nur ein Protokoll, sondern gleich zwei implementiert werden, mit all ihren Spezialfällen. Hinzu kamen viele versprochene Zusatzfunktionen, die als Alleinstellungsmerkmal angesehen wurden.
Die Middleware wurde auch als zentraler Aspekt des Produktportfolios im Marketing gesehen und musste in jedem Projekt eingesetzt werden. Allerdings gab es zahlreiche Fehler und Unklarheiten. Gefühlt konnte nahezu jedes Problem der Projektteams auf diese Spezialmittelware zurückgeführt werden. Allein die Installationszeiten, bis ein Entwickler seinen Arbeitsplatz eingerichtet hatte, waren astronomisch. Dies wurde dadurch verschärft, dass Dokumentation und Installationsroutinen kaum vorhanden waren, sodass nur wenige Experten – die Kollegen aus dem Middleware-Entwicklungsteam – alle Installationen und Probleme beheben mussten. Dies verzögerte alle Entwicklungen erheblich und verschärfte sich immer mehr.
Der Stolz auf die eigene Lösung und das Gefühl, eine überlegene Lösung geschaffen zu haben, verhinderte aber ein frühes Umschwenken.
Aufgetretene Antipatterns
Die Studie passt zu dem oben beschriebenen Antipattern "Emotional Misattachment", allerdings lassen sich auch Verbindungen zu "Domain Allergy", "Sunk Cost Fallacy", "Reinventing the Wheel" und anderen Antipatterns finden.
Nicht immer kann man eine Praxisschilderung eindeutig einem einzigen Antipattern zuordnen, da in der Regel in der Praxis mehrere gleichzeitig auftreten oder diese sich auch nicht so scharf gegeneinander abgrenzen lassen.
Lösung
Wie ist es ausgegangen oder wie hätte man das Problem lösen können? Was waren die Ergebnisse?
Das ist nicht immer bekannt, weil das Problem eventuell noch immer besteht oder wir nicht mehr Teil des Projekts sind usw.:
Die Lösung für das Problem wäre in diesem Fall relativ einfach gewesen, die Verwendung einer Standard-Middleware. In diesem Fall hat dann der Markt mit dem Platzen der Dotcom-Blase das Problem gelöst. Es fehlte nun das Geld, diese Middleware weiter zu betreiben, die Mitarbeiterzahl schrumpfte stark. Das Middleware-Team wurde aufgelöst. Projektteams entwickelten nun gezielt Problemlösungen auf der Basis von Standardsoftware.
Diese Case-Study wirkt möglicherweise ein wenig veraltet, aber tatsächlich tritt dieses Antipattern immer noch oft auf. Die Technologien sind verschieden: Sei es ein besonders sicheres Transportprotokoll zum Datenaustausch, Verschlüsselung auf dem Client, Generierung von Code aus einer DSL oder einem Diagramm. Immer wieder kommt es vor, dass Speziallösungen entwickelt werden, die besondere Eigenschaften aufweisen, die Standardsoftware nicht leistet. Diese Lösung hat dann möglicherweise erhebliche negative Auswirkungen auf den gesamten Entwicklungsprozess.
Dies zeigt, dass Antipatterns nicht einfach mit der Zeit verschwinden, sondern zeigt die Relevanz des Auffindens dieser Antipatterns.
Wie geht es weiter?
Wir haben in den letzten drei Jahren eine Menge Ideen für Antipatterns zusammengetragen. Leider hatten wir es bisher nicht geschafft, diese auch alle zu beschreiben. Antipatterns leben von Case-Studys, ohne eine gute Case-Study wird kein Antipattern veröffentlicht. Denn gerade erst der Praxisbezug veranschaulicht den Kontext, in dem das Antipattern auftritt. Leider entwickeln sich Antipatterns erst über eine längere Projektlaufzeit und eine einzelne Person ist immer nur in eine überschaubaren Menge von Projekten involviert.
Wichtig ist auch noch mal das Verständnis, dass die Beispiele keine Wertung beinhalten. In jedem System eines gewissen Umfangs und Alters treten mit der Zeit unerwünschte Eigenschaften zutage. Gerade weil man bei Softwarearchitekturen immer Kompromisse eingeht, die in der aktuellen Projektsituation angemessen sind, aber möglicherweise in der Zukunft überdacht werden müssen. So hat beispielsweise eine Cloud-Umgebung ganz andere Eigenschaften als ein klassische On-premise-Lösung von vor zehn Jahren. Wurde damals ein einheitliches normalisiertes Datenmodell bevorzugt, so ist dies in Anbetracht von Microservices-Architekturen heute eher nicht mehr der Fall. Dies zu reflektieren und einzuordnen, ist ein normaler Prozess des Lernens.
Aber auch Antipatterns müssen noch viele erstellt und gefunden werden. Wer sich hierzu berufen fühlt, kann sehr gerne auf unserer GitHub-Seite mitwirken (siehe Abbildung 5).
Abb. 5: Architecture Antipatterns, Webseite [AAP]
Auch persönlich ist das Schreiben von Case-Studys und Antipatterns eine positive Erfahrung, die hilft manchmal, negative Erfahrungen noch einmal zu überdenken und daraus zu lernen. Denn ist man ehrlich, so sind erfahrene Softwareentwickler und Architekten meist solche, die einfach mehr Fehler gemacht, aber eben auch daraus gelernt haben. Antipatterns helfen anderen dabei, diese Probleme zu vermeiden und sie anekdotisch zu erlernen, um die negativen Folgen vermeiden oder begrenzen zu können. Und manchmal hat es sogar einen positiven psychologischen Effekt, wenn man den Projektfrust, der ja immer wieder mal vorkommt, in positive schöpferische Bahnen lenken kann.
Ich habe an dieser Stelle kurz das Konzept der Architektur-Antipatterns-Sammlung vorgestellt. Die eigentlichen Antipatterns konnte ich aber nur kurz umreißen. In der Folge würde ich gerne an dieser Stelle noch einige Antipatterns und ihre Auswirkungen in der Praxis ausführlicher beschreiben.
Weitere Informationen
[AAP] Architecture Antipatterns, siehe:
architecture-antipatterns.tech/
[For22] N. Ford, R. Parsons, P. Kua, P. Sadalage, Building Evolutionary Architectures – Automated Software Governance, O‘Reilly Media, 2. Auflage, 2022
[GoF] E. Gamma, R. Helm, R. Johnson, J. Vlissides, Entwurfsmuster: Elemente wiederverwendbarer objektorientierter Software (Programmer‘s Choice), Addison-Wesley, 2009
[Sta20] G. Starke, Die VENOM Story, siehe:
www.innoq.com/de/articles/2020/11/strategische-anwendungsmodernisierung-mit-split-extract-strategien/
[Til20] S. Tilkov, Good enough Architecture, GOTO Conf. 2020, siehe:
www.youtube.com/watch?v=RtRpL3Ndi0c&t=0s
Du möchtest Zugriff auf alle unsere Inhalte? Dann teste jetzt 30 Tage SIGS+