Pimp my Legacy mit “Self-Contained Systems”

Aufgrund von geänderten fachlichen Prozessen mussten in einem Teil eines von uns vor ca. 5 Jahren entwickelten Systems massiv Änderungen und Neuimplementierungen vorgenommen werden. Gerne hätten wir die Gelegenheit genutzt und ein komplettes Rewrite der Anwendung unter Berücksichtigung der aktuellen Trends wie z.B. microservices vorgenommen, allerdings war nach Aufnahme der ersten Anforderungen schnell klar, dass uns dies unter den gesetzten Rahmenbedingungen nicht gelingen würde: Die Änderungen mussten innerhalb von drei Monaten fertig umgesetzt werden.

In dieser kurzen Zeit erschien es undenkbar wesentliche Teile der existierenden Strukturen komplett herauszulösen. Stattdessen mussten diese im Altsystem an die neuen Anforderungen angepasst werden. Da hierfür tiefes Know-How der Altprozesse und der Software Struktur notwendig war, bestand kaum eine Möglichkeit weitere Entwickler ins Team zu holen, ohne dass sich die Einarbeitung der neuen Team-Mitglieder negativ auf die Erfüllung des Zeit-Ziels ausgewirkt hätte.
Mit der bestehenden Anzahl Team-Mitglieder wäre eine Termineinhaltung allerdings genauso unmöglich gewesen. Wir befanden uns also in einer Zwickmühle: Entwicklung am Altsystem skaliert schlecht in Punkto Entwicklungsgeschwindigkeit.

Daher entschieden wir uns einen wesentlichen neuen fachlichen Aspekt in ein eigenes separates System auszulagern und verfolgten hier die Idee des “Self-Contained System”. Self-Contained Systems basieren auf der microservices [2] Idee:

  • Es wird nicht ein großes, monolithisches System erstellt, sondern das Gesamtsystem in relativ kleine (fachliche) Services zerlegt. Jeder Service hat genau eine Geschäftsfunktion
  • Services sind sehr lose gekoppelt
  • Services sind einzeln installierbar und aktualisierbar
  • Microservices sind gegenüber anderen Services isoliert und autark, so hat auch jeder Service seine eigene Datenhaltung
  • Hoher Freiheitsgrad bei Technologieauswahl

Self-Contained Systems (SCS) greift diese Eigenschaften auf, definiert diese aber deutlich strikter und lässt somit weniger Raum für Interpretationen als dies bei microservices der Fall ist. Die wesentlichen Merkmale von SCSs sind [1]:

SCS

Self-Contained Systems

  • Jedes SCS ist eine autonome Web-Applikation
  • Jedes SCS gehört genau einem Team
  • Kommunikation zwischen SCSs oder anderen Systemen ist wo immer möglich asynchron
  • Ein SCS beinhaltet Daten und Logik
  • Eine SCS beinhaltet seine eigene UI, es gibt KEINE geteilte UI
  • Kein shared code: Es wird keine Business Logik mit anderen SCSs geteilt
  • Ein SCS hat seine eigene Infrastruktur, bzw. geteilte Infrastruktur sollte soweit irgend möglich vermieden werden

Architektur

SCS Architektur

SCS Architektur

Durch das Aufsetzen eines eigenen SCS für den neuen Funktionsbereich konnten wir von der Technologie der bestehenden monolithischen Anwendung abweichen und statt des dort verwendeten Eclipse RCP Frameworks auf UI Seite eine moderne Angular2 [3] Web Anwendung umsetzen.

Im Backend kommt Spring Boot [4] zum Einsatz, wodurch auch das Deployment der Gesamtanwendung als Fat-Jar sehr einfach zu realisieren war. Die Datenhaltung der Anwendung wurde aufgrund von Vorgaben des Kunden in einer Shared-Oracle Datenbank abgelegt, allerdings in einem gesonderten Schema, wodurch der Anspruch einer SCS an nicht geteilter Infrastruktur zumindest eingehalten werden konnte.

Integration in das Gesamtsystem

Die neu geschaffene Anwendung kann zwar autark arbeiten, allerdings muss sie sich natürlich in den Gesamtprozess integrieren und mit dem Altsystem Daten austauschen. Da SCSs laut Definition (siehe oben) wo immer möglich asynchron kommunizieren sollen, wurde hier ein Messaging orientierter Ansatz gewählt. Zu unserem Glück verwendet das Altsystem bereits Hazelcast [5] als “In Memory Data Grid”. Durch die Verwendung der Hazelcast Messaging Funktionen konnte die asynchrone Kommunikation somit sehr leicht umgesetzt werden. Hazelcast stellt hierbei – ähnlich wie bei JMS – Topics zur Verfügung, an denen sich Subscriber anmelden können. Stellt nun ein Knoten des Memory Grids eine Nachricht in einen Topic ein, wird diese allen angemeldeten Subscribern zugestellt.

