Marcelo Emmerich's Picture

Marcelo Emmerich

11 posts

Ist Blockchain "the next big thing"?

Nein ist sie nicht. Denn sie ist nicht "next", sondern schon mitten unter uns! Und damit meine ich nicht die langweiligen Use-Cases der Bezahlung mit Bitcoin in Online-Shops, sondern die Use-Cases, bei denen die wichtigsten Aspekte der Blockchain-Technologie (Dezentralisierung und Transaktionsintegrität) zum Tragen kommen. Beispielsweise gibt es diverse Ansätze, Flüchtlinge, die ohne Dokumente um Asyl bitten, mittels Blockchain-Technologie digitale Identitäten anzubieten. Andere Use-Cases gravitieren im Orbit dezentraler Börsen für alles mögliche (Strom zum Beispiel). Wer Google bemüht findet weitere Beispiele.

Aus diesem Grund haben wir uns frühzeitig mit der Blockchain beschäftigt und diese als Zukunftstechnologie identifiziert. Richtig interessant wurde das Thema für uns erst mit dem Erscheinen von Ethereum. Im Gegensatz zu Bitcoin und andere Kryptowährungen ist Ethereum eine Platform für verteile Anwendung auf der Basis von Blockchain-Technologie. Ethereum bietet Programmierschnittstellen, mit denen man auf die Blockchain zugreifen kann. Somit kann man Anwendungen entwickeln, die:

  • sehr hohe Transaktionssicherheit bieten
  • echt Server-less sind
  • immer und für immer laufen können
  • Verträge (smart contracts) implementiert, die eindeutig sind, automatisch ablaufen und fälschungssicher sind

Gehen wir die einzelnen Punkte im Detail durch:

Transaktionssicherheit

Die Transaktionssicherheit in der Blockchain basiert auf 3 Grundtechnologien:

  • Peer-to-peer Netzwerke
  • Starke Kryptographie
  • Redundanz

Peer-to-peer Netzwerke

Die Blockchain basiert auf einem Peer-to-Peer Netzwerk. In diesem Netzwerk kommunizieren sog. Knoten mit benachbarten Knoten. Somit kann ein Blockchain-Netz nicht abgeschaltet oder heruntergefahren werden. Dazu müsste man alle Knoten abschalten, was bei Millionen von Knoten überall auf der Welt nahezu unmöglich ist.

Starke Kryptographie

Divere Aspekte einer Blockchain basieren auf starke kryptographische Verfahren. Am wichtigsten für die Integrität der Blockchain sind Hashing Algorithmen. Die Blockchain, wie der Name schon sagt, ist im Grunde eine Kette von Blöcken. In dieser Kette sind alle Transaktionen gespeichert, die es jemals in der Blockchain gegeben hat. Immer wenn ein neuer Block dazukommt, werden Hashes aus den vorherigen Blöcken errechnet. Somit kann ein Block geprüft werden, indem alle Hashes vom ersten Block an (in Ethereum heiist dieser Block der Genesis-Block) bis zum aktuellen errechnet werden und mit dem des Blocks verglichen werden. Stimmen sie überein, ist der Block valide. Das Verfahren ist in der Praxis etwas komplexer und es gibt Unterschiede zwischen den verschiedenen Blockchain Netzen, das Grundprinzip ist aber immer gleich.

Redundanz

In Blockchain-Netze gibt es keine zentralen Server. Stattdessen gibt es die o.g. Knoten, die eine Kopie der gesamten Blockchain haben. Ja richtig, jeder Benutzer der Blockchain hat eine (mehr oder weniger aktuelle) Kopie der gesamten Blockchain. Somit ist es fast ausgeschlossen, dass ein Angreifer eine veränderte Kopie der Blockchain in Umlauf bringen kann, da es Millionen von Knoten mit "echteren" Versionen gibt, die die eines Angreifers verdrängen würden.
Aber diese Redundanz birgt auch den größten derzeitigen Nachteil der Blockchain-Technologie: Mangel an Skalierbarkeit. Wie oben beschrieben muss jeder Knoten die gesamte Blockchain verarbeiten.

Server-less

