Bild von Requirements Engineering & Domain-Driven Design

08. Mai 2025

Requirements Engineering & Domain-Driven Design

Strukturierte Prozesse und eine gemeinsame Sprache fördern erfolgreiche Softwareprojekte. Effektives Requirements Engineering und Domain-Driven Design helfen, Barrieren in der Kommunikation zwischen Kunden und Entwicklern zu überwinden.

Ein zentrales Problem in der Softwareentwicklung ist die Kommunikation zwischen Kunden und Entwicklern. Oft können Kunden ihre Wünsche nicht klar formulieren, was zu gravierenden Folgen führt: Über- oder Unterentwicklung sowie falsche Lösungen. Requirements Engineering und Domain-Driven Design helfen, Brücken zwischen Stakeholdern und Entwicklern zu schlagen, Ziele klar zu definieren und den Projekterfolg zu fördern.

Christian Bühler, erfahrener Requirements Engineer und Mitgründer von KnowGravity , leitete einen zweitägigen Workshop, während dem wir anhand eines Fallbeispiels die Grundlagen des Requirements Engineerings erlernten. In dieser Zusammenfassung zeigen wir auf, wie wir zunächst die Stakeholder identifizieren,  Ziele festlegen und diese abstimmen. Mithilfe von Domain-Driven Design entwickeln wir gemeinsam Lösungsansätze und dokumentieren sie. So sind die Anforderungen klar nachvollziehbar.

Stakeholder finden und managen

Der erste Schritt im Stakeholder-Management ist die Identifikation der relevanten Stakeholder. Ein Stakeholder ist eine Person oder Organisation, die direkt oder indirekt Einfluss auf die Anforderungen eines Projekts hat. Typische Stakeholder können Fachexperten, Projektleiter, Endbenutzer, rechtliche Berater, Sicherheitsbeauftragte und viele andere sein.

Bei der Identifikation von Stakeholdern stellt man sich folgende Fragen:

  • Wer hat ein Interesse am System? (z. B. Projektleiter, die den Erfolg des Projekts sicherstellen möchten)
  • Wer ist (in)direkt vom System betroffen? (z. B. Mitarbeiter, die das System nutzen oder davon beeinflusst werden)
  • Wer hat mit dem System zu tun? (z. B. IT-Administratoren, die das System implementieren und warten)
  •  
  • Wer gibt Randbedingungen vor? (z. B. rechtliche und sicherheitstechnische Anforderungen, die von den entsprechenden Abteilungen vorgegeben werden)

Die identifizierten Stakeholder werden dokumentiert. Bei Personengruppen wird eine repräsentative Person ausgewählt, um die Interessen der gesamten Gruppe zu vertreten. Wichtige Informationen, die erfasst werden sollten, sind:

  • Ziele: Was sind die Erwartungen und Ziele der Stakeholder in Bezug auf das System?
  • Wissensgebiet: In welchen Bereichen haben die Stakeholder Fachwissen oder Expertise?
  • Relevanz/Macht/Einfluss: Wie wichtig sind die Stakeholder für den Projekterfolg? Welche Macht oder Einfluss haben sie auf Entscheidungen?
  • Kontaktdaten: Wie können die Stakeholder erreicht werden?
  • Zeitliche/räumliche Verfügbarkeit: Wann und wo sind die Stakeholder verfügbar für Meetings oder Feedback?

Es ist entscheidend, gründlich bei der Identifikation und Dokumentation der Stakeholder vorzugehen. Werden Stakeholder übersehen, können wichtige Anforderungen und Perspektiven verloren gehen, was zu Problemen im Projektverlauf führen kann. Ein effektives Stakeholder-Management trägt dazu bei, die Kommunikation zu verbessern, Missverständnisse zu vermeiden und sicherzustellen, dass alle relevanten Anforderungen berücksichtigt werden.

©KnowGravity

Die dokumentierten Stakeholder(gruppen) können in einer Stakeholder-Matrix abgebildet werden. Diese Matrix ermöglicht es, schnell zu erkennen, welche Stakeholder intensiver gemanagt werden müssen.

Im obigen Beispiel zeigt sich, dass das Projekt erhebliche Auswirkungen auf die Logistikmitarbeiter hat, diese jedoch nicht den Einfluss besitzen, um wesentliche Änderungen am Projekt vorzunehmen. Daher wären tägliche Meetings mit den Logistikmitarbeitern zeitlich ineffizient und könnten die Ressourcen unnötig belasten.

