Tag

Microservices Archives - embarc

Einheitlicher UI-Rahmen mit PHP und Server Side Includes (Micro Moves, Bauteil 8)

By | Inhaltliches | No Comments
Blog-Serie Micro Moves -- Logo

Bereits einer früheren Folge dieser Blog-Serie  hatten wir unterschiedliche Optionen für die UI-Frage rund um Microservices diskutiert, und auch zwei Extreme dargestellt. Wir haben uns dann für einen Weg entschieden, und dabei Nachteile in Kauf genommen. In dieser Folge zeige ich einen alternativen Ansatz, der diese Mankos vermeidet. Wie jeder Kompromiss hat aber auch dieser seinen Preis.

Er ist es wert, wenn wir beispielsweise beim Hinzufügen einer neuen fachlichen Funktionalität, die sich im Hauptmenü widerspiegelt, nicht viele bestehende Module anfassen wollen.

Um was geht es — ein Überblick

Diese Folge liefert einen einheitlichen Rahmen für das webbasierte Frontend, das bisher auf mehrere Bauteile (games, players, play, …) verteilt ist. Im Grunde bleibt es das auch. Wir ziehen lediglich wiederkehrende Teile heraus. So erhöhen wir die Wartbarkeit und reduzieren redundant implementierte Funktionalität.

Überblick, Bauteil 8

Die gemeinsamen Fragmente des UI-Rahmens liefert ein neues Modul homepage, das mit PHP 7 realisiert ist und in einem Apache httpd läuft. Die rote (8) markiert den Standpunkt des Bauteils im Gesamtbild („Sie befinden sich hier.“). Die Einbindung der Fragmente des UI-Rahmens erfolgt mit Server Side Includes (SSI) in unserem Reverse Proxy nginx, den wir in Folge 4 eingeführt hatten.

UI-Optionen und ein Kompromiss

Die UI-Frage im Zusammenhang mit Microservices: Trotz mehrerer Teile soll sich die Anwendung dem Benutzer “aus einem Guss“ präsentieren. Wie realisieren wir mit mehreren Teilen ein UI?

In Folge 3 dieser Serie haben wir zwei extreme Antworten für diese Frage beschrieben: Jeder Microservices hat sein eigenes UI bzw. es gibt einen gemeinsamen Client für alle. In der Abbildung unten seht Ihr sie als Optionen (1) bzw. (3). Dazwischen eine neue Option (2) als Kompromiss — die Heldin dieser Folge.

Die folgende Tabelle beschreibt die einzelnen Optionen und nennt Beispiele für die technische Umsetzung.

OptionBeschreibungUmsetzung
(1) Jeweils eigenes UIJeder Microservice bringt sein komplett eigenes UI mit. Die Integration zwischen den UIs erfolgt innerhalb des Browsers über Links.z.B. klassische HTML-basierte Web-Applikationen à la amazon.de, Web- MVC-Framework (Request/Response) garniert mit JavaScript (etwa Spring Web MVC oder PHP Micro Framework)
(2) Plugin-AnsatzMicroservices integrieren sich über eigene UI-Anteile in ein übergeordnetes UI. Im einfachsten Fall enthält dieses nur die Hauptnavigation.z.B. Desktop-Applikation à la Spotify, Portalserver, anderweitig server- oder client-seitig eingebettete HTML-Fragmente (etwa mit Server Side Includes oder als Single Page Application z. B. mit AngularJS).
(3) Full ClientEin gemeinsames UI nutzt alle Microservices über deren Schnittstellen. Diese sind selbst UI-los und enthalten nur Geschäftslogik.z.B. Mobile-App à la YouTube für Smartphone und Tablet, nativ entwickelt für Zielsysteme wie iOS, Android etc. oder hybrid erstellt, etwa mit PhoneGap

Jeweils eigenes UI

Bisher in dieser Serie haben wir im Wesentlichen Variante (1) verfolgt. So ist games mit Java und Spring Web MVC realisiert, players mit Python und Flask. Beide liefern jeweils den gesamten Inhalt ihrer Seiten. Für den Benutzer wirkt es durch den gemeinsamen Nenner Bootstrap wie aus einem Guss. Ein Wechsel zwischen games und players wirkt nicht wie ein Bruch, weil die Oberflächen gleich gebaut sind.

Die Vorteile von Ansatz (1) kommen besonders dort zum Tragen, wo Teams für Vertikalen verantwortlich sind und unabhängig arbeiten wollen:

  • Das Team hat große technologische Freiheiten im UI
  • Funktionalität ist vom Team vollständig (inkl. UI) lieferbar, unabhängig von anderen Teams

Full Client

Full Client so

Das Modul play unserer Serie deutet dagegen an, wie Ansatz (3) funktioniert. Bei play handelt es sich um eine Single Page Application (SPA) in Vue.js. Sie greift auf andere Services (chess-diagrams, games via REST) zu.

Die Vorteile dieses Ansatzes liegen in der potentiell besseren (bzw. leichter erreichbaren) User Experience:

  • Inhalte und Funktionen aus verschiedenen Themen lassen sich nahtlos auf einer Seite integrieren – es gibt keine Brüche
  • ein einheitliches User Interface ist leicht erreichbar
  • ein spezialisiertes Team für optimales UX denkbar