Wie oben beschrieben ist ein Blockchain-Netz ein Peer-to-Peer Netzwerk, das ohne zentralen Server auskommt. Damit werden, aus Sicht der Software-Entwicklung, echte Server-less Applikationen möglich. Der Code bzw. die Verträge werden Teil der Blockchain und sind irgandwann auf jedem Knoten repliziert worden.

Run always and forever

Wir haben oben gesehen dass man ein Blockchain-Netz so gut wie nicht ausschalten kann. Somit sind Anwendungen, die auf der Blockchain geschrieben wurden, immer da und laufen auch für immer. (Auch wenn das in der Praxis nur die halbe Wahrheit ist, aber mehr dazu in einem der folgenden Artikel)

Smart Contracts

Das Herzstück der Ethereum-Blockchain-Technologie, aus Entwickler-Sicht zumndest, sind die sog. Smart Contracts. Diese stellen, wie der Name schon sagt, Verträge dar, die als Code in der Blockchain hinterlegt werden. Ethereum Smart Contracts werden in einer JavaScript-ähnlichen Sprache, genannt Solidity entwickelt und können recht komplex werden.

Ausblick

Nach dieser kurzen Einführung werden wir weitere Artikel zu den einzelnen Themen veröffentlichen. Wir werden den Fokus auf die Entwicklung für und mit der Blockchain legen sowie adjazent gelagerte Themen wie die Entwicklung von sog. Oracles und wie man mit den inhärenten Skalierungsproblemen der Blockchain umgehen kann.

Warum git-flow hakt

Git ist heutzutage als de-facto Standard für Source Code Management kaum noch wegzudenken. Es existieren exzellente Produkte, die die Arbeit mit git vereinfachen, allen voran Github, Bitbucket und Gitlab. Nun stellt git erst einmal "nur" das Werkzeug zur Verfügung. Um damit professionell zu arbeiten, benötigt man auch einen Prozess, der in die Entwicklung hineingreift und bis zum Continuous Integration und Continuous Deployment geht. Eines der bekanntesten git Workflows ist git-flow. Den Grundlegenden Ablauf von git-flow ist hier zu sehen: git-flow
Man kann anhand des Diagrammes schon sehen, dass ein Szenario mit vielen Entwicklern, Branches, Versionen und Releases schnell komplex werden kann. Trotzdem ist git-flow ziemlich populär, da es eine gewisse Ordnung propagiert und Richtlinien vorgibt. Das ist zumindest die Theorie. In der Praxis macht sich seit geraumer Zeit Kritik breit, die meistens folgendes bemängelt:

  • Merge Konflikte.
  • Feature-Trennung
  • Probleme bei der Release-Planung

Ich werde im Einzelnen auf diese Punkte eingehen. Vorab möchte ich aber festhalten, dass das eigentliche Problem die langlebigen Branches sind. Langlebige Branches entstehen wenn die Arbeit, die in einem Branch erledigt werden soll viel zu umfangreich dimensioniert wurde, so dass der Branch zu lange existiert. Daraus resultieren die o.g. Probleme. Und git-flow neigt dazu, eben diese langlebigen Branches zu produzieren. Auch auf die Gefahr hin, dass ich wieder ins SCRUM-bashing verfalle, aber SCRUM und an SCRUM orienterte Tools erhöhen die Wahrscheinlichkeit von langlebigen Branches. Hier ein Beispiel aus der Praxis.

In Projekt XY wurde der (hervorrangende) Atlassian Stack (Jira, Bitbucket und Confluence) und (das weniger hervorragende) SCRUM eingesetzt. Sprich es gab User Stories, die es umzusetzen galt. Diese wurden im Jira verwaltet. Wenn also ein Entwickler eine User Story umsetzen sollte, wurde der Status der Story im Jira verändert (bspw. von "Ready for Dev" nach "in development"). Nun bietet Jira ein praktisches Feature. Man kann direkt aus der Story heraus ein Branch anlegen, der sich an den Namen der Story anlehnt. So wurde es gehandhabt, und so entstanden etliche langlebige Branches, weil die Entwickler nur in diesen Branch committed haben, bis die Story fertig war. Erst dann wurde gemerged.

Und dann traten die o.g. Problemen auf, auf die ich wie versprochen nun im Detail eingehe:

Merge Konflikte

