Domain Primitives

Nein, das ist kein Bild von Gipf-Oberfrick sondern...
Beitrag erstellt am: 15.09.21
Ein Domain Primitive ist ein fachliches Konzept und ersetzt die gängige Nutzung von Omnitypes (Primitives) wie String, Int, Float, Boolean etc. in den fachlichen A-Komponenten (vgl. Modulbildung: Strukturierung des Systems auf der Basis von Software-Kategorien).
 
Wie ich bereits im Beitrag Gedanken zu Domänentypen ausgeführt habe, sind Domain Primitives im Kontext von "Secure by Design" ein wichtiges Element. Sie erhöhen die Robustheit unserer Entwürfe und helfen, leckgeschlagene Abstraktionen (vgl. Joel Spolsky zum Thema "The Law of Leaky Abstractions") zu verhindern.

Funktionen der fachlichen Domäne verwenden Domain Primitives für Parameter und Rückgabewerte.

Beispiele

  • Bestellmenge für Produkte in einem Warenkorb: Integerwert > 0, mit einem Maximumwert von 650.
  • Anzeigename für einen Benutzer in einem Online-Forum: Zeichenkette, minimale Länge 3, maximale Länge 64 Zeichen, nur alphanumerische Zeichen, Bindestrich und Unterstrich, sowie Leerzeichen erlaubt; Leerzeichen am Ende und Schluss werden ignoriert.
  • Backofen Garguttemperatur: Integerwert mit einem Wertebereich von 20 – 100 Grad Celsius.
  • Backofen Garraumtemperatur: Integerwert mit einem Wertebereich von 20 - 300 Grad Celsius.

Die Eigenschaften

Ein Domain Primitive
  • ist konzeptionell ein Wertobjekt und besitzt somit keine Identität; zwei Ausprägungen sind gleich, wenn sie den gleichen Wert repräsentieren
  • kapselt einen lesbaren Datenwert, der in Regel auf einem Omnitype (Primitive) basiert
  • lässt sich als Argument und Rückgabewert für Funktionen nutzen
  • definiert Regeln für gültige Werte (Gültigkeitsprüfung), beispielsweise einen klar definierten Wertebereich, gültige Syntax, etc.
  • stellt eine Konstruktor-Funktion (unit) bereit, in der die Gültigkeitsprüfung erfolgt. Diese liefert entweder ein gültiges Exemplar oder das für den Domain Primitive definierte absorbierende Element bzw. einen Default-Wert, wenn die Regeln für gültige Werte verletzt sind
  • definiert bei Bedarf eine Identitätsfunktion; diese retourniert das übergebene Domain Primitive unverändert (nötig für die Nutzung eines Domain Primitives in der funktionalen Komposition)
  • definiert bei Bedarf ein absorbierendes Element, das eine Wertbereichsverletzung ausdrückt
  • ist bei Bedarf ein Monoid (mit zweistelliger Verknüpfungsfunktion und einem neutralen Element)

Warum Domain Primitives anstelle von Omnitypes?

Omnitypes gehören gemäss Definition der Software-Kategorien zur Kategorie 0. Sie sind damit in Komponenten der Kategorie A explizit erlaubt. Wie ist unter diesem Aspekt der erhöhte Umsetzungsaufwand von Domain Primitives zu rechtfertigen?

Domain Primitive erlauben uns, fachliche Semantik einzufangen und dafür zu sorgen, dass wir möglichst nur gültige Zustände überhaupt abbilden können. Der dafür nötige Mehraufwand zahlt sich rasch aus, weil Domain Primitives Konzepte explizit machen. Insgesamt verbessert dies die intellektuelle Beherrschbarkeit und Robustheit unserer Systeme in mehrfacher Hinsicht:
  • Prüflogik lässt sich an einem Ort verbindlich abbilden, und zwar in der Konstruktor-Funktion und den jeweiligen für den Domain Primitive definierten Operationen. Nach erfolgter Prüfung können wir sicher sein, dass wir entweder ein gültiges Wertobjekt vom gewünschten Typ haben oder ein absorbierendes Element. Damit entfallen weitere Prüfungen verteilt im Domänen-Code und ungültige Ausgangswerte können keinen Schaden anrichten.
  • Kein Vertauschen von Argumenten in Funktionsaufrufen aufgrund gleicher Omnitypes, sofern man natürlich auf eine Sprache mit Compile-Time-Type-Checking setzt.
  • Möglichkeit deklarativer Code-Pipelines dank absorbierender Elemente.

Nach meiner Erfahrung bieten Domain Primitives nur Vorteile. Sie lassen sich in jeder Programmiersprache umsetzen und nutzen. Ich möchte sie in meiner Arbeit nicht mehr missen. Zur Nachahmung empfohlen :-)