Files
4plants/Doku/architektur.md
2026-06-13 13:26:39 +02:00

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 \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).

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 \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.

B. Spezialisierte Logik (Stateless Services)

Um "Fat Managers" zu vermeiden, wird Fachlogik in spezialisierte Klassen 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.
  • 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 DomainEventCollector gesammelt 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 \leftrightarrow Model transformieren.

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 \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.

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