In unserer Serie hier führte die Wahl von (1) dazu, dass wir Teile der Oberfläche, etwa die Navigation, mehrmals implementiert haben. Das JWT-Token aus Folge 7 haben wir gleich drei mal ausgelesen (1x in Java in games, 1x in JavaScript in play, 1x in Python in players). Wie können wir diesen redundanten Code vermeiden, und trotzdem die Module unabhängig voneinander inkl. Oberfläche entwickeln und deployen?

Transklusion als weiterer Lösungsansatz

Eine verbreitete Idee für Weboberflächen nach Option (2) bezieht die Inhalte der Seite(n) von unterschiedlichen Stellen (bei uns Modulen wie players oder games) und fügt sie an einer Seite zusammen. Als Buzzword fällt hier mitunter „Transklusion“, lt. Wikipedia „die Übernahme von einem elektronischen Dokument oder Teilen davon in ein oder mehrere andere Dokumente …“. Auch in der Angular-Szene ist dieser Begriff gebräuchlich.

Auf diese Weise ist es möglich, wiederkehrende Schnipsel der Oberfläche wie zum Beispiel die Navigation von zentraler Stelle zu beziehen und immer wieder einzubinden. Im Ursprung des Begriffes ist von Dokumenten die Rede, es kann sich aber auch um dynamische Teilinhalte handeln. Dann wird es interessant.

Die Einbinde-Idee kennt verschiedene Möglichkeiten zur Umsetzung. Sie unterscheiden sich vor allem durch das Programm, das die Gesamtseite zusammenbaut. Ort des Geschehens kann sowohl der Client (also der Web-Browser), als auch das Backend (ein Server) sein.

ClientBackend
Im Browser laden geeignete JavaScript-Routinen Teile (HTML-Fragemente) dynamisch nach und fügen sie in das Dokument ein. Das Einbinden der Schachbrett-Grafik aus chess-diagrams in play durch ein img-Tag fällt auch in diese Kategorie und ist in der Umsetzung noch schlanker.Auf der Server-Seite kommen Edge-Server, CDNs (Content Delivery Networks) oder auch Proxy-Server oder der Web-Server selbst in Frage. Standardisierte Technologien in diesem Umfeld: SSI (Server Side Includes) und ESI (Edge Side Includes). Darüber hinaus gibt es darauf spezialisierte Bibliotheken und Framework-Lösungen wie Tailor von Zalando.

Ich zeige im Folgenden eine Lösung mit SSI und PHP. Anschließend diskutiere ich Stolpersteine und Konsequenzen dieses Ansatzes.

Eine Umsetzung mit PHP-Schnipseln

In unserer Schachplattform illustrieren wir die Technik mit drei wiederkehrende Schnipseln:

  • Den Header, inkl. den JavaScript- und CSS-Ressourcen
  • Das Menu (Navigationsleiste), inkl. der Kennzeichnung des aktiven Moduls
  • Den Footer, inkl. Link zur About-Seite des Moduls

Dabei sind der zweite und dritte Schnipsel mit (überschaubarer) Dynamik ausgestattet: In der Navigation ist das aktive Modul in der Menu-Zeile hervorgehoben. In Abhängigkeit vom Anmeldestatus des Benutzers ändern sich die Links im rechten Teil des Menüs (Anmelden / Registrieren vs. Profil /Abmelden). Hier ein Beispiel:

Aktives Modul: games, Benutzer Peter Pan ist angemeldet.
Aktuelles (aktives) Modul: games, Benutzer Peter Pan ist angemeldet.

Beim Footer-Schnipsel ist die Jahreszahl des Copyrights dynamisch und der Link auf die About-Seite des Moduls abhängig vom aktiven Modul. Das folgende Bild zeigt die Platzierung der Navigationsleiste navbar und der Fußzeile footer in der Oberfläche.

Sichtbare Schnipsel in der Weboberfläche
PHP 7 Logo

Umgesetzt sind die Schnipsel mit einem neuen Modul: homepage, Quelltext wie üblich auf GitHub. Es ist in PHP 7 geschrieben und läuft in einem Apache HTTP Server. PHP ist laut Selbstauskunft „eine beliebte, universell einsetzbare Skriptsprache, die sich besonders für die Webentwicklung eignet.“ Als Nebeneffekt haben wir mit PHP eine weitere Programmiersprache im System — polyglott war ja ein Ziel dieser Serie.

Das homepage-Modul besteht aus einer Handvoll HTML-Seiten, teilweise mit eingebettetem PHP. Die Tabelle unten listet sie auf.

SeiteBeschreibung
header.phpKopf einer Seite mit head– und title-Tag und CSS für Bootstrap.
navbar.phpNavigationsleiste. Der Request-Parameter active setzt den hervorgehobenen Menüeintrag. Mögliche Werte bisher: „games“, „players“.
footer.phpFuß der Seite mit Links, enthält auch die JavaScript-Bibliotheken für jQuery und Bootstrap. Das Copyright-Jahr setzt es via PHP automatisch, der Parameter module beeinflußt den Link auf die About-Seite. Beispiel: „players“ -> /players/about.html
index.htmlHomepage der gesamten Anwendung. Statischer Inhalt, die drei Schnipsel unten bindet es ein.
about.htmlÜber das Modul homepage. Statischer Inhalt, die drei Schnipsel unten bindet es ein.

Wie bei den anderen Modulen gibt es auch bei homepage ein Dockerfile. Die Einbindung in das Gesamtsystem erfolgt in der Datei nginx.conf für den Reverse Proxy sowie in docker-compose.yml für Docker Compose.

