Viele Softwareprodukte starten klein und bleiben früher oder später in ihrer Entwicklung stecken. Manche Produkte starten groß und schlagen am Anfang fehl oder kosten einfach zu viel. Hier möchte ich skizzieren, wie Software klein anfangen und zu einem großen System heranwachsen kann. Als Beispiel möchte ich hier einen Shop nehmen, der klein startet und über die Zeit eine große B2C-Plattform wird.

Aller Anfang ist schwer?

Fangen wir mit dem Gedankenspiel klein an. Wir benötigen eine Storefront mit den angebotenen Büchern und einen kleinen Check-out-Prozess. Damit es wirklich schnell geht installieren wir Wordpress und erstellen ein paar Seiten mit Büchern. Eine Suche gibt es nicht und wir setzen nur hier und da ein paar Warenkorb-Symbole mit Links, die auf unseren Check-out-Prozess zeigen. Für den Checkout verwenden wir eine kleine Rails-Applikation ohne Authentifizierung. Wir benötigen lediglich ein Formular, indem die Anschrift festgehalten wird. Die Bezahlung erfolgt offline per Vorkasse oder Nachnahme, wie in alten Zeiten. Bereitgestellt wird das ganze auf einem einfachen virtuellen Server. Die Kosten für das Aufsetzen und die laufenden Kosten sind überschaubar.

Für jeden Ausbauschritt füge ich eine kleine Tabelle ein, die andere Wahlmöglichkeiten enthält, die aus verschiedenen Gründen hintenanstehen:

Voraussetzungen

Möglichkeiten Pro Contra
fertige Lösung: Magento Text zu komplex,
kein Know-how vorhanden
Shopify zu teuer
selber bauen zu teuer,
zu aufwendig
Kombination günstig,
kaum Know-how nötig

Der erste Erfolg

Nun stellt sich heraus, dass die Zahl der potentiellen Kunden doch recht stark ansteigt und Wordpress diese Menge an Nutzern nicht mehr handhaben kann. Die erste Idee ist einfach ein CDN vorzuschalten, somit den Traffic abzuleiten und das Problem zu lösen. Da sich Wordpress allerdings schon länger als zu unflexibel gezeigt hat, wird ein Wechsel auf ein anderes CMS erwogen. Jekyll, ein sehr einfaches CMS, das statische Dateien aus Markdown-Dateien generiert bietet sich hier an. Ein Webserver liefert die Dateien direkt aus und bietet so genügend Performance. Der Check-out-Prozess kann aufgrund der guten Entscheidung vom Anfang einfach so bestehen bleiben. Die Daten der Bücher werden vorerst in maschinenlesbaren Markdown Dateien gesammelt und mit Git versioniert.

Voraussetzungen

Möglichkeiten Pro Contra
CDN keine Entwicklung,
zukunftssicher,
günstig
Kein Know-how vorhanden
Statisches CMS günstig,
unabhängig

Neue Bücher

Langsam gibt es Probleme bei dem einzigen Entwickler. Er hat zu viel zu tun und kann nicht mehr gleichzeitig Bücher einpflegen und den Shop weiterentwickeln. Deshalb wird für Jekyll ein Backend installiert, welches von einer neu eingestellten Person bedient wird. Die Daten werden nun nicht nur für das Ausliefern der Seiten im Internet verwendet, sondern auch für das Drucken von Prospekten und das Versenden von Newslettern. Dafür wurden zwei kleine zusätzliche Systeme ins Leben gerufen.

Voraussetzungen

Möglichkeiten Pro Contra
Wechsel auf anderes CMS anderes CMS ist für Benutzer ausgereifter
Jekyll-admin CMS bereits im Einsatz,
Know-how bereits vorhanden

Warenkorb