Das ist glaube ich offensichtlich. Wenn es viele, langlebige Branches gibt, die unabhängig voneinander unterschiedliche Stände haben, und evtl. den gleichen Code verändern, wird es merge Probleme geben. Diese wachsen in Anzahl und Komplexität mit der Anzahl der am gleichen Code arbeitenden Entwickler, und können oft nicht automatisch aufgelöst werden. Das kosten Zeit und Nerven.

Feature-Trennung

Vielleicht kennt das der Eine oder Andere. Der PO fordert unvermittelt ein Release, der aus Business-Gründen Feature XY beinhalten muss. git-flow kennt da den Hotfix als Antwort. Was aber, wenn es Abhängigkeiten zu anderen, langlebigen Branches gibt? Das aufzulösen kann mitunter extrem aufwendig werden.

Probleme bei der Release-Planung

Die o.g. Punkte führen zum dritten und letzten Punkt. Es ist kaum möglich, den Merge-Aufwand für ein bestimmtes Release abzuschätzen. Da jeder Entwickler seit Tagen oder sogar Wochen nur in seinem langlebigen Branch arbeitet, kann keiner sagen, wie groß der Unterschied zwischen dem eigenen Code und der der anderen ist.

Trunk Based Development

Eine Möglichkeit, diese Probleme zu umgehen ist Trunk Based Development. Um die Definition zu bemühen, ist Trunk Based Development:

A source-control branching model, where developers collaborate on code in a single branch called ‘trunk’, resist any pressure to create other long-lived development branches by employing documented techniques, avoid merge hell, do not break the build, and live happily ever after.

Hier das entsprechende Bild dazu:
trunk based dev

In der git Welt würde man statt trunk eher master branch sagen. Ändert aber nichts an der Idee. Amüsant find ich allerdings die Tatsache, dass trunk ein Begriff aus dem alt ehrwürdigem Source Code Management Werkzeug Subversion ist. Amüsant deswegen, weil heutzutage viele Entwickler git für so überlegen halten, dass SVN nur noch mit Mitleid betrachtet wird.

Aber das nur am Rande. Warum ist trunk based dev also besser als git-flow? Hier einige der Gründe:

  • Es wird immer nur vom trunk gebrancht
  • die Branches sind kurzlebig, < 1 Tag
  • es gibt insgesamt weniger Branches
  • es wird daher auch mehrfach am Tag gebaut

Vor allem der letzte Punkt ist hier von großer Bedeutung. Um es hier ganz deutlich zu sagen, wer nicht mindestens täglich einen release-tauglichen Build erzeugt praktiziert kein CI!!. CI ist nicht die Verwendung eines oder mehrerer Tools. Wir machen nicht CI weil wir Jenkins im Einsatz haben. Wir machen CI weil wir mehrmals täglich release-taugliche Builds durch das ständige Mergen in den trunk durch unsere CI pipelines jagen, inklusive automatisierter Tests. Alles andere ist ein Antipattern, bekannt unter dem Namen CI Theater

Wir sehen also, dass die negativen Implikationen einer ohne Reflexion eingeführten Methode recht weitreichend sein können. Es lohnt sich, den eigenen Prozess rund um git und CI auf den Prüfstand zu stellen und ggf. trunk based development in Betracht zu ziehen.

Open Source: Fluch oder Segen?

Open Source Software (OSS) ist eine gute Sache. Man kann den Source Code einsehen und, falls nötig, diesen selbst erweitern. Getrieben wird die Arbeit oft von der Entwickler-Community, dadurch werden Bugs schneller gefixt und Fragen über Foren und Mailinglisten kurzfristig und unkompliziert beantwortet. Ist das zu wenig, bieten viele Unternehmen auch kommerziellen Support an.

Soweit die positiven Seiten von OSS. Die meisten negativen Seiten sind, so glaube ich, bekannt;

  • uneinheitlicher, oft schlecht dokumentierter Code
  • komplizierte Abhängigkeiten zu anderen Projekten
  • mangelnder cross-plattform-support
  • keine Installer, komplexer Buildvorgang

Eine etwas subtilere Problematik hat sich im Rahmen eines Kundenprojektes gezeigt. Unsere Erfahrungen möchte ich hier anekdotisch festhalten.