Server Side Includes

Server Side Includes (kurz SSI) sind eine ziemlich archaische Technologie für Web-Server. Ein solcher führt, wenn er SSI unterstützt, die entsprechenden Skript-Anweisungen innerhalb eines Dokumentes aus, bevor er es an den HTTP-Client (den Browser) ausliefert. Zuvor ersetzt er die SSI-Anweisungen durch deren Ergebnis.

Die für uns interessante SSI-Anweisung ist include — mit ihr bindet ein Server (oft wiederkehrende) Dokumentteile ein, und reduziert so Redundanz und Wartungsaufwand. Hier ein Beispiel für das Einbinden einer Datei:

<!--#include file="footer.html" -->

Alternativ zu statischen Dateien können auch dynamische Inhalte eingebunden werden. Im folgenden Fall führt der Server das PHP-Skript aus und inkludiert das Ergebnis.

<!--#include virtual="navbar.php" -->

Anwendung in FLEXess

In FLEXess habe ich die wiederkehrenden Elemente (Header, Footer, Navigation) aus den HTML-Seiten, welche die Module players, games etc. liefern, gelöscht und durch SSI-Anweisungen ersetzt. Bevor unser Reverse Proxy sie an den Browser ausliefert, führt er sie aus und fügt so die Inhalte aus den Modul homepage ein. Die SSI-Konfiguration in nginx ist dabei einfach. Hier ein Ausschnitt aus der Datei nginx.conf im FLEXess-Modul reverse-proxy für das Modul players :

...
location / {
    ssi on;
    proxy_pass http://homepage:80/;
}
...
location /players/ {
    ssi on;
    proxy_pass http://players:8000/;
}
...

Die erste Anweisung lenkt Anfragen von der Document-Root auf das neue homepage-Modul. Dieses liefert von nun an die Startseite (/index.html) und das Favicon (/favicon.ico). Vor allem aber die zentralen Fragmente für Header, Navigation und Footer. Sie landen via SSI auch in die statischen Seiten von homepage selbst (deswegen ist SSI auch dort aktiv geschaltet). Wichtig aber vor allem die Anweisung „ssi on;“ in players. Auf diese Weise scant nginx in HTML-Seiten von dort nach SSI-Anweisungen und führt sie aus. Details zur SSI-Konfiguration entnehmt Ihr der Dokumentation von nginx.

In players ist der Einbau der Fragmente sehr einfach. Die verwendete Template-Engine unterstützt Basisseiten. Von einer solchen sind alle anderen Seiten abgeleitet. Hier die zentrale Basisseite für players mit den SSI-Anweisungen.

<!DOCTYPE HTML>
<html>
<!--# include virtual="/header" -->
<body>

    <!--# include virtual="/navbar?active=players" -->

    <div id="header" class="container">
        <div class="page-header">
        {% block header %}
        {% endblock %}
        </div>
    </div>

    <div id="messages" class="container">
    {% with messages = get_flashed_messages(with_categories=true) %}
      {% if messages %}
        {% for category, message in messages %}
          <div class="alert alert-{{category}}">{{ message }}</div>
        {% endfor %}
      {% endif %}
    {% endwith %}
    </div>


    <div id="content" class="container">
        {% block content %}
        {% endblock %}
    </div>

    <!--# include virtual="/footer?module=players" -->

</body>
</html>

Feinheiten

Noch zwei Details zur Implementierung: Zum einen müssen wir nicht footer.php o.ä. schreiben, es reicht footer. Mir war wichtig, dass die verschiedenen Module nicht wissen, dass die Homepage in PHP geschrieben ist. Schlimm genug dass sie wissen müssen, dass die Einbindung mit SSI erfolgt. Erreicht habe ich das durch eine Konfiguration des Apache httpd. Details dazu lest Ihr in diesem Beitrag von Alex Cican: „How to remove .php, .html, .htm extensions with .htaccess“.

Zum zweiten: In den Verwendungen in der Seite aus players oben tauchen Aufrufparameter auf. Beispielsweise active für den aktiven Menupunkt. Da das Fragment aus homepage nicht weiß, von wo es eingebunden wurde, übergeben wir diese Information. Alternativ zu den Parametern könnten wir auch versuchen die URL auszuwerten. Im Falle des angemeldeten Benutzers arbeiten wir nochmal anders. Nämlich mit dem JWT-Cookie aus Folge 7, das sich in PHP auch prima auslesen lässt.

ESI statt SSI?

Neben SSI zum Einbinden der Schnipsel wäre ESI (Edge Side Includes) ein gangbarer und vergleichbarer Weg. Der ESI-Standard ist neuer und umfangreicher als SSI. Auch dort gibt es ein include. Die Syntax der Anweisungen ist etwas moderner: XML statt HTML-Kommentare. Die Wahl hier fiel vorrangig deshalb auf SSI, weil unser Reverse Proxy nginx es unterstützt, ESI hingegen nicht. Eine Alternative zu nginx wäre hier Apache Traffic Server, der könnte auch ESI.

Stolperfallen

Die Sache mir SSI funktioniert in unserem Fall hier ganz prima. Es gibt dennoch Stolperfallen, die ich Euch nicht vorenthalten möchte.

Stolperfalle