Im Gegensatz dazu sollte mit der IT-Leitung, die einen hohen Einfluss auf das Projekt hat und stark davon betroffen ist, eine engere Zusammenarbeit angestrebt werden. Regelmässige Meetings und ein intensiver Austausch mit der IT-Leitung sind entscheidend, um sicherzustellen, dass technische Anforderungen und Herausforderungen frühzeitig adressiert werden.

Ziele Identifizieren und Abstimmen

Im nächsten Schritt identifizieren wir die Ziele des Projekts. Wir definieren ein Ziel hier als die Wirkung oder Folge, die aus der Nutzung unseres Systems entsteht. Es ist wichtig, Ziele nicht mit Anforderungen zu verwechseln, die die Eigenschaften oder das Verhalten unseres Systems beschreiben. Ein Beispiel für ein Ziel in unserem Projekt könnte lauten: «Der Logistikaufwand wird um 20% reduziert.» Eine entsprechende Anforderung wäre hingegen: «Die Standardlösung ist mit bestehenden Prozessen kompatibel.»

Der Prozess zur Identifikation und Abstimmung der Ziele erfolgt in mehreren Schritten:

  • Identifikation des Pain Points: Der Logistikaufwand ist zu hoch.
  • Identifikation des qualitativen Ziels: Der Logistikaufwand soll reduziert werden.
  • Identifikation des quantitativen Ziels: Der Logistikaufwand wird um 20% reduziert.

Qualitative Ziele müssen mit allen Stakeholdern abgestimmt werden. Ebenso ist es wichtig, die Messmethoden für quantitative Ziele mit allen Stakeholdern zu klären. Es ist zu beachten, dass sich Ziele im Verlauf des Projekts ändern können; solche Änderungen müssen jedoch von den Stakeholdern akzeptiert werden.

Jedes Ziel sollte zudem einen verantwortlichen Träger unter den Stakeholdern haben. Ziele, für die sich kein Stakeholder verantwortlich fühlt, sind instabil und können ohne weiteres entfernt werden, selbst wenn bereits Implementationsaufwand investiert wurde. Sollten wir Vorschläge von ausserhalb unserer Stakeholder erhalten, dürfen wir diese nicht eigenmächtig hinzufügen. Stattdessen können wir auf unsere Stakeholder-Dokumentation verweisen, und die externe Person muss selbst einen Träger finden.

In dieser Phase nehmen wir die Rolle eines Mediators ein. Wir bringen unsere Stakeholder zusammen und arbeiten darauf hin, einen Konsens für die Projektziele zu erarbeiten, der von allen Beteiligten akzeptiert wird.

Problem und Kontext/Domäne identifizieren und verstehen

Nachdem wir nun die Ziele und die Stakeholder identifiziert haben, gilt es, die Probleme und den Kontext zu verstehen. Hierbei bedienen wir uns der Prinzipien des Domain-Driven Design (DDD). Der Kern von DDD besteht darin, die Softwareentwicklung eng mit der Geschäftslogik (Domäne) zu verknüpfen. Im Mittelpunkt stehen das Wissen und die Sprache der Domäne.

Die Hauptprinzipien von DDD sind:

  1. Fokus auf die Kerndomäne:
    Dies bedeutet, dass die Geschäftslogik, Prozesse und Regeln korrekt in der Software abgebildet werden. Um dies zu erreichen, ist eine enge Zusammenarbeit zwischen Entwicklern und Fachexperten erforderlich. Gemeinsame Workshops, wie beispielsweise Event Storming, sind hierbei besonders hilfreich, um die verschiedenen Aspekte der Domäne zu erfassen und zu diskutieren.
  2. Gemeinsame Sprache (Ubiquitous Language):
    Eine gemeinsame Sprache ist ein Vokabular, das sowohl von Entwicklern als auch von Fachexperten verwendet wird. Durch die disziplinierte Nutzung dieser Sprache werden Missverständnisse vermieden und ein gemeinsames Verständnis gefördert. Die entwickelte Sprache sollte in allen Kommunikationsformen strikt verwendet werden und, wenn möglich, auch im Code durch korrekte Benennungen von Klassen und Typen widergespiegelt werden.
  3. Abgegrenzte Bereiche (Bounded Contexts):
    Abgegrenzte Bereiche definieren, in welchem Teil der Domäne Begriffe und Modelle konsistent verwendet werden können. Verschiedene Bereiche können unterschiedliche Definitionen für denselben Begriff haben. Zum Beispiel könnte der Begriff «Kunde» im Sales-Bereich eine Firma bezeichnen, während im Customer Support ein Endbenutzer gemeint sein könnte.