Durch Loganalysen und Kundenbefragungen zeigt sich, dass viele Kunden abspringen, weil sie mit den bisherigen Zahlungsmöglichkeiten nicht einverstanden sind. Auch treten immer wieder Betrugsversuche auf, so dass wir uns entscheiden neue Zahlungsmöglichkeiten durch die Anbindung eines Zahlungsdienstleisters einzuführen. Gleichzeitig soll der Checkout-Prozess durch einen richtigen Warenkorb erweitert werden. Weil diese zwei Funktionen schnell gebraucht werden und um die Tätigkeiten gut auf zwei Teams verteilen zu können, wird der Warenkorb als neuer Service aufgebaut, der durch Javascript in allen Seiten eingebettet wird. Die Idee der SCS und der Frontend-Integration stand hier Pate.

Voraussetzungen

Möglichkeiten Pro Contra
Shopsystem einführen Zahlungsdienstleisteranbindung bereits vorhanden nur Teile des Shopsystems werden verwendet
Checkout-Prozess erweitern vieles Notwendige schon vorhanden
Warenkorb zusätzlich einführen parallele Entwicklung,
einfache Einbettung in restlichen Shop

Suche

Mit hunderten bis tausenden von Büchern ist es für Kunden langsam nicht mehr sinnvoll möglich ihre Bücher zu finden, weshalb nun eine Suche benötigt wird. Es wird hier auf eine vorhandene SaaS Lösung gesetzt, da die Geschwindigkeit der Implementierung wesentlich wichtiger ist als die Details der Funktionalität.

Voraussetzungen

Möglichkeiten Pro Contra
fertige SaaS-Lösung mit Crawler kaum Implementierungsaufwand momentane Abhängigkeit von Dienstleister bzgl. Kosten und Funktionalität
ElasticSearch keine Lizenzkosten hoher Aufwand

Durchbruch

Der letzte Schritt zu einem ausgewachsenen Shop liegt noch in Skalierung. Dies wird spätestens beim nächsten Vorweihnachtsgeschäft wichtig. Um die zusätzliche Last ohne Ausfälle überstehen zu können, wird nun doch ein CDN eingeführt, welches die statischen Katalogseiten ausliefert. Der Warenkorb und der Checkout Service erhalten jeweils eine große, vom neuen Cloud-Hoster verwaltete SQL Datenbank und werden auf automatisiertes Scale-Out also horizontale Skalierung umgestellt.

Voraussetzungen

Möglichkeiten Pro Contra
Plattform ausbauen niedrigere Kosten Hosting-Wissen muss ausgebaut werden
Cloud Hosting weiter konzentrieren auf Applikationsentwicklung höhere Kosten,
Kosten nicht gut planbar

Rekapitulation

Es wurde jeweils ein günstiger Weg gewählt, der das weitere Wachsen nicht blockiert hat. Die Integrierbarkeit und Anpassbarkeit der jeweils ausgewählten Lösung wurde hierfür also bei jeder Entscheidung als gewichtiges Kriterium berücksichtigt. Die einzelnen Systeme können unabhängig skalieren und haben einfache Schnittstellen, durch die sie leicht austauschbar bleiben. Geholfen hat weiterhin, dass zu jeder Zeit die Aufgabe der jeweiligen Systeme klar abgegrenzt waren. Zugegebenerweise ist die Shop-Geschichte ein wenig konstruiert. Allerdings kann man sich zu jedem Zeitpunkt und für verschiedene Architekturebenen überlegen, inwieweit man sich auf einen solchen Verlauf vorbereiten kann.

Das Ziel sollte in jedem Fall sein die Architektur mitwachsen zu lassen und nicht in einer “gewachsenen Architektur” zu landen. Deshalb ist ratsam bei Weiterentwicklungsschritten die jeweiligen vergangenen Entscheidungen neu herauszuholen und nochmals zu prüfen. Als Beispiel hierfür dient das CDN, bei dem wir uns anfangs dagegen und später dann doch dafür entschieden haben. Dieses Beispiel verdeutlicht auch, dass man kleine Erweiterungsschritte vornehmen sollte, auch wenn es sich manchmal im Nachhinein als kleiner Umweg entpuppt. Es ist doch meistens besser keine größeren Umbauten vorzunehmen und dabei evtl. mehrere Schritte zu weit zu gehen.