Messaging via Hazelcast

Messaging via Hazelcast

Der Vorteil gegenüber JMS ist, dass Hazelcast im Speicher der Anwendung läuft und somit kein gesondertes Messaging System notwendig ist. Die Kommunikation findet dabei von Hazelcast Knoten zu Hazelcast Knoten über TCP IP statt.

Integration der SCS Web UI in den RCP Client

Integration der SCS Web UI im RCP Client

Auf UI Seite konnten wir zudem die Funktionen der Eclipse RCP zum Einbetten von Browser-Fenstern als Views in die Rich Client Anwendung verwenden um die neu geschaffene SCS zu integrieren.

Dem Endbenutzer ist somit ein einheitlicher Zugang zur neuen Anwendung ermöglicht worden. User, die bislang keine RCP Installation auf ihrem Rechner vorliegen hatten, können die neue Anwendung zudem auch ohne RCP Installation nutzen.

Die SCS im Browser

Die SCS UI im Browser

Dies ist insbesondere deswegen von Vorteil, da das in der SCS implementierte Feature von unterschiedlichen Fachbereichen genutzt wird und einige dieser Fachbereiche keinerlei andere Funktionen aus der RCP Anwendung benötigen.

Die beiden Screenshots zeigen die Varianten: Im RCP ist die Web-Oberfläche neben anderen Eclipse-Views zu erkennen, während sich die App in der Standalone-Ansicht im Browser als eigenständige Anwendung präsentiert. Da der RCP Client mit einer eigenen Navigation im linken Teil ausgestattet ist, wird die SCS eigene Navigation und Titelzeile, die im Browser zu erkennen ist, in der eingebetteten Variante ausgeblendet. Darüber hinaus wird bei der RCP Variante das Single Sign On der RCP Anwendung genutzt um auch die Authentifizierung Richtung SCS durchzuführen; in der Browser Ansicht muss dies durch die SCS direkt umgesetzt werden.

Zusammenfassung

Durch die Entscheidung für die neue Fachlichkeit den SCS Ansatz zu wählen, ergaben sich für uns folgende Vorteile:

  • Wir konnten  das Entwicklungsteam um Kollegen erweitern ohne diese einem aufwendigen Briefing in das Legacy System unterziehen zu müssen.
  • Das Altsystem ist nicht um weitere Funktionen gewachsen, diese sind komplett im neuen SCS implementiert worden.
  • Im SCS konnten wir aktuelle Softwarekomponenten (insbesondere Angular2) verwenden ohne gleich die UI des kompletten Altsystems neu schreiben zu müssen.
  • Durch die Verwendung von Hazelcast zum Austausch von Nachrichten konnte eine asynchrone Kommunikation ohne Middleware realisiert werden.
  • Endbenutzer, die nur die neuen Funktionalitäten nutzen müssen, benötigen keine aufwendige RCP Installation mehr (inkl. Updates etc.).
  • Durch die Integration als Browser-Views im Eclipse RCP ist eine beinahe geräuschlose Integration in die Altanwendung erfolgt.

Nachteile / Schwierigkeiten:

  • Mit der SCS haben wir ein weiteres System, das entsprechend überwacht werden muss. Hierzu haben wir Spring Boot Admin [6] genutzt.
  • Bei der Integration der SCS in den RCP  mussten einige Hürden bewältigt werden (Navigation ausblenden, Authentifizierung vom RCP übernehmen). Darüber hinaus stellte uns der RCP in der von uns verwendeten Variante (leider noch Eclipse 3.7) einige Fallen beim Verwenden des Browser Widgets. Diese waren aber mit ein wenig Google-Recherche schnell überwunden.

Fazit

Abschließend lässt sich sagen, dass wir ohne den gewählten Ansatz wahrscheinlich nicht in time fertig geworden wären. Das Schöne an diesem Ansatz ist darüber hinaus, dass wir eine klare Trennung der Zuständigkeiten der Systeme erreicht haben. Das bestehende Legacy-System hatte zuvor bereits eine hohe Komplexität, die dank SCS nicht weiter gewachsen ist.


Quellen / Referenzen

[1] http://scs-architecture.org/

[2] http://microservices.io/patterns/microservices.html

[3] https://angular.io/

[4] https://projects.spring.io/spring-boot/

[5] https://hazelcast.com/

[6] https://github.com/codecentric/spring-boot-admin

Beitragsbild: photo credit: clement127 Ferrari garage via photopin (license)

Verfasst von Björn Seebeck am 18. Juli 2017