Durch die Anwendung dieser Prinzipien können wir ein tiefes Verständnis für die Probleme und den Kontext der Domäne entwickeln. Dies ist entscheidend, um sicherzustellen, dass die Software die tatsächlichen Bedürfnisse der Stakeholder erfüllt und die Geschäftsprozesse effektiv unterstützt.

Bausteine Domain-Driven Design

Eine Entity ist ein Objekt mit eindeutiger Identität, die über die Zeit bestehen bleibt. Diese Identität ermöglicht es, das Objekt von anderen zu unterscheiden, selbst wenn sich Attribute ändern. Ein spezifischer Kunde in einem System könnte durch eine eindeutige Kunden-ID identifiziert werden. Diese ID bleibt konstant, auch wenn sich andere Eigenschaften des Kunden, wie Name, Adresse oder Kontaktdaten, ändern. Die Identität des Kunden ist entscheidend, um seine Transaktionen, Bestellungen und Interaktionen im System nachverfolgen zu können.

Ein Value Object ist ein Objekt, das durch seine Eigenschaften definiert wird und keine eigene Identität hat. Es ist typischerweise unveränderlich (immutable), was bedeutet, dass einmal erstellte Instanzen nicht mehr verändert werden können. Eine Adresse kann als Value Object betrachtet werden, das durch Attribute wie Strasse, Stadt und Postleitzahl definiert ist. Zwei Adressen sind gleich, wenn alle ihre Attribute übereinstimmen. Wenn sich eine Adresse ändert (z. B. ein Umzug), wird ein neues Value Object erstellt, anstatt das bestehende zu ändern.

Ein Aggregate ist eine Gruppe von zusammengehörigen Entities und Value Objects, die als Einheit betrachtet werden. Ein Aggregate hat einen Aggregate Root, der die Hauptentität darstellt und für die Integrität des gesamten Aggregats verantwortlich ist. Eine Bestellung könnte als Aggregate betrachtet werden, das die Hauptentität «Bestellung» (Aggregate Root) und zugehörige Value Objects wie «Bestellpositionen» (z. B. Produkte, Mengen) und «Zahlungsinformationen» umfasst. Die Bestellung ist die zentrale Einheit, die alle relevanten Informationen und Regeln für die Bestellung verwaltet.

Repositories sind Schnittstellen zur Persistenzschicht, die den Zugriff auf Aggregates ermöglichen. Sie abstrahieren die Datenzugriffslogik und bieten Methoden zum Speichern, Abrufen und Löschen von Aggregates. Ein Bestellungs-Repository könnte Methoden wie GetBySave und Delete bereitstellen, um Bestellungen zu verwalten. Es ermöglicht der Anwendung, Bestellungen zu speichern und abzurufen, ohne sich um die Details der Datenbankinteraktion kümmern zu müssen

Ein Domain Event ist ein Ereignis, das eine signifikante Veränderung im Zustand der Domäne darstellt. Es wird verwendet, um andere Teile des Systems über diese Veränderung zu informieren und kann Aktionen in anderen Kontexten auslösen. Wenn eine Person das Alter von 18 Jahren erreicht, könnte ein Domain Event «PersonVolljährig» ausgelöst werden. Dieses Ereignis könnte andere Teile des Systems informieren, dass die Person nun als potenzieller Kunde erfasst werden kann, was möglicherweise weitere Aktionen wie die Berechtigung für bestimmte Dienstleistungen oder Angebote nach sich zieht.

Event Storming

Event Storming ist eine kollaborative Modellierungstechnik, die in der Softwareentwicklung und Prozessoptimierung eingesetzt wird, um ein gemeinsames Verständnis von einem Geschäftsbereich oder einer Anwendungsdomäne zu schaffen. 

Event Storming Workshops werden also durchgeführt, um uns bei der kollaborativen Modellierung von Geschäftsprozessen zu unterstützen und eine gemeinsame Sprache zwischen den Stakeholdern zu schaffen. Unsere Teilnehmer bestehen aus Personen mit Fragen (z. B. Entwickler) und Personen mit Antworten (z. B. Produktverantwortlichen, Fachexperten). Der Prozess ist technologiearm; es werden lediglich Post-its benötigt.