Architektur aus verschiedenen Blickwinkeln

Lösen wir uns hiermit also von unserem Beispiel und Betrachten die Aspekte einer agilen Architektur einmal auf verschiedenen Ebenen. Eine guter Anfang dafür ist Unterteilung der Architektur in Mikro- und Makro-Architektur. Dabei möchte ich hier die einfache Definition verwenden, in der Die Mikro-Architektur die Teile der Architektur sind, die ein Entwicklungsteam alleine treffen kann, ohne dass diese sich später unangenehm auf andere Teams auswirken können. Eine formellere Definition findet unter Self-Contained Systems? — Architektur auf mehreren Ebenen.

Mikro-Architektur

Gute Ansätze in der Mikro-Architektur können aus der der hexagonalen oder Zwiebelarchitektur abgeleitet werden, die altbewährte Ansätze der Kapselung von Schnittstellen, egal welcher Art, nutzt. Eine gute Idee ist weiterhin sich von Bibliotheken, Datenbanken, Drittsystemen, etc. zu entkoppeln. Im Zeitalter der (MVC-)Frameworks sind diese alten Tugenden ein wenig in Vergessenheit geraten, feiern aber momentan wieder ein Revival. Dies kann bei wachsenden Systemen dazu genutzt werden, Systeme leichter zu zerteilen. Ein Modulith z.B. mag sich gut dazu eignen unter entsprechenden Voraussetzungen in mehrere Services zerteilt zu werden. Wenn dies nicht der Fall sein sollte, bleibt immer noch die Möglichkeit in einer Systemlandschaft einzelne und noch kleine Systeme neu zu entwickeln. Wenn der Kontext gut gewählt war, lässt sich ein System womöglich einfach ersetzen.

Makro-Architektur

Wie im Beispiel schon angedeutet, wird die Makro-Architektur oft nicht durch die IT oder die Technik, sondern hauptsächlich durch die Fachlichkeit oder andere Umstände geprägt. In Diskussionen über dieses Thema fallen oft Wörter wie der “richtige Schnitt”, DDD oder Conway’s Law. Hier sind alle an der Architektur Mitarbeitenden gefragt nicht in die gefürchteten Fallen zu tappen und stattdessen die richtigen Weichen vorab zu setzen. Das ist natürlich ungleich schwerer als im Nachhinein aufzuräumen. Ein guter Rat ist hierbei nicht umkehrbare Entscheidungen in umkehrbare zu verwandeln. Es ist immer eine gute Entscheidung, sich andere Möglichkeiten offen zu halten und damit ein günstiges Revidieren in der Zukunft zu ermöglichen. So ist es auch nach einem sehr sorgsam ausgesuchten Schnitt von IT-Systemen wahrscheinlich, dass sich die Rahmenparameter ändern und somit eine Änderung der Architektur sinnvoll wird. Man sollte also immer ein Auge auf solche Änderungen haben und im Zweifelsfall die Vor- und Nachteile erneut abwägen. So manche gut ausgedachte Architektur ist einer guten Salamitaktik von der Seite der Anforderer zum Opfer gefallen. Dies kann man dem Anforderer aber nur bei Vorsatz ankreiden und versuchen dies in der Zukunft zu verhindern. In jedem Fall sollte man regelmäßig zwischen dem Reißbrett im sprichwörtlichen Elfenbeinturm und der Entwicklung wechseln und schauen, ob das momentane Zielbild der Architektur noch eingehalten wird und sinnvoll ist oder ob ein neues entwickelt werden sollte.

Infrastruktur