Zum einen: Der Reverse Proxy (bei uns nginx) führt nur SSI-Anweisungen in Dokumenten aus, die er „sieht“. Konkret muss dafür SSI für das betreffende eingebundene Modul aktiv sein („ssi on;“). Zum anderen (jetzt kommt die Falle) darf der Content nicht komprimiert sein.

Apache httpd beispielsweise zippt Inhalte standardmäßig, bevor er sie zum Client sendet. Sie landen dann im Browser und werden dort entpackt, inklusive der nicht ausgeführten SSO-Anweisungen.

Entweder, Ihr gewöhnt dem Webserver in der Konfiguration das Zippen ab, wenn nginx die Inhalte per SSI anreichern soll. Oder Ihr konfiguriert nginx umgekehrt durch Header-Anpassung so, dass er komprimierte Inhalte nicht akzeptiert. Apache sendet sie dann artig unkomprimiert. Ich habe das auf dem zweiten Weg gelöst. Eine kurze Beschreibung dazu findet sich zum Beispiel bei Stackoverflow („With nginx, how do I run SSI on a page returned from another server?“).

Weiterleitungsziele ermitteln (Redirect)

Ein weiteres Problemhat zwar nicht direkt mit SSI zu tun. Aber es ist bei der Umstellung in FLEXess auf SSI zu Tage getreten. Module möchten mitunter ein HTTP Redirect (Status Code 3xx) senden.

In unserem Fall war das bei players nach dem An- und Abmelden eines Benutzers erforderlich. Der Grund: In diesen beiden Fällen setzt players entweder ein Cookie (beim Anmelden) oder entfernt es (beim Abmelden). Anschließend stellt players eine Seite dar, in welcher der Anmeldestatus korrekt in der Navigation angezeigt sein muss. Problem: Die Homepage ermittelt den Anmeldestatus aus dem JWT-Token des aktuelle Requests — die Änderung des Cookies ist erst mit dem nächsten Request aktiv.

Früher konnte players das intern klären. Jetzt ist die einfachste Lösung ein Redirect. Der Browser sendet dann einen neuen Request, bei dem der Cookie mit dem JWT-Token nach Anmelden enthalten ist, und nach Abmelden auch schon gelöscht.

Problem: players hängt unterhalb des Reverse Proxies. Für das Redirect-Ziel benötigt es die Original-URL. Konkret: Schema (http vs. https), Servername, Port, URL … Die einfachste Lösung hier war es im nginx die Konfiguration so zu ändern, dass dieser die Daten in HTTP-Headern an players weiterleitet („proxy_set_header“). Eine Beschreibung dazu liefert ein schöner Beitrag bei Digital Ocean: „Understanding Nginx HTTP Proxying, Load Balancing, Buffering, and Caching“.

Diskussion des Ansatzes

Positive Konsequenzen

Mit dem beschriebenen Ansatz lassen sich gleich drei Module in FLEXess von Code für redundante Funktionalität im Frontend befreien (games, players und play). Bei play ist es zudem nicht mehr erforderlich, dass es das JWT-Token im Browser per JavaScript auslesen kann. Das lässt sich nun verbieten („httpOnly“) und damit eine Sicherheitslücke schließen (siehe XSS-Angriff).

Chat

Der größte Vorteil ist sicher, wenn ein weiteres Modul hinzukommt, dass den Rahmen der Weboberfläche nutzen und sich in der Navigation einnisten möchte. Es ist nun erforderlich nur zwei Module anzupassen und neu zu deployen: das neue Modul selbst und das angepasste homepage-Modul. Vorher hättet Ihr alle Module anpassen müssen, in denen die Navigation auftaucht.

Änderungen im zentralen Design oder eine Aktualisierung der Bootstrap-Version sind nun auch an zentraler Stelle möglich. Ein einheitlichen Aussehen lässt sich ebenfalls leicht realisieren.

Und der Preis dafür

Doch es gibt auch Nachteile. Einzelne Module können nun eben keine unterschiedlichen Bibliotheksversionen mehr im Frontend benutzen, und verlieren an Freiheit. Die Anwendung lässt sich nicht mehr schrittweise umstellen (falls gewünscht). Falls unterschiedliche Teams für die Module verantwortlich sind entstehen Abhängigkeiten zwischen diesen.

Zum Testen eines Moduls selbst ist zumindest für die Weboberfläche nun eine weitere Komponente erforderlich, die sich um SSI kümmert. Ansonsten fehlt die Navigation und das Ganze ist sehr trist. Dazu benötigt das zuständige Team nicht das ganze Modul-Arsenal. Es reicht ein nginx, der statische Inhalte einfügt, wenn der Test die Dynamik in der Navigation und im Footer nicht erfordert.

Muss es zentral sein?

Tatsächlich könnte ein Team auf den zentralen SSI-Ansatz für seine Module auch verzichten. Es liefert die betreffenden Schnipsel selbst und erhält sich so seine Freiheit. Das homepage-Modul würde dann als Vorschlag oder Angebot angesehen, nicht als Teil der Makro-Architektur. Auf dieser Weise bleibt Teams die Möglichkeit, neue Dinge einfach auszuprobieren in diesem Bereich. Auf Kosten des Mehraufwandes (für das Team). Und mitunter auch auf Kosten der Konsistenz der Oberfläche (für die Gesamtanwendung).

Wie es weiter geht …