Technologisch gesehen ging es um die Implementierung von Audio- und Video-Streaming auf der Basis der Bibliotheken von https://www.ffmpeg.org/. Zur Einordnung falls nicht bekannt, ffmpeg wird als das "Schweizer Taschenmesser" der Videobearbeitung bezeichnet und ist ein Open Source Projekt. Es besteht zum Einen aus ein Paar Kommandozeilentools zum bearbeiten, konvertieren, streamen, analysieren und wiedergeben von Mediendaten, zum Anderen gibt es eine Handvoll Bibliotheken, die von Entwicklern in eigene Software integriert werden können, um die o.g. Funktionen flexibel einbauen zu können. Ein weiterer, wichtiger Aspekt ist, dass ffmpeg für fast alle Plattformen und Betriebssysteme verfügbar ist.

Wir sollten mit Windows anfangen, also war der Plan, eine DLL zu erstellen, die die ffmpeg Funktionen kapselt, so dass Konsumenten einfache Methoden wie startStreaming, stopStreaming usw. aufrufen können.

Als erstes wollten wir die richtige Version von ffmpeg auswählen. Dazu besuchten wir die ffmpeg Website und stellten fest, dass es dort nur entweder den Source Code oder die Kommandozeilentools gibt. Nicht aber die vorkompilierten Bibliotheken für Entwickler. Glücklicherweise fanden wir die Seite von http://ffmpeg.zeranoe.com/builds/, der aktuelle Builds anbietet.

Allerdings stellten wir als nächstes fest, dass unsere erste, einfache Implementierung sich nicht mit dem aktuellen Zeranoe Build bauen lässt. Offensichtlich hat sich die API an wesentlichen Stellen geändert. Interessant dabei ist, dass selbst die Beispiele aus der aktuellen Codebasis nicht mit der aktuellen Bibliothek kompilierbar sind.

Also gingen wir wieder auf die Suche (sprich Google, Stackoverflow, etc.) und fanden zuerst eine gut versteckte und schlecht dokumentierte Deprecation-Liste von ffmpeg, in der die alten Methoden stehen, die nicht mehr verfügbar sind und ein Paar kryptische Hinweise auf die neuen Methoden. Weiter fanden wir einen Blog-Eintrag eines ffmpeg Entwicklers, der beschreibt, wie man die wichtigsten Methoden nutzen kann. Nun konnten wir weiter arbeiten.

Die Freude währte aber nicht lange. Als wir anfingen, ernsthaft Features umzusetzen, insbesondere was den Support bestimmer Codecs anbelangt, bekamen wir erneut Probleme. Grund dafür war, dass der Zeranoe-Build nicht alle Codecs beinhaltete, die wir benötigten. Also mussten wir unsere eigene ffmpeg Version für Windows bauen. Um diese Geschichte abzukürzen, mehrere Tage später hatten wir nun unsere eigene Version gebaut und unsere Implementierung lief.

Naja, halbwegs zumindest. Wir waren weit davon entfernt, Video und Audio in ordentlicher Qualität in so etwas wie echtzeit übertragen zu können. Audio und Video hingen extrem hinterher und waren komplett unsynchronisiert, sprich es gab mehrere Sekunden Versatz zwischen Audio und Video.

Ich möchte hier nicht auf die Enzelheiten der Implementierung einer eigenen Videostreaming-Lösung eingehen, das würde den Rahmen sprengen. Nur so viel sei gesagt, es ist alles andere als banal, auch wenn man, wie bei uns der Fall, über Vorkenntnisse in relevante Bereiche (Videostreaming, GStreamer, mpeg2 Decoding mit JS) verfügt. Vor diesem Hintergrund verwundert es ein wenig, dass es genau zu dem Thema keine funktionierenden Beispiele oder Anleitungen gibt, weder von ffmpeg noch sonst von der Community.

Nach vielen Versuchen und durch extensives Studieren des Source Codes kamen wir der Sache zwar näher, hatten aber bei ein Paar Themen noch immer keine befriedigende Lösung. Also dachten wir, es sei an der Zeit kommerziellen Support für diese spezifischen Themen in Anspruch zu nehmen. Auf der Website von ffmpeg gibt es die passende Seite mit einer Handvoll namentlich genannter Entwickler, die je nach Schwerpunkt kommerziellen Support anbieten.