Die Infrastruktur nimmt sowohl in kleinen Projekten als auch in großen oft einen großen Teil des Arbeitsaufwandes in Anspruch. Deshalb ist es wichtig an den richtigen Stellen zu sparen und genau abzuwägen, ob lieber mehr Arbeitskraft oder Geld in die Infrastruktur fließt um evtl. lieber einen selbst-gemanagten Root-Server statt einer Full-Service-Datenbank und AWS-Lambda Instanzen oder Heroku-Dynos zu bezahlen. Bei wachsenden Nutzungszahlen oder Verlagerung der Nutzung kann es sinnvoll werden entsprechende Entscheidungen zu überdenken. Natürlich ist es nicht denkbar, alle paar Wochen die gesamte Infrastruktur umzukrempeln. Allerdings ist es durchaus sinnvoll, vorab diese verschiedenen Möglichkeiten im Kopf zu haben und die Migration der Infrastruktur vorab mit einzukalkulieren. Hier ist es z.B. empfehlenswert von Anfang an auf ein Konzept ähnlich der 12-Factor-App zu setzen, um einem zukünftigen Wachstum der Infrastruktur vorzugreifen.

Verschiedene Faktoren für entsprechende Entscheidungen sind etwa:

Diese Faktoren haben in der Regel starke wechselseitige Einflüsse. Zum Beispiel ist ein sehr niedriger Wissensstand für Heroku notwendig und die Skalierungsmöglichkeiten sind entsprechend hoch. Allerdings können die Infrastrukturkosten schnell um Zehnerpotenzen teurer als eine selbst gehostete Infrastruktur sein.

Lifecycle-Themen

Im Bereich des Lifecycle-Managements ist es ähnlich wie bei der Infrastruktur. Hier kann man sehr viel Energie investieren und Geld ausgeben. Für sehr kleine Produkte reicht hier schon eine IDE mit automatische laufenden Tests oder eine Entsprechung auf Konsolenebene. Wenn von Anfang an genug Arbeit in automatisierte Tests gesteckt wird, dann fällt der Weg über einen CI-Server bis hin zu automatisierten Deployments leichter. Weiterhin führen gut geschriebene Unit-Tests automatisch dazu, dass die Mikroarchitektur besser testbar und somit auch leichter lesbar und wartbar wird.

In größeren Installationen reicht ein simples Deployment mit entsprechendem Logging in Logfiles meist nicht mehr aus. Sobald mehrere Server oder Instanzen verwendet werden, wird es zunehmend schwierig den Überblick zu behalten. In diesem Fall ist es gut, wenn man bereits ein gutes Logging-Framework im Einsatz hat, um damit dann auf Lösungen wie den Elastic-Stack wechseln zu können.

Enterprise-Architektur

Der Schritt zur Enterprise-Architektur ist fließend. Dort werden allerdings Aspekte wie Budget, Kostenstrukturen dominant, so dass dies hier den Rahmen sprengen würde.

Architektur-Reviews

Um das ganze umzusetzen bieten sich regelmäßige Reviews an, die regelmäßig oder vor entscheidenden Entscheidungen durchgeführt werden. Dabei wird das aktuelle Bild der Zielarchitektur geprüft. Im gleichen Zug können dann die Qualitätsziele neu ermittelt oder geschärft werden. Wenn man sich an den agilen Werten orientiert ist es durchaus sinnvoll, sich regelmäßig mit der Architektur zu beschäftigen und sich dabei evtl. an Sprints aus der SCRUM-Entwicklung ein Beispiel zu nehmen. Natürlich sollten Architektur-Sprints wesentlich länger dauern, bevor man sich wieder zu einem Review zusammenfindet. Das liegt natürlich daran, dass ein Architekturreview einen wesentlich höheren Aufwand als ein Sprint-Review in Anspruch nimmt. Ein solches Architektur-Review kann sowohl intern als auch mit Hilfe externer Hilfe durchgeführt werden. Einige meiner Kollegen haben dies hier ausführlich erklärt.

Fazit

Eine gute Architektur eines Softwareprodukts oder einer Softwarelandschaft unterliegt einem stetigen Wandel und sollte regelmäßig überdacht und für zukünftige Vorhaben gewappnet sein, so dass der Fluss eines agilen Projektmanagements unterstützt werden kann. Allerdings sind einige wichtige Maßnahmen am Anfang notwendig, um sich den Weg nicht zu verbauen.