Ein Blick auf den Bauplan verrät: Mittlerweile haben wir fast alle Teile beisammen. Was noch fehlt ist der mobile Client. Weiterhin möchte ich ein paar querschnittliche Themen rund um den Betrieb diskutieren (Deployment, Monitoring, Tracing, Logging …). Bleibt also spannend.

Fragen und Anregungen sind natürlich jederzeit willkommen. Per Kommentar hier im Blog oder gerne auch per Maildirekt an mich …

CUT: Richtig schneiden (5C-Design, Teil 2)

By | Allgemein, Inhaltliches | No Comments

Je unabhängiger ein Baustein ist, desto einfacher wird er zu handhaben sein. Schneide Bausteine so, dass sie sich möglichst gut voneinander abgrenzen.

  1. Software-Entwurf: Ein Blick zurück und nach vorn
  2. CUT: Richtig schneiden
  3. CONCEAL: Verbergen
  4. CONTRACT: Schnittstelle festlegen
  5. CONNECT: Verbinden
  6. CONSTRUCT: Aufbauen
  7. It´s a Wrap: Zusammenfassung

Um Komplexität dauerhaft beherrschbar zu machen, gibt es kaum eine Alternative dazu, diese in einzelne kleinere Teile zu zerlegen. Dafür muss man sich zunächst einmal die Frage stellen, an welchen Grenzen diese Abgrenzung denn am besten funktioniert. Wie findet man diese? Im Endeffekt wird der Programmcode der Lösung ein Abbild der fachlichen Anforderungen sein. Die möglichen Grenzen müssten demnach bereits in den Anforderungen auffindbar sein. Warum eine solche “fachliche Grenzziehung” (auch Vertikalität genannt) zu mehr Eigenständigkeit der Bausteine führt möchte ich anhand eines Beispiels verdeutlichen.

Schichten vs. Vertikale Architektur

Abbildung 1 zeigt ein nach klassischer Manier in technische Strukturen zerlegtes System. Daraus ergeben sich die dort abgebildeten Schichten, manchmal auch Layer genannt. Damit werden vorrangig die technischen Aspekte der Lösung betont. Dies hat den Vorteil, dass Entwickler passend zu ihren Stärken Strukturen im Code wiederfinden. Es werden außerdem querschnittliche Themen wie Persistenz gleichartig behandelt, was meist auch gewünscht ist. Auch das User-Interface wird für den Benutzer hier wohl ein durchgängig flüssiges Erlebnis darstellen. Aber: Sobald der Wunsch auftaucht, in irgendeinem der bestehenden Features ein weiteres Eingabe-Feld hinzuzufügen, zieht dies eine Kaskade an Änderungen in allen Layern nach sich. Man beginnt in der DB, zieht dies dann im DB-Access-Layer nach, danach in der Service-Schicht und zum Schluss im UI. Auch wird ein Ausfall einer niedrigeren Schicht sich immer auch auf alle Schichten darüber auswirken. Solch technische Strukturen sind demnach nicht wirklich eigenständig.

Abb. 1: Schichtenarchitektur

Die Alternative zu technischen Strukturen sind fachliche bzw. vertikale Strukturen (siehe Abb. 2). Hier wird besonders die Fachlichkeit betont. Das heißt übrigens nicht, dass man bei näherem Blick in eine dieser fachlichen Strukturen nicht wieder so etwas wie Layer finden wird. Trotzdem: Der Aspekt, der der obersten Abstraktionsebene Form gibt, wird immer etwas stärker betont werden als der sekundäre Aspekt innerhalb dieser primären Struktur.

Abb. 2: Vertikale / Fachliche Architektur

Die Grenzen der fachlichen Zerlegung

Tatsache ist allerdings, dass vertikale Abtrennung in manchen Fällen etwas besser funktionieren wird, und in anderen Fällen wiederum nicht so gut. Die Anforderungen eignen sich nämlich nicht immer in gleichem Maß für eine solche Aufteilung. Manchmal sind bereits die Business-Regeln, die der Fachexperte formuliert, so dermaßen miteinander vernetzt, dass eine effiziente Zerlegung schwierig wird. Werfen Sie dazu bitte einen Blick auf die Architektur, die in Abb. 3 dargestellt ist. Es handelt sich dabei um einen Web-Shop, welcher nach allen aktuellen Regeln der Kunst in fachliche Microservices zerlegt wurde, während die User-Interfaces nach wie vor als monolithische Layer implementiert sind.

Zunächst ist bemerkenswert, dass man ein solch monolithische Design des UI in Microservice-Architekturen häufig antrifft. Hier möchte ich kurz innehalten und die Frage stellen, warum dem eigentlich so ist. Warum klappt hier die fachliche Zerlegung oft nicht so gut wie im Backend? Die Ursache ist bei einer nicht-funktionalen (oder qualitativen) Anforderung zu finden. Wenn ich dem User ein durchgängiges Erleben des UIs ermöglichen möchte, so ist ein vertikaler Architekturstil an dieser Stelle nicht besonders gut geeignet. Daran sieht man, dass qualitative Anforderungen ebenfalls Einfluss auf die optimal mögliche Zerlegung eines Systems haben können.