In einem ersten Schritt werden Domain Events gesammelt. Domain Events sind Ereignisse in der realen Welt, die einen Einfluss auf unsere Domäne haben. Diese Events lösen in unserer Domäne eine Reaktion aus.

©KnowGravity

In einem zweiten Schritt ordnen wir die gesammelten Events zeitlich. Dadurch können eventuell vergessene Events identifiziert und Lücken geschlossen werden.

©KnowGravity

Jetzt wissen wir, was in unserer Domäne geschehen kann. Nun gilt es herauszufinden, wer (User/Actor) was (Command) in Reaktion auf ein Event ausführt.

©KnowGravity

Die gefundenen User und Commands zeigen uns die Schnittstellen zu unserem System. Ein User vom Typ Product Manager interagiert mit unserem System, um ein neues Produkt zu registrieren und dessen Details zu spezifizieren.

Jetzt werden die Aggregates identifiziert. Aggregates sind Gruppen von Objekten, die als einzige Einheit behandelt werden. Zum Beispiel behandeln wir alle unsere Produkte als das Aggregate Produkt. Das Ziel ist nun, herauszufinden, welche Aggregates von welchen Events manipuliert werden. Das Erstellen eines neuen Produkts wird beispielsweise das Produkt-Aggregate beeinflussen.

©KnowGravity

Die Geschäftsprozesse wurden visuell erarbeitet. Das Bild zeigt jedoch nur den «Happy Path» Es fehlen jedoch dynamische Geschäftsregeln, wie zum Beispiel: «Bestellungen werden nur ausgeführt, wenn alle Produkte an Lager verfügbar sind.» Kleinere technische Regeln, wie «Der Kunde muss eingeloggt sein, um Bestellungen auszuführen», sind zu trivial, um sie hier aufzuführen und sollten daher ignoriert werden.

©KnowGravity

Das resultierende Bild zeigt uns die Geschäftsprozesse einschliesslich der dynamischen Regeln. Können wir Lücken identifizieren? Gibt es Inkonsistenzen? Was könnte verbessert werden? Sollten gewisse Prozesse detailreicher modelliert werden? Falls ja, führen wir eine zusätzliche Iteration durch.

Nach dem Workshop sollten die Stakeholder ein besseres gemeinsames Verständnis der Domäne haben, potenzielle Probleme identifiziert werden und die Kommunikation gefördert werden. Zudem sind die Geschäftsprozesse/Use Cases visuell modelliert und sollten sowohl von Entwicklern als auch von Stakeholdern problemlos verständlich sein. Die Ergebnisse verwenden wir nun, um genauere Dokumentationen zu erstellen.

Von Event Storming zu Dokumentation

Durch die erstellten Modelle im Event Storming haben wir eine Grundlage um das besprochene zu verfeinern und besser zu visualisieren. Die Geschäftsprozesse sollten jetzt schon gut modelliert sein und lassen sich einfach als BPMN-Diagramm darstellen. Hier ein Beispiel wie der «Deliver Order» Prozess aussehen könnte.

Unter Verwendung aller vorher gefundenen Commands und Users können wir ein Use Case Diagramm in UML erstellen.

©KnowGravity

In diesem Diagramm sehen wir schon einfacher welche Akteure über welche Schnittstellen mit dem System interagieren.

Die Aggregates visualisieren wir in einem Klassendiagramm .

©KnowGravity

Wir sind primär an den Attributen und Assoziationen interessiert. Spezifische Methoden einer Klasse sind für nicht-technische User irrelevant und werden weggelassen. Datentypen sind auch nicht zu spezifizieren, wichtig ist dass das Datenmodell und die Assoziationen stimmig sind. Wenn wir Datentypen spezifizieren dann nicht technisch (intdouble) sondern fachlich (z. B. KundenNummer anstatt uint). Wie bereits erwähnt versuchen wir eine Brücke zwischen den Entwicklern und Stakeholdern zu erstellen und beschränken uns auf das Wesentliche. 

Im Bild oben ist auch zu erkennen dass unsere Aggregates für Many-to-Many-Assoziationen nicht ausreichen. Die Klasse OrderPosition wird zusätzlich benötigt um mehrere Article einer Order hinzuzufügen.

