arrow_backZurück zum Blog
DE
Architekturbeitrag

Domain first: Warum das Modell wichtiger ist als das Framework

Warum gute Systeme am Fachmodell lesbar bleiben und nicht am Frameworkdialekt hängen

account_circleAnjunar09. September 2026Veröffentlicht

Wenn ich „Domain first“ sage, meine ich nicht einfach, dass es irgendwo ein domain-Modul gibt. Ich meine etwas Strengeres: Das Modell muss der Ort sein, an dem die eigentliche Wahrheit des Systems lesbar bleibt. Nicht das Framework. Nicht die Datenbank. Nicht die Controller-Schicht. Nicht die UI-Komposition.

Viele Projekte behaupten, fachlich zu modellieren, und liefern am Ende doch nur technische Objekte mit ein paar Validierungsannotationen. Das ist noch keine Fachlichkeit. Das ist bestenfalls Infrastruktur mit Namen.

In diesem Blogprojekt ist ein BlogPost kein bloßes Transportobjekt. Er trägt Beziehungen, Zustände, Übersetzungen, Sichtbarkeit und Regeln. Genau so muss ein Fachobjekt aussehen: nicht künstlich aufgeblasen, aber auch nicht auf eine JSON- oder Tabellenform reduziert.

@ManyToOne(optional = false, fetch = FetchType.LAZY, targetEntity = classOf[User])
var author: User = uninitialized

@OneToMany(
  mappedBy = "post",
  cascade = Array(CascadeType.ALL),
  orphanRemoval = true,
  targetEntity = classOf[BlogPostTranslation]
)
val translations: util.Set[BlogPostTranslation] =
  new util.LinkedHashSet[BlogPostTranslation]()

@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 24)
var status: BlogPostStatus = BlogPostStatus.DRAFT

Der interessante Punkt hier ist nicht JPA. Der interessante Punkt ist, dass das Modell sichtbar macht, was ein Blogbeitrag in diesem System überhaupt ist. Autor, Übersetzungen, Status, Kommentarbezug, Veröffentlichungszeitpunkt. Wenn ich das Modell ernst nehme, kann ich später API, UI und Persistenz daran ausrichten. Wenn ich das Modell ignoriere, ziehen alle Schichten in unterschiedliche Richtungen.

Deshalb mag ich auch die transienten Felder für lokalisierte Sicht:

@Transient
var locale: String = BlogPost.DefaultLocale

@Transient
var title: String = uninitialized

@Transient
var teaser: String = uninitialized

@Transient
var content: LexicalDocument = uninitialized

Das kann man kritisch lesen und fragen, ob das nicht „gemischt“ sei. Für mich ist hier gerade das Gegenteil interessant: Das System drückt aus, dass ein Blogpost nicht nur eine starre Datenbankform ist, sondern eine fachliche Einheit mit lokalisierter Projektion. Wenn ich das elegant und kontrolliert im Modell ausdrücke, muss ich diese Wahrheit nicht an fünf anderen Stellen künstlich rekonstruieren.

Framework-first-Systeme arbeiten umgekehrt. Erst kommt die technische Struktur: Controller, DTO, Repository, Mapper, Request, Response, Entity, ViewModel. Danach versucht man, das Fachliche irgendwo dazwischenzuschieben. Das Ergebnis ist oft Bewegung ohne Form.

Domain first heißt nicht, dass das Modell „rein“ und deshalb weltfremd sein muss. Es heißt, dass die Architektur vom Modell her erklärt werden kann. Wenn ich einen neuen Entwickler frage, was ein BlogPost in diesem System ist, dann sollte er das am Modell verstehen können. Nicht erst nach drei Framework-Tutorials und zwei Mappingschichten.

Genau deshalb ist auch das Schema im Domain-Modul spannend:

class Schema
    extends AbstractEntitySchema[BlogPost](RuntimeContext.entityManager()) {
  val author: SingularProperty[BlogPost, User] = reference(_.author)
  val locale: Property[BlogPost, String] = property(_.locale, classOf[OwnerRule[BlogPost]])
  val title: Property[BlogPost, String] = property(_.title, classOf[OwnerRule[BlogPost]])
  val slug: Property[BlogPost, String] = property(_.slug, classOf[OwnerRule[BlogPost]])
  val status: Property[BlogPost, BlogPostStatus] = property(_.status, classOf[OwnerRule[BlogPost]])
}

Man kann darüber diskutieren, ob man dieses Schema exakt so bauen würde. Aber die Richtung ist richtig: Die Fachstruktur bekommt ein explizites Meta-Modell. Das schafft Klarheit für Validierung, Rechte, API und UI. Das Framework dient dabei, aber es führt nicht.

Für mich ist das der entscheidende Unterschied. Ich habe nichts gegen Frameworks. Ich habe etwas dagegen, wenn sie zur eigentlichen Sprache des Systems werden. Dann spricht das Projekt irgendwann nicht mehr über Artikel, Veröffentlichungen, Rechte und Lokalisierung, sondern nur noch über technische Mechanik.

Ein gutes Modell entlastet alle anderen Schichten. Die API muss weniger raten. Die UI muss weniger erraten. Die Persistenz ist weniger zufällig. Und Diskussionen über Anforderungen landen wieder dort, wo sie hingehören: bei fachlichen Begriffen.

Domain first ist deshalb keine Stilfrage. Es ist eine Schutzmaßnahme. Sie schützt das System davor, dass die eigentliche Fachlichkeit im Frameworkrauschen verschwindet.

forum

Noch keine Kommentare.