From 0f9913faa2c270a6f9118322af533c0c4dbcba7c Mon Sep 17 00:00:00 2001 From: Jens Beckmann Date: Wed, 17 Jun 2026 15:50:21 +0000 Subject: [PATCH] Doku/architektur.md aktualisiert --- Doku/architektur.md | 52 +++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/Doku/architektur.md b/Doku/architektur.md index 32a448c..39f94ba 100644 --- a/Doku/architektur.md +++ b/Doku/architektur.md @@ -5,9 +5,9 @@ Das Ziel dieser Architektur ist eine strikte Trennung zwischen technischer Infra ### Grundregeln: * **Unidirektionaler Fluss:** `UI` $\rightarrow$ `Logic` $\rightarrow$ `Data`. Ein Layer darf niemals Informationen aus einem übergeordneten Layer importieren. -* **Dependency Inversion:** Die `Logic`-Schicht definiert die Anforderungen (Interfaces). Die `Data`-Schicht implementiert diese. Die Logik ist somit unabhängig von der Datenbank-Technologie. -* **Model-Zentrierung:** Das Model ist das Herzstück der Applikation. Es ist ein anämisches POPO (Plain Old PHP Object) und wird primär im gesamten System verwendet. -* **Atomarität:** Business-Operationen sind atomar. Entweder alles wird gespeichert oder nichts (Transaction Management). +* **Dependency Inversion:** Die `Logic`-Schicht definiert die Anforderungen (Interfaces). Die `Data`-Schicht implementiert diese. Die Logik ist somit vollständig unabhängig von der Datenbank-Technologie oder externen APIs. +* **Model-Zentrierung:** Das Model ist das Herzstück der Applikation. Es ist ein anämisches POPO (Plain Old PHP Object) und dient als primärer Datenträger zwischen den Schichten. +* **Atomarität:** Business-Operationen sind atomar. Entweder alles wird gespeichert oder nichts (Transaction Management via `TransactionManagerInterface`). --- @@ -19,40 +19,40 @@ Die UI-Schicht ist die dünne Eintrittspforte. Sie besitzt keine Geschäftslogik * **Verantwortlichkeiten:** * Mapping von Input auf **DTOs**. * Syntaktische Validierung via Symfony Constraints am DTO. - * Grobe Autorisierungsprüfung (Rollen-basiert, z.B. `ROLE_USER`). + * Grobe Autorisierungsprüfung (Rollen-basiert). * Aufruf des entsprechenden **UseCase**. ### 🔵 Logic Layer (Business Core) Hier wird definiert, *was* das System tut. Die Logik ist in Orchestrierung und zustandslose Fachlogik unterteilt. #### A. Orchestrierung & State -* **UseCase:** Der Dirigent eines Business-Prozesses. Er koordiniert den Ablauf: `Authorization` $\rightarrow$ `Validation` $\rightarrow$ `Calculation` $\rightarrow$ `Save`. Er steuert die Transaktionsgrenzen via `TransactionManagerInterface`. -* **Manager:** Zuständig für das **State Management**. Er implementiert das *Cache-Aside Pattern* (prüft Cache vor dem Provider) und steuert die Cache-Invalidierung nach Schreibvorgängen. +* **UseCase:** Der Dirigent eines Business-Prozesses. Er koordiniert: `Authorization` $\rightarrow$ `Validation` $\rightarrow$ `Calculation` $\rightarrow$ `Save`. Er steuert die Transaktionsgrenzen. +* **Manager:** Zuständig für das **State Management**. Implementiert das *Cache-Aside Pattern* (Prüfung Cache vor Provider) und steuert die Invalidierung via Cache-Tags nach Schreibvorgängen. #### B. Spezialisierte Logik (Stateless Services) -Um "Fat Managers" zu vermeiden, wird Fachlogik in spezialisierte Klassen ausgelagert: +Zur Vermeidung von "Fat Managers" wird Fachlogik ausgelagert: * **Calculators:** Pure Functions für Berechnungen $\rightarrow$ gibt Werte zurück. * **Policies:** Business-Regelprüfungen $\rightarrow$ gibt `boolean` zurück. -* **Validators:** Komplexe Zustandsprüfungen $\rightarrow$ wirft `ValidationException`. +* **Validators:** Komplexe semantische Zustandsprüfungen $\rightarrow$ wirft `DomainException`. * **Strategies:** Kapselung austauschbarer Algorithmen. #### C. Domain Objekte -* **Models:** Die primären Datencontainer (z.B. `GardenPlan`). Anämisch und unabhängig von der DB. +* **Models:** Primäre Datencontainer (z.B. `GardenPlan`). Anämisch und unabhängig von der DB. * **DTOs:** Transportobjekte zwischen UI und Logic. -* **Domain Events:** Dünne Ereignisse (ID & Typ), die via `DomainEventCollector` gesammelt und nach dem Commit gefeuert werden. +* **Domain Events:** Dünne Ereignisse, die manuell im UseCase nach erfolgreichem Commit getriggert werden. ### 🔴 Data Layer (Infrastructure) Die technische Realisierung. Alles hier ist austauschbar, solange die Interfaces der Logic-Schicht erfüllt werden. -* **Provider / Processor:** Implementierungen der in der Logic definierten Interfaces. Provider = Lesen | Processor = Schreiben. -* **Entities:** Die technischen Repräsentationen für Doctrine (z.B. `GardenPlanEntity`). -* **Mappers:** Explizite Klassen, die zwischen `Entity` $\leftrightarrow$ `Model` transformieren. +* **Provider / Processor:** Implementierungen der Interfaces (`Provider` = Lesen | `Processor` = Schreiben). +* **Entities:** Technische Repräsentationen für Doctrine (z.B. `GardenPlanEntity`). +* **Mappers:** Explizite Klassen, die zwischen `Entity` $\leftrightarrow$ `Model` transformieren (KI-generiert/manuell). --- ## 3. Technischer Workflow & Pipeline ### Der Schreib-Pfad (Write Flow) -`UI (Controller/Command)` $\rightarrow$ `DTO` $\rightarrow$ `UseCase (Start Transaction)` $\rightarrow$ `Auth Check (Voter)` $\rightarrow$ `Validator` $\rightarrow$ `Policy` $\rightarrow$ `Calculator` $\rightarrow$ `Manager` $\rightarrow$ `Processor` $\rightarrow$ `Mapper` $\rightarrow$ `Entity` $\rightarrow$ `DB`. +`UI` $\rightarrow$ `DTO` $\rightarrow$ `UseCase (Start Transaction)` $\rightarrow$ `Auth Check` $\rightarrow$ `Validator` $\rightarrow$ `Policy` $\rightarrow$ `Calculator` $\rightarrow$ `Manager` $\rightarrow$ `Processor` $\rightarrow$ `Mapper` $\rightarrow$ `Entity` $\rightarrow$ `DB` $\rightarrow$ `Commit` $\rightarrow$ `Trigger Events`. ### Der Lese-Pfad (Read Flow) `UI` $\rightarrow$ `UseCase` $\rightarrow$ `Manager (Cache check)` $\rightarrow$ `Provider Interface` $\rightarrow$ `Implementation` $\rightarrow$ `Mapper` $\rightarrow$ `Model` $\rightarrow$ `UI`. @@ -61,13 +61,23 @@ Die technische Realisierung. Alles hier ist austauschbar, solange die Interfaces ## 4. Querschnittsfunktionen -### Transaktionssteuerung & Fehler -* **Transaction Management:** Der UseCase nutzt ein `TransactionManagerInterface`, um sicherzustellen, dass alle Änderungen innerhalb eines Prozesses atomar erfolgen. -* **Error Handling:** Eigene Domain-Exceptions in der Logic. Ein zentraler **Symfony ExceptionListener** mappt diese auf HTTP-Statuscodes (400, 403, 404, etc.). +### Dependency Injection & Composition Root +Um eine strikte Entkopplung zu gewährleisten, wird die `Logic`-Schicht niemals direkt auf konkrete Implementierungen referenzieren (kein hartcodiertes `#[Autowire(service: ...)]`). +* **Implicit Autowiring:** Bei einer einzigen Implementierung pro Interface nutzt Symfony das Standard-Autowiring. +* **Composition Root:** Die `services.yaml` fungiert als zentrale Konfigurationsinstanz, in der Interfaces auf konkrete Implementierungen gemappt werden (Alias/Bind), um die Infrastruktur von außen steuerbar zu machen. -### Asynchronität (Messenger) -* **Inbound:** `Message` $\rightarrow$ `Handler` $\rightarrow$ `DTO` $\rightarrow$ `UseCase`. -* **Outbound:** Nachrichten werden erst **nach** dem erfolgreichen Commit der Transaktion verschickt (Post-Commit Trigger), um "Ghost Notifications" zu vermeiden. +### Fehlermanagement & Exception-Handling +Ein zentrales System mappt fachliche Fehler auf HTTP-Standards: +* **Hierarchie:** Alle Fachfehler erben von einer Basis-`DomainException`. +* **Mapping:** Ein `Symfony ExceptionListener` fängt diese ab und mappt sie auf Statuscodes: + * `ResourceNotFoundException` $\rightarrow$ 404 + * `AccessDeniedException` $\rightarrow$ 403 + * `BusinessRuleViolationException` $\rightarrow$ 422/400 +* **Format:** Die Antwort erfolgt im **RFC 7807 (Problem Details for HTTP APIs)** Format, um dem Frontend präzise, maschinenlesbare Fehler zu liefern. + +### Transaktionssteuerung & Asynchronität +* **Transaction Management:** Abstrahiert über ein `TransactionManagerInterface`. +* **Messenger:** Outbound-Nachrichten werden erst nach erfolgreichem DB-Commit versendet, um inkonsistente Benachrichtigungen ("Ghost Notifications") zu vermeiden. --- @@ -114,4 +124,4 @@ src/ │ └── Implementation/ │ ├── Provider/[Feature]/ # Realisierung der Interfaces │ └── Processor/[Feature]/ # Realisierung der Interfaces -``` +``` \ No newline at end of file