Unsere dynamischen Geschäftsregeln lassen sich nicht in einem Klassendiagramm darstellen. Wir behelfen uns hier mit einem Zustandsdiagramm .

Im Diagramm erkennen wir den Lebenszyklus einer Bestellung ohne Zahlungsprozess. Eine leere Order wird von Sales erstellt und hat den Zustand AwaitOrderDetails. Sales fügt dann Produkte und das Lieferdatum hinzu, unter der Bedingung, dass die Produkte vorhanden sind und das Lieferdatum in der Zukunft liegt. Sales bestätigt nun die Bestellung, und die Order befindet sich im Zustand Confirmed. Falls nötig, kann Sales in diesem Zustand das Lieferdatum noch anpassen. Wenn das Datum erreicht ist, wechselt der Zustand automatisch zu ScheduledShipping. Ein Lagerhausverantwortlicher kann nun den Zustand auf Shipped ändern, wenn die Order ausgeliefert wird. Schliesslich, wenn die Bestellung ausgeliefert wurde, endet sie im Zustand Delivered. Sollte die Bestellung abgebrochen werden oder nach 5 Jahren nach Erstellung, löschen wir die Order.

Anforderungen

Nach der Erstellung der Diagramme ist die Erstellung einer Requirements-Spezifikation einfach. Wir müssen nur noch die Anforderungen spezifizieren. Eine Anforderung beschreibt eine gewünschte Eigenschaft oder ein gewünschtes Verhalten eines Systems. Wir unterscheiden zwischen funktionalen Anforderungen (was ein System machen soll), Qualitätsanforderungen (wie ein System ist) und Randbedingungen.

Funktionale Anforderungen sind für uns mittlerweile einfach zu erfassen, da wir sie bereits durch Event Storming und unsere Diagramme modelliert haben. Uns interessiert, in welchem Zustand das Ereignis akzeptiert wird, welche Bedingungen erfüllt sein müssen, welche Aktion das System ausführt und in welchen Zustand das System wechselt.

Ein Beispiel:

Priority kann eingeteilt werden in:

  • Muss (Must have): Mindestanforderung, muss umgesetzt werden.
  • Sollte (Should have): Sollte umgesetzt werden wenn alle Muss Anforderung trotzdem erfüllt werden können.
  • Kann (Nice to have): Kann umgesetzt werden falls höherwertige Anforderungen nicht beeinträchtig werden.
  • Wird: Wird nicht umgesetzt, aber für die Zukunft vorgemerkt.

Hier können wir auch gleich auf unser BPMN, Use Case und Zustandsdiagramm verweisen. Dadurch ist die funktionale Anforderung dokumentiert und ihr Platz im System auch ersichtlich. 

Qualitätsanforderungen beziehen sich auf Merkmale die nicht durch Funktionale Anforderungen abgedeckt werden können. Sie beschreiben Qualitäten wie Performanz, Verfügbarkeit, Sicherheit, etc., beziehen sich also darauf wie das System sein sollte, nicht was es tut.

Sie sollten möglichst früh und getrennt von den funktionalen Anforderungen dokumentiert werden. Die Prüfbarkeit sollte durch quantitative Aussagen sichergestellt werden, wie z. B. «In 98% aller Systeminteraktionen muss eine Antwort innerhalb von 3 Sekunden erfolgen».

Randbedingungen schränken den Lösungsraum weiter ein und können von den Projektbeteiligten nicht beeinflusst werden. Sie ergeben sich zum Beispiel aus gesetzlichen Vorgaben.
 

Fazit

Zusammenfassend unterstützen uns RE und DDD dabei, das Richtige richtig zu entwickeln. Durch die Identifikation der relevanten Stakeholder werden keine Ziele vergessen. Da die Stakeholder aktiv an den Lösungsvorschlägen mitarbeiten, wird die erwartete Akzeptanz der Lösungen grösser sein. Die erarbeitete Dokumentation kann noch jahrelang nach der Implementierung verwendet werden, um das System zu verstehen. Insbesondere die Verknüpfung der Anforderungen mit den Zielen ermöglicht es, zu verstehen, warum die Anforderung wichtig ist.

Link

Domain-Driven Design: Tackling Complexity in the Heart of Software (Evans,Eric 2003)


Schliessen
Stamp Icon-Print Icon-Clear
S
M
L
XL
XXL