Wir schrieben einige an und schilderten unsere Problemstellung. Ungefähr die Hälfte meldete sich nicht zurück. Einer meldete sich sofort zurück und gab an, dass es nicht sein Spezialgebiet wäre und wir sollten doch Entwickler A und B ansprechen. Das hatten wir schon. Entwickler A versuchte zuerst, uns auf all die schlechten, veralteten Beispiele zu verweisen, die wir mittlerweile auswendig im Schlaf rückwärts rezitieren konnten. Nach langem hin-und-her bekamen wir folgendes Angebot, frei übersetzt klang das in etwa so: "mein Kumpel hat nach der Arbeit an 2 Tagen in der Woche jeweil 3 Stunden Zeit und kann das für EUR 200 die Stunde in einem Zeitraum von 3 Monaten erledigen". Damit war das für uns schon mal gestorben. Mit Entwickler B kamen wir etwas weiter, auch wenn dieser manchmal fast zwei Wochen brauchte, um zu antworten. Als wir dann sagten, dass wir keinen Rewrite der Software, sondern nur eine Beratung zu punktuellen Themen benötigen, hieß es hier sinngemäß: "das ist dann für mich nicht mehr (finanziell) interessant. Viel Erfolg.".

Es gab noch einen Entwickler C, der auch nach sehr langer Zeit reagierte, als es aber soweit war hatten wir die Probleme bereits selbst gelöst.

Das mag vielleicht ein extremes Beispiel gewesen sein. Open Source Projekte, hinter denen ein kommerzielles Unternehmen steht sind meist anders aufgestellt. Allerdings ist die Software-Branche nach wie vor auch auf den Einsatz von Open Source Software angewiesen, die "nur" von der Community betreut wird. Ich glaube es macht Sinn, sich bei der Auswahl der Tools und Bibliotheken dieser Aspekte zumindest bewusst zu sein.

Post-Agil

Vor über 15 Jahren wurde das Agile Manifesto aufgeschrieben und hat damit den Grundstein für eine Idee gelegt, die eine ganze Generation geprägt hat. Doch was ist heute noch von der ursprünglichen Idee übrig? Auf der einen Seite haben wir die stark kommerzialisierte SCRUM Fraktion, auf der anderen eine Vielzahl mehr oder weniger ernst zu nehmenden Derivaten, Erweiterungen und verwandten Methodologien. Einige davon werden teilweise als "post-agil" bezeichnet.
Viele Unternehmen spüren die Notwendigkeit, ihre Prozesse effektiver zu gestalten und versprechen sich von agilen Methoden die entsprechende Verbesserung. Allerdings ist es vor dem Hintergrund der o.g. Aspekte nicht trivial, die richtige Methode zu ermitteln.
Wir helfen unsere Kunden dabei, wirklich agil zu werden. Dabei gehen wir unvoreingenommen in die Bedarfsanalyse und beziehen nicht nur die IT in unserer Empfehlung. Nicht selten schlagen wir dabei ein post-agiles Verfahren vor.

Was ist post-agil eigentlich?

Um die Frage beantworten zu können man sich den geschichtlichen Kontext vor Augen führen. Die agile Bewegung wurden zu einer Zeit ins Leben gerufen, als es Gang und Gebe war, Software-Projekte nach dem Wasserfall Prinzip durchzufühen. Oft vergingen Monate, in denen keine einzige Zeile Code geschrieben wurde, sondern "nur" am Design und Architektur der Anwendung gefeilt wurde. Dies ist heute als BUFD (Big Up-Front Design) bekannt. Damals war der Ansatz, Software in kleinen Inkrementen und kurzen Zyklen zu liefern geradezu revolutionär. Insbesondere der Anspruch der XP-Bewegung (Extrem Programming), zu jeder Zeit ein lieferbares Produkt zu haben, stellte in Paradigmenwechsel dar. Aber wie gesagt, das war vor 15 Jahren. In der Zwischenzeit hat sich einiges getan, was zum Aufkommen des Begriffes "post-agil" geführt hat:

  • Kommerzialisierung. Agile Entwicklung ist heute ein Wirtschaftsfaktor. Man muss immer sehr genau hinschauen, gerade wenn große Consulting-Häuser pauschal SCRUM vorschlagen. Oft sind finanzielle Interessen dahinter. Schließlich kann man gut von SCRUM Zertifizierungen, Workshops, Bücher und Tools leben.
  • Begrifflichkeit. In einem anderen Artikel habe ich schon darüber geschrieben. Wenn vor die Wahl gestellt, wer wird sich schon dafür entscheiden, nicht "agil" sein zu wollen. Das Wort alleine impliziert schon eine Verbesserung, ohne die Tragweite des Commitments erkennbar zu machen.
  • Soziale Aspekte. Die Kritik vor allem an SCRUM als führende agile Methode hat auch eine Konnotation, die stark mit der sozialen Entwicklung der Software-Entwickler verwurzelt ist. Vor 15 Jahren waren Software-Entwickler noch mit dem Image des sozial gehandicapten Nerd verbunden, der das Sonnenlicht meidet und sich nur von Pizza und Cola ernährt. Dieses Bild hat sich gewandelt. Software-Entwickler heute sind meist gut situiert, integriert und sie sind, im Gegensatz zur Jahrtausendwende, recht viele. Es ist gesellschaftlich anerkannt, dass ohne uns nichts mehr funktionieren würde. Ohne Software würde kein modernes Auto fahren, kein Licht angehen, keine Heizung heizen, usw. Diese Macht und die Wahrnehmung in der Gesellschaft verändert auch das Selbstbewusstsein in der Branche. Vor diesem Hintergrund kann man vielleicht gut nachvollziehen, dass Programmierer heute Methoden in Frage stellen, die sie zwingen, mit Spielkarten und fiktiven Punkten zu "spielen", um Aufwende abzuschätzen, oder täglich die gleich klingende Formel des Daily Scrums zu rezitieren.
  • Reife des Berufes. Mit der oben beschriebenen Macht und der gesellschaftlichen Anerkennung kommt aber auch eine größere Verantwortung. Und das ist meiner Meinung nach der entscheidende Scheidepunkt, an dem wir heute stehen. Wir sind Teil einer mächtigen, globalen, wirtschaftlich starken und gesellschaftlich anerkannten Industrie. Es wird Zeit dass wir uns entsprechend verhalten. Die Art und Weise wie heute agile Methoden eingesetzt werden, spiegelt diese Werte nicht wider. Es ist nach wie vor möglich, sich nach den Regeln von bspw. SCRUM absolut korrekt zu verhalten und trotzdem keinen entsprechenden Wert zu erzeugen und die Verantwortung nicht zu übernehmen.

Aus diesen Gründen wird der Ruf nach einem "post-agilen" Ansatz immer lauter.

Post-agil: Definitionen

Um es vorweg klar zu stellen, es gibt keine eindeutige Definition des Begriffes "post-agil". Für einige ist "post-agil" lediglich die Anwendung der urspünglichen agilen Werte, wie sie im agilen Manifesto stehen. Dort wiegen:

  • Individuen und Interaktionen mehr als Prozesse und Werkzeuge
  • Funktionierende Software mehr als umfassende Dokumentation
  • Zusammenarbeit mit dem Kunden mehr als Vertragsverhandlung
  • Reagieren auf Veränderung mehr als das Befolgen eines Plans

Andere wiederum haben ein "post-agiles Manifesto" erarbeitet, dieser lautet, vereinfacht ausgedrückt: wenn es funktioniert, tu es. Wenn es nicht funktioniert, lass es. Und dann gibt es wieder Tendenzen, die Idee von post-agil zu kommerzialisieren, wie z.B. Modern Agile. Dabei wird das Konzept auf mehr als nur die Softwareentwicklung ausgeweitet.

The conventic way

Wir glauben, dass es keine "one-size-fits-all" Methode gibt. SCRUM ist nicht die pauschale Lösung für alle Software-Projekte. Jeder Kunde und jedes Projekt hat eine eigene Historie und steht an einer anderen Ausgangsposition. Für ein Unternehmen, das aus einem Wasserfall-Prozess hinauswachsen möchte mag SCRUM die richtige Wahl sein. Für andere, die schon 5 Jahre SCRUM oder Kanban machen mag Programmer Anarchy, Mob Programming oder Extreme Programming eine Alternative bzw. eine Ergänzung sein. Daher lautet unser Credo:

