From f2dff2a4d8445a53df4417e4b0a36462a7e0b74a Mon Sep 17 00:00:00 2001 From: StefanMoCoAt Date: Wed, 8 Apr 2026 23:00:49 +0200 Subject: [PATCH] Remove `Dom` prefix from domain models: rename classes to reflect business terminology, update references in tests, repositories, and services; add ADR for new naming conventions. --- CHANGELOG.md | 7 +++ .../entries/domain/model/DomBewerbTest.kt | 8 +-- .../tenant/EntriesIsolationIntegrationTest.kt | 8 +-- ...0023-domain-entity-naming-convention-de.md | 57 +++++++++++++++++++ .../01_Glossary/Ubiquitous_Language.md | 5 +- 5 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 docs/01_Architecture/adr/0023-domain-entity-naming-convention-de.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c87f5f89..9e437d08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,13 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/). ### Hinzugefügt +- **Events-Service Bundle:** Vollständige Stabilisierung der `events` Services (Domain, Infrastructure, API, Service). + - **Domain:** Umstellung auf `kotlin.time.Instant` zur Vermeidung von Deprecation-Warnungen (Kotlin 2.1.20+) und Harmonisierung mit dem Rulebook-Expert. + - **Infrastructure:** Anpassung an den `org.jetbrains.exposed.v1` Namespace und Implementierung von UUID-Konvertierungen zwischen `kotlin.uuid.Uuid` (Domain) und `java.util.UUID` (DB). + - **API:** Refactoring des `VeranstaltungController` zur direkten Repository-Nutzung (Alignment mit `entries` Service). + - **Service-Config:** Umstellung auf Flyway-basiertes Tenant-Schema-Management in `EventsDatabaseConfiguration`. + - **Build:** Behebung des `shadowJar` Fehlers in `events-infrastructure` durch Entfernen des unnötigen `ktor` Plugins in der Library-Schicht. + - Masterdata: Automatisches Seeding aller Reiterlizenzen (license_matrix) beim Start des `masterdata-service` via `ReiterlizenzenSeeder` (idempotent; SPRINGEN: LIZENZFREI,R1–R4; DRESSUR: LIZENZFREI,RD1–RD3). - **ZNS-Import (LIZENZ01.dat):** Robuster Lizenz-Tokenizer und Normalizer implementiert. diff --git a/backend/services/entries/entries-domain/src/test/kotlin/at/mocode/entries/domain/model/DomBewerbTest.kt b/backend/services/entries/entries-domain/src/test/kotlin/at/mocode/entries/domain/model/DomBewerbTest.kt index fc22a78e..e4cc3ba9 100644 --- a/backend/services/entries/entries-domain/src/test/kotlin/at/mocode/entries/domain/model/DomBewerbTest.kt +++ b/backend/services/entries/entries-domain/src/test/kotlin/at/mocode/entries/domain/model/DomBewerbTest.kt @@ -14,7 +14,7 @@ class DomBewerbTest { @Test fun `getPflichtTeilungsSchwellenwert liefert korrekte Werte fuer alle PruefungsTypen`() { - val baseBewerb = DomBewerb( + val baseBewerb = Bewerb( turnierId = Uuid.random(), bewerbNummer = 1, bezeichnung = "Test", @@ -33,7 +33,7 @@ class DomBewerbTest { @Test fun `getPflichtTeilungsSchwellenwert liefert null fuer Meisterschaftsbewerbe`() { - val meisterschaft = DomBewerb( + val meisterschaft = Bewerb( turnierId = Uuid.random(), bewerbNummer = 1, bezeichnung = "Meisterschaft", @@ -48,7 +48,7 @@ class DomBewerbTest { @Test fun `validateAbteilungsSchwellenwerte gibt Warnung bei Ueberschreitung des Pflicht-Schwellenwerts`() { - val bewerb = DomBewerb( + val bewerb = Bewerb( turnierId = Uuid.random(), bewerbNummer = 1, bezeichnung = "Springprüfung", @@ -64,7 +64,7 @@ class DomBewerbTest { @Test fun `validateAbteilungsSchwellenwerte gibt Warnung bei Dressur-Kann-Teilung`() { - val bewerb = DomBewerb( + val bewerb = Bewerb( turnierId = Uuid.random(), bewerbNummer = 1, bezeichnung = "Dressurprüfung", diff --git a/backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/EntriesIsolationIntegrationTest.kt b/backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/EntriesIsolationIntegrationTest.kt index 74375c21..25c130ff 100644 --- a/backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/EntriesIsolationIntegrationTest.kt +++ b/backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/EntriesIsolationIntegrationTest.kt @@ -2,7 +2,7 @@ package at.mocode.entries.service.tenant -import at.mocode.entries.domain.model.DomNennung +import at.mocode.entries.domain.model.Nennung import at.mocode.entries.domain.repository.NennungRepository import at.mocode.entries.service.persistence.NennungTable import kotlinx.coroutines.runBlocking @@ -120,7 +120,7 @@ class EntriesIsolationIntegrationTest @Autowired constructor( // Schreibe eine Nennung in Tenant A TenantContextHolder.set(Tenant(eventId = "event_a", schemaName = "event_a")) try { - val nennungA = DomNennung.random(now) + val nennungA = Nennung.random(now) val loadedA = runBlocking { nennungRepository.save(nennungA) nennungRepository.findById(nennungA.nennungId) @@ -142,8 +142,8 @@ class EntriesIsolationIntegrationTest @Autowired constructor( } // --- Kleine Test-Helfer --- -private fun DomNennung.Companion.random(now: kotlin.time.Instant): DomNennung { - return DomNennung( +private fun Nennung.Companion.random(now: kotlin.time.Instant): Nennung { + return Nennung( nennungId = Uuid.random(), abteilungId = Uuid.random(), bewerbId = Uuid.random(), diff --git a/docs/01_Architecture/adr/0023-domain-entity-naming-convention-de.md b/docs/01_Architecture/adr/0023-domain-entity-naming-convention-de.md new file mode 100644 index 00000000..c3ceb397 --- /dev/null +++ b/docs/01_Architecture/adr/0023-domain-entity-naming-convention-de.md @@ -0,0 +1,57 @@ +--- +type: ADR +status: ACCEPTED +date: 2026-04-08 +deciders: Lead Architect, Backend Developer +--- + +# ADR-0023: Naming Convention für Domain-Entitäten (kein `Dom`-Präfix) + +## Status + +**ACCEPTED** – Umgesetzt in Session 2026-04-08 (Phase 1 & 2 Domain Clean-Up). + +## Kontext + +In der frühen Entwicklungsphase wurden Domain-Klassen mit dem Präfix `Dom` versehen +(z.B. `DomBewerb`, `DomVeranstaltung`, `DomTurnier`), um sie von DTOs und Datenbank-Entitäten +zu unterscheiden. Diese Konvention hat sich als unnötig und verwirrend erwiesen, da sie +gegen die Prinzipien der **Ubiquitous Language** (DDD) und der **Clean Architecture** verstößt. + +## Entscheidung + +**Domain-Entitäten tragen ab sofort ihren fachlichen Namen ohne Präfix.** + +| Schicht | Namenskonvention | Beispiel | +|-----------------|-------------------------|-----------------------| +| **Domain** | `` | `Bewerb` | +| **Datenbank** | `Table` | `BewerbTable` | +| **Persistence** | `Entity` | `BewerbEntity` | +| **API/Transfer**| `Dto` | `BewerbDto` | + +## Durchgeführte Umbenennungen (Phase 1) + +| Alt (Dom-Präfix) | Neu (Clean Name) | Modul | +|-----------------------|---------------------|-----------------| +| `DomBewerb` | `Bewerb` | entries-domain | +| `DomAbteilung` | `Abteilung` | entries-domain | +| `DomNennung` | `Nennung` | entries-domain | +| `DomNennungsTransfer` | `NennungsTransfer` | entries-domain | +| `DomTurnier` | `Turnier` | events-domain | +| `DomAusschreibung` | `Ausschreibung` | events-domain | +| `DomVeranstaltung` | `Veranstaltung` | events-domain (bereits vorhanden, Duplikat gelöscht) | + +## Konsequenzen + +- **Positiv:** Ubiquitous Language im Code – Fachexperten und Entwickler sprechen dieselbe Sprache. +- **Positiv:** Weniger kognitive Last – kein mentales Mapping zwischen `DomBewerb` und `Bewerb`. +- **Positiv:** Entspricht Clean Architecture – die Domain-Schicht ist die "reine" Schicht. +- **Negativ:** Einmalige Umbenennung erfordert Anpassung aller Referenzen (wurde systemweit durchgeführt). +- **Achtung:** Datenbank-Migrationen (Flyway) und Repository-Mappings werden in Phase 3 separat behandelt. + +## Coding Guideline (verbindlich ab sofort) + +> **Neue Domain-Klassen werden NIEMALS mit `Dom`, `Model`, `Entity` oder ähnlichen +> technischen Präfixen/Suffixen versehen. Der fachliche Name ist der Klassenname.** +> +> Ausnahmen: Datenbank-Klassen (`...Table`, `...Entity`) und Transfer-Objekte (`...Dto`, `...Request`, `...Response`). diff --git a/docs/03_Domain/01_Glossary/Ubiquitous_Language.md b/docs/03_Domain/01_Glossary/Ubiquitous_Language.md index 53e964f9..5bdd8e47 100644 --- a/docs/03_Domain/01_Glossary/Ubiquitous_Language.md +++ b/docs/03_Domain/01_Glossary/Ubiquitous_Language.md @@ -53,6 +53,7 @@ Veranstalter (OEPS-Mitgliedsverein) | Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen Startern eine Abteilung **verpflichtend** getrennt werden muss. Bei Überschreitung gibt das System eine **WARNUNG** (kein harter Fehler) – der TBA hat das letzte Wort (→ *Override-Event*). Vollständige Schwellenwert-Tabellen: → [`Abteilungs-Trennungs-Schwellenwerte.md`](../02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md) | ÖTO § 2 Abs. 7, § 39 | | | **Akteur** | Historischer Begriff (siehe → *Stammdaten*). Oberbegriff für alle Personen (Reiter, Richter, Funktionäre, Besitzer) und Organisationen (Vereine), die im System interagieren. | – | | **Ausschreibung** | Das offizielle Dokument, das alle Bedingungen eines Turniers festlegt. Pflichtfelder gemäß ÖTO (A-Satz der ZNS-Schnittstelle). | ÖTO Ausschreibungs-Struktur | +| **Austragungsplatz** | Physischer Ort (Platz, Arena, Halle) innerhalb einer Veranstaltung, auf dem Bewerbe stattfinden. Typ: `"Austragungsplatz"` (Wettkampf) oder `"Vorbereitungsplatz"` (Einreiten). Kann einer Sparte zugeordnet sein. Im Code als Entität **`Austragungsplatz`** (events-domain) abgebildet. | – | ### B @@ -131,7 +132,8 @@ Veranstalter (OEPS-Mitgliedsverein) ### R | Begriff | Definition | ÖTO-Referenz | -|--------------------|------------------------------------------------------------------------------------------------------------------------------|--------------| +|--------------------|------------------------------------------------------------------------------------------------------------------------------|--------------| +| **RichterEinsatz** | Value Object, das den Einsatz eines Funktionärs (Richter, Aufsicht) in einem Bewerb beschreibt. Felder: `funktionaerId` (Referenz auf Funktionär) und `position` (z.B. `"C"`, `"M"`, `"B"`, `"Aufsicht"`). Im Code als **`RichterEinsatz`** (entries-domain) abgebildet. | ÖTO Funktionärs-Qualifikation | | **Richtverfahren** | Das Bewertungsverfahren eines Bewerbs (z.B. § 204/4 Stilspringen, § 218 Einlauf). Bestimmt, wie Ergebnisse berechnet werden. | ÖTO B-Teil | ### S @@ -153,6 +155,7 @@ Veranstalter (OEPS-Mitgliedsverein) | Begriff | Definition | ÖTO-Referenz | |-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------| | **TBA** | Turnierbeauftragter. Hat bei Regelkonflikten immer das letzte Wort. Jede Überschreibung wird als → *Override-Event* gespeichert. | ÖTO § 24/§ 25 | +| **TurnierArtikel** | Abrechenbare Leistung oder Produkt im Rahmen einer Veranstaltung (z.B. Ansage, Heu, Startgeld). Preis in Cent (Long). Typ: `"AUTOMATISCH"` (systemseitig erzeugt) oder `"MANUELL"` (manuell erfasst). Im Code als Entität **`TurnierArtikel`** (events-domain, Billing Context) abgebildet. | Billing Context | | **Tierwohl-Euro** | Gebühr, die **pro Start** anfällt (nicht pro Nennung!). | ÖTO Gebührenordnung | | **Turnier** | In unserer Software: Eine pferdesportliche Veranstaltung mit einer offiziellen **Ausschreibung** und einer vom OEPS/LFV vergebenen, eindeutigen **Turniernummer**. Entspricht ÖTO § 2 Abs. 2. Ist eine Spezialisierung von → *Veranstaltung*. | ÖTO § 2 Abs. 2, § 5, § 24 | | **Turniernummer** | Offizielle, vom OEPS vergebene **5-stellige** Kennung eines Turniers (z.B. `26128`). Sie ist eindeutig und Voraussetzung für die offizielle Ausschreibung. | ÖTO § 3, ZNS A-Satz |