baydev
Published on

Zwei Gesichter der Daten

Authors
  • avatar
    Name
    Ismail Bay
    Twitter

Unternehmen verwenden eine Sammlung verschiedener Systeme, die gemeinsam für ein Ziel arbeiten. Kundendaten werden in CRM-Systemen gehalten, ERPs verwalten die Ressourcen und Auswertungen in Excel validieren, ob das Business-Ziel heuer erreicht wird.

Neben Fremdsoftware entsteht auch eine Reihe an Business-Applikationen, die über Schnittstellen miteinander bzw. mit der Außenwelt kommunizieren.

Eines haben fast alle Systeme gemeinsam: Es fallen Daten an, die persistiert und gegebenenfalls für andere Akteure veröffentlicht werden sollen.

In einer traditionellen, monolithischen Softwareentwicklung würde man vermutlich Batch-Jobs einsetzen, die diese Daten in einer nutzbaren Form lesen und speichern.

In der Microservice-Welt würden wir kleinere Services erstellen und die jeweils notwendigen Daten (Bounded Context1) bei dem jeweiligen Service speichern. Das sorgt für Unabhängigkeit und Entkopplung der Services und erlaubt die Skalierbarkeit, nicht unbedingt im Sinne von technischer Skalierung, sondern eher im Sinne von Wachstum in den Teams und im Unternehmen.

Beide Ansätze haben eine gemeinsame Eigenschaft: Daten leben im jeweiligen System und werden aus guten Gründen für die Außenwelt geheimgehalten. So können die Services unabhängig bleiben und ohne Auswirkung auf andere Teile weiterentwickelt werden. Wenn Daten in anderen Systemen benötigt werden, können sie per Schnittstellen verfügbar gemacht werden.

Viele Services benötigen aber Teile dieser Daten für ihre Dienste:

service-data

Mit fortschreitendem Projekt werden neue Anforderungen bekannt und verstanden geglaubte Domainkontexte verschwimmen ineinander. In Kombination mit vernachlässigtem Abbau technischer Schuld findet man sich dann ungefähr vor diesem Bild:

service-data

Aufgrund der großen Schnittmenge muss ein Service mit vielen anderen sprechen:

service-data

Die Unabhängigkeit der Services bedeutet, dass ein Service schnell und frei iterieren kann. Wenn ein Service aber die Daten von anderen Services benötigt, müssen sie ungefähr zur gleichen Zeit angepasst werden. Im Gegensatz zu monolithischen Applikationen ist dies bei Microservices nicht so einfach und erfordert Koordination zwischen Teams und im Release-Management.

Die typische dafür Lösung ist, übergreifende Änderungen einfach zu vermeiden, indem man die Verantwortlichkeiten zwischen den Services sauber trennt. In der realen Welt ist das oft nicht möglich. Die meisten Services teilen sich die Daten, die im gesamten System entstehen. Somit sind die ineinander verflochten.

Datenkapselung

Damit ein Service unabhängig bleibt, ist es wichtig, dass seine Daten intern gehalten werden. Somit kann es ohne Auswirkungen auf andere Service weiterentwickelt und angepasst werden.

Andererseits erfüllen Services ihren Zweck, indem sie ihre Daten nach außen über Schnittstellen preisgeben bzw. Schnittstellen für Datenmodifikationen anbieten.

Dieses widersprüchliche Verhalten, Verstecken und Öffnen, führt zu immer mehr Schnittstellen, die am Ende zu einer Art eigenständiger, selbst entwickelter Datenbank führt.

api-data

Wer hat die Daten?

Jedes Service hat die eigenen Daten (Database per Service Pattern2) bzw. teilt sich die Daten direkt mit anderen Diensten (Shared Database Anti-Pattern!3). Viele Funktionalitäten in einer Applikation brauchen aber einen Schnitt über mehrere Services. Eine gängige Lösung ist, mit einer API zu sprechen, die die notwendigen Daten aus mehreren Systemen sammelt und im aggregierten Zustand (API Composition4) zurückliefert.

Trotz einer API-Composition erfordern Datenänderungen oft eine koordinierte Anpassung an mehreren Teilen des gesamten Systems. Ausserdem müssen mehrere Services abgefragt werden, um die benötigten Daten zu sammeln.

Eine weitere Toolbox stellt das CQRS Pattern dar. Da CQRS in der Regel mit Events und einem Message-Bus realisiert wird, bietet es eine neue Möglichkeit zur mehr Unabhängigkeit zwischen den Services, da sie nicht mehr direkt und synchron miteinander sprechen müssen. Mehr dazu im nächsten Artikel.

Footnotes

  1. https://martinfowler.com/bliki/BoundedContext.html

  2. https://microservices.io/patterns/data/database-per-service.html

  3. https://microservices.io/patterns/data/shared-database.html

  4. https://microservices.io/patterns/data/api-composition.html