Context over Convention

Wir analysieren den Kontext des Projektes in der Organisation, um darauf aufbauend die richtige Methode vorzuschlagen. Wir führen dieses Prinzip übrigens konsequent auch bis in die Entwicklung weiter. Somit scheuen wir auch nicht die Diskussion über "religiöse" Themen, wie z.B. "muss ich immer einen Test schreiben bevor ich den eigentlichen Code schreibe?" oder "brauchen wir wirklich eine MicroServices Architektur?". Es ist alles eine Frage des Kontextes, egal welche Konventionen gerade "in" sind.

Vom Monolithen zum Microservice

Einführung

Microservices sind in aller Munde, das Thema hat Hochkonjunktur. Überall kann man lesen, wie man Microservices Architekturen aufbauen kann und welche Tools dafür notwendig sind. Wer heute ein neues Projekt als Monolith designt gilt als old-school. Das ist zwar ein grober Fehler, mit einen Monolithen zu starten ist in vielen Fällen die besere Alternative, das ist aber nicht unser Thema heute. Ich möchte heute auf ein Thema eingehen, das uns vermutlich die nächsten Jahre beschäftigen wird. Wie können wir eine existierende, Monolithische Anwendung in eine Microservices Architektur überführen?

In diesem Artikel werde ich auf einige Strategien und Muster eingehen, die wir in vergangenen Projekten angewendet haben, um monolithische Applikationen in eine Microservices Architektur zu überführen. Ich werde explizit weder auf die Definition von Microservices eingehen noch bestimmte Tools erwähnen, das kann man woanders in ausreichender Tiefe und Breite lesen.

Ansatzpunkte

Bei allen Fällen die ich erlebt habe, stellte sich erst einmal die Frage, wo man ansetzen soll. Wie kann man sich der Thematik annähern? Betrachten wir zuerst die möglichen Ausgangslagen. Der gemeinsame Nenner ist meistens, dass es eine monolithische Anwendung gibt, mit der es Probleme gibt. Hier findet sich meistens schon der erste Hinweis darauf, ob eine Überführung in eine Microservice Architektur überhaupt Sinn macht. Schauen wir uns diese Gründe an:

  • Die Applikation ist schlecht oder gar nicht mehr wartbar
  • Die Applikation lässt sich nicht in akzeptabler Zeit bzw. automatisiert deployen
  • Das Deployment der Applikation ist immer mit Downtime verbunden
  • Fehler in bestimmten Teilen der Applikation führen zu einem Totalausfall der Anwendung
  • Die Applikation skaliert schlecht oder gar nicht
  • Die Applikation lässt sich nicht mit vertretbarem Aufwand erweitern
  • Teile der Applikation lassen sich nicht ohne extrem negativen Auswirkungen auf das Gesamtsystem austauschen

Können mehrere dieser Gründe herangezogen werden, so ist es zumindest empfehlenswert, weiter zu untersuchen, ob eine Microservices Architektur besser geeignet wäre.

Erste Annäherungsversuche

UI Trennung

Ein erster Ansatzpunkt kann sein, zu untersuchen ob die UI - sofern die Applikation überhaupt eine hat - vom Rest getrennt werden kann. Je nach Art der Applikation kann die Präsentationsschicht recht umfangreich sein. Umso mehr lohnt es sich, diese zu extrahieren. Allerdings muss hier evtl. ein Zwischenschritt eingeführt werden. Ist die Präsentationsschicht zu komplex, ist es ratsam, diese erst als einen zweiten Monolithen zu extrahieren und zwischen dem Frontend-Monolithen und dem Backend-Monolithen eine Schnittstelle einzuziehen. Erst im nächsten Schritt kann dann damit begonnen werden, diese millerweile kleineren Monolithen in Services aufzulösen.

UI Trennung

Monolithen Modularisieren (Orthogonale Transformation)