Im Backend wiederum scheint die vertikale Modularisierung prima geklappt zu haben. Im Service “Kundenkonto” werden die Daten gespeichert, die ich vom Kunden benötige um ihn in der Plattform zu registrieren. Dabei wird die Validität seiner Angaben entweder über eine EMail oder eine SMS geprüft. Aus diesem Grund haben wir das Thema “Kommunikation” hier mit rein gepackt. Weiters gibt es Services für die “Bestellung”, das “Lager”, die “Bezahlung” und die “Lieferung”. Querschnittliche fachliche Themen wie die Daten des Kunden (Zahlungsweise, Lieferadresse, Rechnungsadresse etc.) haben wir ebenfalls auf diese Services aufgeteilt wie das Produkt an sich (Preis, Lagerstand, Beschreibung etc.).

Das Ziel war Logik und Daten jeweils nahe beieinander zu haben um eine Architektur mit hoher Kohäsion und niedriger Kopplung zu erreichen. Dies ist hier auch ganz gut gelungen, wie ich finde. Würde mir das jemand als Architektur zum Review vorlegen mit der Fragestellubg, ob dies gängigen Best-Practices folgt, hätte ich zumindest auf den ersten Blick nichts zu beanstanden.

Abb. 3: Die einwandfreie Microservice-Architektur unseres Web-Shops

Eine neue Anforderung

Ab sofort soll es in gewissen Fällen möglich sein, frische Schnittblumen bei jeder Bestellung mit auszuliefern. Dies kann entweder über Bezahlung möglich sein, oder ab jeweils einem Umsatz von 1000 Euro einmalig als Gratis-Angebot. Dies ist allerdings nur möglich bei Lieferdiensten, die dabei auch mitmachen. Diese müssen nämlich die Blumen immer frisch bei örtlichen Blumenhändlern abholen. Außerdem ist dies nur möglich, wenn es in der jeweiligen Gegend auch einen Blumenhändler gibt, der mit uns kooperiert. Angeboten wird dies außerdem nur weiblichen Kunden. Für männliche Kunden wird überlegt evtl. später ein After-Shave als Bonus den Paketen beizulegen. Allerdings nur solange auch welche auf Lager sind. In welchem der Bausteine würden Sie diese Änderung verorten? Es gäbe dafür diverse Strategien:

  • Man schreibt einen neuen Service “Geschenke”, der genau dieses Feature abbildet.
  • Man gibt das neue Feature irgendwo dazu, z.B. bei Payment, Bestellung oder Lieferung.
  • Man extrahiert aus den bestehenden Services einen neuen namens “Produkt”, der Daten und Logik der Produkte beinhaltet und dabei die Geschenke als Sonderfall behandelt.

Jede dieser Lösungen führt dazu, dass sich die Kopplung zwischen den Services im Vergleich zur Situation davor vergrößert. Dies allerdings nicht, weil keine gute Arbeit geleistet wurde, sondern weil dies die Anforderungen selbst nötig machten.

Fazit

Es gibt nicht nur qualitative Anforderungen, die eigentlich immer querschnittlicher Natur sind. Es gibt ebenfalls funktionale Anforderungen, welche auf gewisse Weise übergreifend sind. Sie vernetzen bestehende Anforderungen und sind nicht so gut als Modul isolierbar. Sie führen dazu, dass sich die Software in Summe nicht so gut modularisieren lässt. Die Aufgabe ist, eine Struktur zu finden, welche möglichst gut zu den fachlichen Anforderungen passt. Außerdem haben Sie idealerweise noch die Möglichkeit, auf Änderungen der Fachlichkeit zu reagieren, indem Sie im Zuge eines Refactorings eine Restrukturierung vornehmen. Abhängig von der Komplexität der Anforderungen selbst wird Ihnen das manchmal besser gelingen, und manchmal sind dem gewisse Grenzen gesetzt. Wenn Ihnen das gelungen ist, geht es weiter mit dem nächsten der 5 C´s, nämlich: “CONCEAL: Verbergen” (Coming soon, stay tuned…).

ModulithFirst_HDowalil_InformatikAktuell

Modulith First! – Artikel von Herbert Dowalil auf Informatik Aktuell

By | Artikel, Publikationen | No Comments

Modulith First! Der angemessene Weg zu Microservices

Logo_Informatik_Aktuell

Modulith First! Der angemessene Weg zu Microservices
Autor: Herbert Dowalil
Artikel auf Informatik Aktuell
online erschienen am 05. März 2019

Hinter dem Microservice-Architekturstil steckt u. a. die Idee, mittels forcierter technischer Abgrenzung durch das Netzwerk die Motivation zur strukturellen und fachlichen Abgrenzung der einzelnen Module (dann Services genannt) zu erhöhen. Dies klappt beileibe nicht immer. Zudem bleibt die Frage, wo genau die Abgrenzung zwischen den einzelnen Services am besten funktioniert? Fachliche, vertikale Strukturen und Domain-Driven-Design sind in aller Munde, stellen aber ebenfalls kein einfach anzuwendendes Patentrezept für eine effiziente Abtrennung von Modulen und Services dar. In diesem Artikel werfen wir einen Blick auf vergleichsweise objektive Ansätze.

Artikel Online Lesen

follow us on Twitter – @embarced

Software Architecture Summit 2019

Modulschnitt in zeitgemäßen Architekturansätzen – Software Architecture Summit 2019

By | Publikationen, Vorträge | No Comments
„(Ange)messen zum Modulschnitt in zeitgemäßen Architekturansätzen“

Software Architecture Summit 2018

