6.7 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 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).
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, z.B.
ROLE_USER). - 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\rightarrowValidation\rightarrowCalculation\rightarrowSave. Er steuert die Transaktionsgrenzen viaTransactionManagerInterface. - 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.
B. Spezialisierte Logik (Stateless Services)
Um "Fat Managers" zu vermeiden, wird Fachlogik in spezialisierte Klassen ausgelagert:
- Calculators: Pure Functions für Berechnungen
\rightarrowgibt Werte zurück. - Policies: Business-Regelprüfungen
\rightarrowgibtbooleanzurück. - Validators: Komplexe Zustandsprüfungen
\rightarrowwirftValidationException. - Strategies: Kapselung austauschbarer Algorithmen.
C. Domain Objekte
- Models: Die primären 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
DomainEventCollectorgesammelt und nach dem Commit gefeuert 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\leftrightarrowModeltransformieren.
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.
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
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.).
Asynchronität (Messenger)
- Inbound:
Message\rightarrowHandler\rightarrowDTO\rightarrowUseCase. - Outbound: Nachrichten werden erst nach dem erfolgreichen Commit der Transaktion verschickt (Post-Commit Trigger), um "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