7.5 KiB
🌿 Architektur-Dokumentation: Gartenprojekt (Symfony)
1. Vision & Kernprinzipien
Das Ziel dieser Architektur ist eine strikte Trennung zwischen technischer Infrastruktur, Geschäftslogik und den Liefermechanismen. Wir verfolgen einen Ansatz, der an Clean Architecture und Hexagonal Architecture angelehnt ist.
Grundregeln:
- Unidirektionaler Fluss:
UI\rightarrowLogic\rightarrowData. Ein Layer darf niemals Informationen aus einem übergeordneten Layer importieren. - Dependency Inversion: Die
Logic-Schicht definiert die Anforderungen (Interfaces). DieData-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).
2. Die Schichtenarchitektur
🟢 UI Layer (Delivery Mechanisms)
Die UI-Schicht ist die dünne Eintrittspforte. Sie besitzt keine Geschäftslogik.
- Einstiegspunkte:
Http(Controller),Console(Commands),Queue(MessageHandlers). - Verantwortlichkeiten:
- Mapping von Input auf DTOs.
- Syntaktische Validierung via Symfony Constraints am DTO.
- 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:
Authorization\rightarrowValidation\rightarrowCalculation\rightarrowSave. 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)
Zur Vermeidung von "Fat Managers" wird Fachlogik ausgelagert:
- Calculators: Pure Functions für Berechnungen
\rightarrowgibt Werte zurück. - Policies: Business-Regelprüfungen
\rightarrowgibtbooleanzurück. - Validators: Komplexe semantische Zustandsprüfungen
\rightarrowwirftDomainException. - Strategies: Kapselung austauschbarer Algorithmen.
C. Domain Objekte
- 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, 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 Interfaces (
Provider= Lesen |Processor= Schreiben). - Entities: Technische Repräsentationen für Doctrine (z.B.
GardenPlanEntity). - Mappers: Explizite Klassen, die zwischen
Entity\leftrightarrowModeltransformieren (KI-generiert/manuell).
3. Technischer Workflow & Pipeline
Der Schreib-Pfad (Write Flow)
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.
4. Querschnittsfunktionen
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.yamlfungiert als zentrale Konfigurationsinstanz, in der Interfaces auf konkrete Implementierungen gemappt werden (Alias/Bind), um die Infrastruktur von außen steuerbar zu machen.
Fehlermanagement & Exception-Handling
Ein zentrales System mappt fachliche Fehler auf HTTP-Standards:
- Hierarchie: Alle Fachfehler erben von einer Basis-
DomainException. - Mapping: Ein
Symfony ExceptionListenerfängt diese ab und mappt sie auf Statuscodes:ResourceNotFoundException\rightarrow404AccessDeniedException\rightarrow403BusinessRuleViolationException\rightarrow422/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.
5. Namensmusterkatalog
| Komponente | Muster | Beispiel |
|---|---|---|
| Model | [Entity] |
GardenPlan |
| Entity | [Entity]Entity |
GardenPlanEntity |
| UseCase | [Action][Entity]UseCase |
CreateGardenPlanUseCase |
| Manager | [Entity]Manager |
GardenPlanManager |
| Calculator | [Topic]Calculator |
SpacingCalculator |
| Policy | [Rule]Policy |
CompatibilityPolicy |
| Validator | [Entity]Validator |
GardenLayoutValidator |
| Provider Interface | [Entity]ProviderInterface |
GardenPlanProviderInterface |
| Processor Interface | [Entity]ProcessorInterface |
GardenPlanProcessorInterface |
| Mapper | [Src]To[Tgt]Mapper |
GardenPlanEntityToModelMapper |
| DTO | [Action][Entity]Dto |
UpdateGardenPlanDto |
6. Ordnerstruktur (Hybrid-Feature Ansatz)
src/
├── UI/
│ ├── Http/Controller/[Feature]/ # z.B. /Planning/GardenPlanController.php
│ ├── Console/Command/[Feature]/ # z.B. /Irrigation/StartWateringCommand.php
│ └── Queue/MessageHandler/[Feature]/ # z.B. /Notification/SendMailHandler.php
│
├── Logic/
│ ├── UseCase/[Feature]/ # z.B. /Planning/CreateGardenPlanUseCase.php
│ ├── Manager/[Feature]/ # z.B. /Planning/GardenPlanManager.php
│ ├── Domain/
│ │ ├── Model/[Feature]/ # z.B. /Planning/GardenPlan.php
│ │ ├── DTO/[Feature]/ # z.B. /Planning/UpdatePlanDto.php
│ │ └── Service/[Feature]/ # Calculator, Policy, Validator, Strategy
│ └── InfrastructureInterface/ # Provider & Processor Interfaces
│
├── Data/
│ ├── Doctrine/
│ │ ├── Entity/[Feature]/ # z.B. /Planning/GardenPlanEntity.php
│ │ └── Mapping/[Feature]/ # z.B. /Planning/GardenPlanMapper.php
│ └── Implementation/
│ ├── Provider/[Feature]/ # Realisierung der Interfaces
│ └── Processor/[Feature]/ # Realisierung der Interfaces