Viele monolithische Anwendungen sind logisch nach einem Schichtenmodell segmentiert. Stark vereinfacht sind diese Segmente von unten nach oben: Persistenzschicht, Domänenschicht, Anwendungsschicht und Präsentationsschicht. Grafisch dargestellt kann diese Architektur als übereinander gestapelte Rechtecke dargestellt werden. Bei komplexen Anwendungen kann es sinnvoll sein, die Architektur des Monolithen erst einmal orthogonal zu transformieren, indem man innerhalb des Monolithen modularisiert. Die Darstellung der resultierenden Architektur besteht dann aus nebeneinander stehenden Boxen. Ein solcher Monolith lässt sich einfacher in eine Microservices Architektur übertragen.

Orthogonale Transformation

Cross Cutting Concerns

Ein weiterer, vorbereitender Punkt kann sein, die sog. Cross Cutting Concerns zu extrahieren. Kandidaten hierfür können, je nach Art der Anwendung, sein: Logging, Encryption, Authentication, Messaging, usw. Diese Themen sind oft technisch gut kapselbar, so dass sich hieraus einfacher Services extrahieren lassen, die dann über eine definierte Schnittstelle angebunden werden können.

Cross Cutting Concerns

Produkte extrahieren

Während sich die o.g. cross cutting concerns eher auf einer technischen Ebene bewegen, haben komplexe Anwendungen auch eine ganze Reihe an fachlichen Komponenten. Viele dieser Komponenten sind fertige Lösungen, die irgendwann in den Monolithen, mal mehr mal weniger gut gekapselt, integriert worden sind. Diese sind ebenfalls Kandidaten für eine einfache Extraktion zu einem Service. Beispiele hierfür sind: Workflow Engines, Search Engines, Affiliate Marketing, Recommendation Engines, CMS, usw.

Zweite Iteration, eine Ebene tiefer

Im vorherigen Abschnitt habe ich die "Low Hanging Fruits" der Microservices Extraktion aufgeführt. Nun bleibt der harte Kern des alten Monolithen übrig. Hier kann man nicht nach Schema F vorgehen, da die Herangehensweise zu stark von der vorliegenden Software abhängt. Trotzdem haben wir Muster identifiziert, die sich in den letzten Projekten wiederholt haben. Diese bespreche ich im folgenden Abschnitt.

Asynchrone Verarbeitung

Oben hatte ich bereits aufgeführt, dass z.B. Messaging ausgegliedert werden kann. Nun bietet es sich an, sich die Komponenten im Monolithen anzuschauen, die asynchron, evtl. über Messaging, kommunizieren. Da hier erfahrungsgemäß die Kopplung geringer ist, bieten sich solche Komponenten an.

Asynchrone Verarbeitung

Datenhaltungsparadigmen

In vielen Anwendungen sieht man eine polyglotte Datenhaltung. D.h. es werden unterschiedliche Datenhaltungen für unterschiedliche fachliche oder technische Anforderungen verwendet. Ich empfehle diese Datenhaltungen sowie die Komponenten, die diese verwenden, zu untersuchen. Oft können diese Kandidaten für eine Extraktion sein.

Datenhaltungsparadigmen

Threads

Threads sind in manchen Fällen ebenfalls lohnenswerte Einstiegspunkte. In vielen Anwendungen werden Threads verwendet, um sehr spezifische Aufgaben auszuführen. Da ein Thread von Natur aus eine lose Kopplung und eine hohe Kohärenz zum Gesamtsystem haben sollte, bietet es sich an, diese auf ihre Extraktionsfähigkeit zu untersuchen.

Algorithmen

Algorithmen bestehen oft aus vielen Klassen oder Modulen, die nur zur Erfüllung der Aufgabe des Algorithmus da sind. Diese sind ebenfalls Kandidaten, um extrahiert zu werden, da hier auch eine lose Kopplung mit einer hohen Kohärenz gegeben ist.

Zusammenfassung und Ausblick

Die o.g. Ansätze sind aus unseren Erfahrungen in Projekten verschiedener Größe entstanden. Wir gehen fest davon aus, dass dieses Thema in den kommenden Jahren immer wieder auftauchen wird. Wir freuen uns auf den regen Austausch mit Kunden, Partnern und der Community, um Ideen und Erfahrungen auszutauschen.