mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 08:29:36 +01:00
refactor: EntityDraft-Pattern auf Customer, Article und ProductCategory anwenden
- CustomerDraft / CustomerUpdateDraft eingeführt - ArticleDraft / ArticleUpdateDraft eingeführt - ProductCategoryDraft / ProductCategoryUpdateDraft eingeführt - Customer.create() nimmt jetzt CustomerDraft, gibt Result zurück - Customer.update(CustomerUpdateDraft) ersetzt 4× updateXxx(VO) - Article.create() nimmt jetzt ArticleDraft statt VOs - Article.update(ArticleUpdateDraft) ersetzt rename() + changeCategory() - ProductCategory.create() nimmt jetzt ProductCategoryDraft, gibt Result zurück - ProductCategory.update(ProductCategoryUpdateDraft) ersetzt rename() + updateDescription() - Use Cases bauen Draft aus Command, kein VO-Wissen im Application Layer - CreateCustomerCommand / UpdateCustomerCommand: int → Integer für paymentDueDays - CLAUDE.md: EntityDraft-Pattern-Dokumentation ergänzt
This commit is contained in:
parent
6b341f217b
commit
87123df2e4
30 changed files with 625 additions and 329 deletions
26
CLAUDE.md
26
CLAUDE.md
|
|
@ -23,6 +23,8 @@ Bounded Contexts: `usermanagement` (implementiert), `production`, `quality`, `in
|
|||
| Command | `{Verb}{Noun}Command` | `CreateUserCommand` |
|
||||
| Domain Entity | `{Noun}` | `User`, `Role` |
|
||||
| Value Object | `{Noun}` | `UserId`, `PasswordHash`, `RoleName` |
|
||||
| Create-Draft | `{Noun}Draft` | `SupplierDraft` |
|
||||
| Update-Draft | `{Noun}UpdateDraft` | `SupplierUpdateDraft` |
|
||||
| Domain Error | `{Noun}Error` (sealed interface) | `UserError.UsernameAlreadyExists` |
|
||||
| JPA Entity | `{Noun}Entity` | `UserEntity` |
|
||||
| Mapper | `{Noun}Mapper` | `UserMapper` (Domain↔JPA) |
|
||||
|
|
@ -32,6 +34,30 @@ Bounded Contexts: `usermanagement` (implementiert), `production`, `quality`, `in
|
|||
| Web DTO | `{Verb}{Noun}Request` | `CreateUserRequest` |
|
||||
| Action Enum | `{Noun}Action implements Action` | `ProductionAction` |
|
||||
|
||||
## EntityDraft-Pattern
|
||||
|
||||
Für Aggregate mit komplexer VO-Konstruktion (Address, ContactInfo, PaymentTerms u.ä.) gilt:
|
||||
Der Application Layer baut **keine** VOs – er erzeugt einen **Draft-Record** mit rohen Strings
|
||||
und übergibt ihn ans Aggregate. Das Aggregate orchestriert Validierung und VO-Konstruktion intern.
|
||||
|
||||
```java
|
||||
// Application Layer – nur Daten weitergeben, kein VO-Wissen
|
||||
var draft = new SupplierDraft(cmd.name(), cmd.phone(), ...);
|
||||
switch (Supplier.create(draft)) { ... }
|
||||
|
||||
// Domain Layer – validiert intern, gibt Result zurück
|
||||
public static Result<SupplierError, Supplier> create(SupplierDraft draft) { ... }
|
||||
public Result<SupplierError, Void> update(SupplierUpdateDraft draft) { ... }
|
||||
```
|
||||
|
||||
**Regeln:**
|
||||
- Pflichtfelder: non-null im Draft-Record
|
||||
- Optionale VOs (z.B. Address, PaymentTerms): `null`-Felder → VO wird nicht konstruiert
|
||||
- Primitive `int` → `Integer` wenn das Feld optional/nullable sein muss
|
||||
- Einzelne `updateXxx(VO)`-Methoden entfallen → ersetzt durch ein `update({Noun}UpdateDraft)`
|
||||
- Uniqueness-Check bleibt im Application Layer (Repository-Concern), nach `Aggregate.create()`
|
||||
- Invarianten-Kommentar im Aggregat aktuell halten
|
||||
|
||||
## Error Handling
|
||||
Funktional via `Result<E, T>` (`shared.common.Result`). Domain-Fehler sind sealed interfaces mit Records. Keine Exceptions im Domain/Application Layer.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue