Ubiquitous Language

Domain-driven Design (DDD) ist kein neues Thema (Eric Evans hat das Konzept vor über einem Jahrzehnt formalisiert). Es ist jedoch merkwürdig, wie die grundlegenden Konzepte zu diesem Thema bis heute auf Interesse stoßen, insbesondere in der .NET-Gemeinschaft. Noch merkwürdiger ist, wie dieselben Konzepte fehlinterpretiert werden.

Das Fundament von DDD liegt im Konzept der allgegenwärtigen Sprache. Es geht nicht darum, zu bestimmen, was eine Entität, ein Wertobjekt, ein Aggregat, ein Dienst oder ein Repository ist.

Wir haben den Eindruck, dass jeder, der mit dem Studium von DDD beginnt, die ersten paar Seiten des Evans-Buches oder des Vernon-Buches liest und sofort zu den Seiten springt, auf denen die Muster beschrieben werden.

Wir sprechen oft mit IT-Leuten, die denken, dass eine definierte allgegenwärtige Sprache bedeutet, dass die Namen von Klassen und Eigenschaften, die von Programmierern geschrieben werden, dem Vokabular von Fachexperten entsprechen. Dies ist jedoch eine grobe Vereinfachung.

Um die Bedeutung einer allgegenwärtigen Sprache zu verstehen, lassen Sie uns mit der unten aufgeführten „Entität“ beginnen:

public class Employee{ public string Id { get; set; } public string Name { get; set; } public string Cpf { get; set; } public decimal Salary { get; set; }}

Hier ist ein ausgezeichnetes Beispiel für eine anämische Implementierung! Aber bevor Sie weiterlesen, versuchen Sie herauszufinden, warum.

In unserer täglichen Arbeit, wenn wir dieses Beispiel verwenden, hören wir Vorschläge, dass dieser Klasse Verhaltensweisen fehlen (was richtig ist!). Wenn wir jedoch fragen, was solche „Verhaltensweisen“ sein könnten, stellen wir fest, dass die Leute allgemeine Argumente wiederholen (von Leuten, die die Idee auch nicht „verstanden“ haben) und nicht erkennen können, was falsch ist!

Eines der häufigsten Argumente ist, dass Eigenschaftssetzer privat sein sollten. An ihrer Stelle sollten wir „DefineXXX“-Methoden haben, die Validierungen implementieren würden. Diese Idee macht keinen Sinn, da der Zweck von Settern genau darin besteht, Werte für die Eigenschaften zu setzen, und es wäre kein Problem, eine Validierungslogik in ihnen zu implementieren.

Die Methoden einer Entität sollten die Gründe für ihre Zustandsänderungen darlegen. Außerdem muss es mindestens einen Konstruktor geben, der in der Lage ist, die Entität von Anfang an in einem gültigen Zustand zu instanziieren.

Es ist nicht ungewöhnlich, Klassenimplementierungen mit Eigenschaften zu finden, die z.B. prüfen, ob der Wert, den man zu setzen versucht, nicht null ist, selbst wenn diese gleichen Eigenschaften null als Standardwert haben. Welche Logik steckt dahinter?

Siehe ein weiteres Beispiel für eine anämische Klasse:

public class Customer { public string Name { get; private set; } public string Email { get; private set; } public DateTime BirthDate { get; private set; } public Customer(Guid id, string name, string email, DateTime birthDate) { Id = id; Name = name; Email = email; BirthDate = birthDate; } }

In der obigen Klasse haben wir einen typischen „Datensatz“ für eine funktionale Implementierung. Aber in einer objektorientierten Sprache ist dies keine Entität.

Die Idee würde sogar in einer rein funktionalen Sprache Sinn machen, in der die „Entität“ konzeptionell auf verschiedene Funktionen verteilt ist, die das Verhalten definieren, aber in C# macht sie überhaupt keinen Sinn.

Lassen Sie uns eine zweite Version für die Klasse Employee ausprobieren:

public class Employee{ public string Id { get; private set; } public string Name { get; private set; } public string Cpf { get; private set; } public decimal Salary { get; private set; } public Employee(string name, string cpf) { //.. } public void RaiseSalary(decimal amount) { //.. }}

Dieses Mal ist die Entität weniger anämisch. Immerhin sind die Beweggründe für die Änderung der Eigenschaftswerte offensichtlich. Beachten Sie, dass sogar der Wert des Schreibens von Tests deutlicher wird.

Trotzdem haben wir immer noch Probleme. Wir haben die Methode „RaiseSalary“ genannt, aber das ist nicht die Art und Weise, wie Fachleute diesen Vorgang beschreiben. Die einzige Möglichkeit, tatsächliche Gründe für das Ändern von Eigenschaftswerten zu definieren, besteht darin, mit diesen Experten zu sprechen.

Zum Nachdenken…

Die allgegenwärtige Sprache zu identifizieren und zu implementieren bedeutet nicht nur, Klassennamen oder Eigenschaften zu definieren. Die allgegenwärtige Sprache muss sich vor allem in den Motivationen für die Zustandsänderungen unserer Entitäten explizit zeigen.

Das Verständnis der allgegenwärtigen Sprache ist viel wichtiger als das Erlernen der Standards. Ohne wirkliche Kenntnis der Domäne ist der Wert von Entwurfsmustern gleich Null.

Sorgen Sie sich zuerst darum, das Wichtigste zu lernen. Nehmen Sie sich die Zeit und Mühe, die Domäne gut zu verstehen und ihre allgegenwärtige Sprache zu buchstabieren. Dann kann es sogar Sinn machen, daran zu denken, DDD mit fortgeschritteneren technischen Konzepten zu verknüpfen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.