Die Erstellung einer Microservice-Architektur alleine garantiert noch lange keinen Projekterfolg. Eine Verteilung auf das Netzwerk hilft zweifelsohne dauerhaft Modulgrenzen einzuhalten, beantwortet allerdings nicht die Frage, wo diese Grenzen idealerweise zu ziehen sind. Fachliche Dekomposition wie im Strategic Design des DDD ist in aller Munde, stößt aber an Grenzen, wenn technische Querschnittsthemen die Fachlichkeit überlagern und liefert uns außerdem keinen Mechanismus zur Prüfung, ob die Abgrenzung der Services oder Module effizient erfolgt ist.

Auch früher war nicht alles schlecht, und längst nicht jeder Deployment-Monolith endete als Big-Ball-of-Mud. In dieser Session übertragen wir auf Metriken basierende Strukturansätze auf moderne Architekturstile, welche uns helfen, eben diese Modul- und Servicegrenzen an der richtigen Stelle zu ziehen. Dabei kombinieren wir Microservices mit Ansätzen wie Clean Architecture, Modulithen, SCS, MonolithFirst oder Right-Sized-Services und schaffen das Rüstzeug um die Fehler der Vergangenheit nicht zu wiederholen.

Zur Veranstaltung

follow us on Twitter – @embarced

szoerner_java_aktuell_makro_micro

Artikel in Java aktuell: Microservices und Makro­-Architektur

By | Artikel, Publikationen | No Comments
Microservices und Makro­-Architektur

In der Ausgabe 01/2019 der Java aktuell ist ein Artikel zu Makro-Architektur und Microservices erschienen. Sie finden ihn hier als PDF zum Download.

Java aktuell 01/19 Cover

Drei zentrale Entwurfsfragen bei vertikalen Anwendungsarchitekturen
Autor: Stefan Zörner
Artikel in Java aktuell 01/2019
online erschienen am 27. Dezember 2018
Artikel-Download (PDF)

Moderne Architektur-Stile wie Microservices oder Self-contained Systems lassen Teams, die einzelne Teile entwickeln, viel Freiheit bei Technologieentscheidungen. Drei Themen entpuppen sich jedoch regelmäßig als Kandidaten, um übergreifend adressiert zu werden, damit die Anwendung wie aus einem Guss wirkt oder andere Architekturziele nicht verfehlt. Dieser Artikel stellt die Fragestellungen vor und zeigt Antworten auf.

Artikel als PDF follow us on Twitter – @embarced

API_summit_ST

Evolutionäre Architektur – Stefan Toth beim API-Summit

By | Vorschau | No Comments

Im Juni 2019 sind wir mit einem Halbtagesworkshop in München beim API Summit vor Ort:

Die 4 Säulen Evolutionärer Architektur

Die 4 Säulen Evolutionärer Architektur
Sprecher: Stefan Toth
Vortrag auf dem API Summit 2019
Montag, 17. Juni 2019, 13.30 – 17.00 Uhr
Holiday Inn Hotel, München-Unterhaching
@apisummit_de

Microservices versprechen vieles – ein zentraler Vorteil ist die langfristige Adaptionsfähigkeit der technologischen und fachlichen Basis. In großen Vorhaben und Produkten mit langer Lebensdauer ist dieses Versprechen besonders attraktiv, allerdings gehört zu einer erfolgreichen Umsetzung mehr als die technische Adaption der richtigen Frameworks. In diesem Workshop wird deshalb der methodische/organisatorische Teil beleuchtet – häufig subsummiert unter dem Begriff der evolutionären Architektur.

Evolutionäre Architektur bemüht sich stetig um notwendige Änderungen und beteiligt möglichst viele Entwickler an der Weiterentwicklung der Architektur. Dabei werden Konzepte und Technologien lokal und unabhängig getestet, bevor sie entweder verworfen werden, lokal als Optimierung bestehen bleiben oder als breiter anwendbares Konzept in die Landschaft wachsen. Dieser Workshop zeigt die vier zentralen Säulen dieser Idee und liefert praktische Details.

API Summit 2019

follow us on Twitter – @embarced

HD_DZone_Visibility Metrics

DZone Article – Visibility Metrics and the Importance of Hiding Things

By | Artikel, Publikationen | No Comments
Visibility Metrics and the Importance of Hiding Things

DZone


Why is it important to hide the things a module contains from its consumers in microservice architecture? Hiding things is important when designing a sustainable architecture. There are a couple of ways to hide internal structures and design decisions from the outside world and from the consumers of a modules API. These days, microservices are very popular. The microservice community argues, that distribution over the network is the one and only way to actually hide the internals of modules (here services). We just need to take a quick look at good old Java, where we already have plenty of options for hiding, even without using tools or proprietary libraries.

Controlling this by using metrics and maybe even tool support can be crucial for success. Just recently I was wondering, how to measure how well a piece of software is in hiding things. Surprisingly there was no software metric and no tool so far that offered a possibility to measure this. The Visibility Metrics described in the article helped me to solve the problem..

..read more

 
follow us on Twitter – @embarced

Modularer Software Entwurf_HDowalil

Buch: Grundlagen des modularen Softwareentwurfs

By | Bücher, Publikationen | No Comments
Grundlagen des modularen Softwareentwurfs

Der Bau langlebiger Mikro- und Makro-Architekturen wie Microservices und SOA 2.0


Cover Grundlagen des modularen Softwareentwurfs, 2018

Autor: Herbert Dowalil
Deutsch, 224 Seiten, Mai 2018
Verlag: Hanser Fachbuch
ISBN: 978-3-446-45509-2

Das Buch bei Amazon kaufen
Beiträge des Autors im Hanser Update Blog

Die digitale Transformation der Gesellschaft bringt für bestehende IT-Landschaften neue Herausforderungen mit sich. Enterprise-Architekturen, welche sich oft durch ungeplant entstandene Komplexität auszeichnen, sollen plötzlich weiter wachsen. Klassische Muster für Enterprise-Architekturen geraten dabei an ihre Grenzen. Moderne Prinzipien und Muster werden entwickelt, um eben diese Komplexität in geordnete Bahnen zu lenken. Der Fokus dieses Buches liegt darauf, softwareintensive Systeme zu strukturieren und so den Bau effizienter und langfristig wartbarer Softwarearchitektur zu ermöglichen.


Erfahren Sie Grundlegendes zu verschiedenen Definitionen des Themas Softwarearchitektur, und wie diese in Wechselwirkung zur Organisation eines Unternehmens stehen. Lernen Sie die Prinzipien des modularen Softwaredesigns kennen. Durch den Einsatz entsprechender Pattern entsteht eine gut wartbare Codebasis, die dazu in der Lage ist, langfristig weiter zu wachsen. Muster langlebiger Enterprise SOA – die Königsdisziplin der Softwarearchitektur ist der Entwurf großer IT-Landschaften. Lesen Sie, wie sich die Muster gut strukturierten Codes auch auf die Strukturen einer Makro-Architektur anwenden lassen.

Monoliths_Microservices_Modularity

Monoliths, Microservices and Modularity – DZone Article

By | Artikel, Inhaltliches | No Comments
Monoliths, Microservices and Modularity

DZone


In this article, I want to have a look at this expected advantages, and if the microservice architectural style does live up to its expectations. Especially when compared to monolithic architectures. To do so, we are still lacking the definition of the term „Monolith.“ Some use that term for software, that grew to a total mess, completely lacking any structure. For this, I will rather use the term „Big Ball of Mud“ (BBoM). A monolith according to my definition is rather a software, built with one technology and based on modules that interact using the mechanisms of the particular technology they are built with. So the difference between microservices and monoliths is, that in a microservice architecture the modules are distributed, whereas in a monolith they are not. A BBoM can be distributed too, so this is certainly not a unique selling point of monolithic architectures.

read more

 
follow us on Twitter – @embarced

Software_Architecture_Summit2018_embarc

Software Architecture Summit 2018 – das Doppelte (Architektur-)Lottchen

By | Publikationen, Vorträge | No Comments

Vorschau: Mitte März 2018 sind wir mit zwei Workshops beim Software Architecture Summit in München:

„Chaos? Revolution? Evolution!“

Software Architecture Summit 2018



Chaos? Revolution? Evolution!
Speaker: Stefan Toth

Workshop auf dem Software Architecture Summit 2018
Dienstag, 13. März 2018, 10:00 – 13:00 Uhr
im Holiday Inn, München Unterhaching

Damit größere Systeme oder Systemlandschaften über einen längeren Zeitraum hohe Qualität ausstrahlen, sind sowohl technische als auch fachliche Änderungen unausweichlich. Die gesündesten uns bekannten Ansätze kümmern sich stetig um diese Änderungen und betrauen möglichst viele Entwickler mit der Weiterentwicklung der Architektur. Konzepte und Technologien werden lokal und unabhängig getestet, bevor sie entweder verworfen werden, lokal als Optimierung bestehen bleiben oder als breiter anwendbares Konzept in die Landschaft wachsen. Durch den harten Test des Lebens (bzw. durch den kontinuierlichen Kontakt von Entwicklern mit wichtigen Qualitätsmerkmalen) entstehen wertvolle Beiträge zu einer Architektur, die sich stetig weiterentwickelt. Evolutionärer Architektur.

In diesem Workshop stellt Stefan Toth den Zyklus evolutionärer Architekturentwicklung vor. Von Lernfenstern mit Experimenten und erlaubten Abweichungen vom „Standard“, über weich definierte Regeln und geförderte Innovation bis hin zur eingeschränkten Anwendbarkeit von überholten Konzepten. Beispiele aus realen Entwicklungsvorhaben verdeutlichen die Konzepte.

„Das doppelte (Architektur-)Lottchen – Makro- vs. Mikroarchitektur“

Software Architecture Summit 2018

Während in einer klassischen Konzern-IT Standards und Blaupausen für immer gleiche Anwendungsarchitekturen sorgen, betonen Microservice-Ansätze die technologische Freiheit. Zwei extreme Spielarten der Ausgestaltung von Makro- und Mikroarchitektur.

In diesem Mix aus Vortrag und kurzen interaktiven Elementen lernen Sie neben dem Konzept selbst auch die auf Ihre Ziele abgestimmte Richtung, die Sie in dieser Fragestellung einschlagen sollten. Wie sieht in Ihrem Kontext die Balance aus – was geben Sie für alle Elemente Ihrer Andwendung(slandschaft) vor, wo lassen Sie bewusst Spielraum? Und gibt es auch noch etwas dazwischen? Zu diesem Zweck passen wir organisatorische und technologische Trends wie 2-Speed/Bimodale Architekturen, Cloud und Domänenorientierung in das Entwurfsdoppel Makro und Mikro ein.

Zur Veranstaltung

follow us on Twitter – @embarced