From d0af98ba3858131307b4caf9488846d22bc0c91b Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 15 Jul 2026 19:36:55 +0200 Subject: [PATCH] feat: define Read Pattern (BusinessQuery -> Manager -> Provider) --- architektur-patterns.md | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/architektur-patterns.md b/architektur-patterns.md index d7ecddd..9955cab 100644 --- a/architektur-patterns.md +++ b/architektur-patterns.md @@ -94,4 +94,83 @@ readonly class CreateOrderResponse public string $orderId, ) {} } + +## 2. Read Pattern (`src/Logic` $\rightarrow$ `src/Data`) + +Das Read Pattern beschreibt den Weg einer Datenabfrage von der UI bis zur Datenquelle. Es stellt sicher, dass die UI-Layer niemals direkt auf die Data Layer zugreift und Business-Modelle konsistent zurückgegeben werden. + +### Der Datenfluss +`UI Layer` $\rightarrow$ **BusinessQuery** $\rightarrow$ **Manager** $\rightarrow$ **Provider** + +#### BusinessQuery (Logic Layer) +- **Zweck**: Dient als fachlicher Einstiegspunkt für Leseoperationen. Sie orchestriert Manager oder andere Queries, um ein Endresultat zu formen. +- **Struktur**: Implementiert das gleiche Muster wie UseCases (`execute()` Methode). +- **Input/Output**: Nutzt Request-DTOs (besonders für Filter und Pagination) und gibt Response-DTOs zurück. +- **Pfad**: `src/Logic/{Module}/{Feature}/Query/...` + +#### Manager (Logic Layer) +- **Zweck**: Steuert die Bereitstellung der Daten. Hier erfolgt primär die Cache-Logik ("Cache-Aside") und die Koordination von Providern. +- **Verantwortung**: Entscheidung, ob Daten aus dem Cache oder frisch vom Provider geladen werden müssen. + +#### Provider (Data Layer) +- **Zweck**: Führt die technische Abfrage gegen die Infrastruktur aus (DB, API). +- **Rückgabewert**: Liefert die **Kern-Business-Models** zurück, nicht notwendigerweise die technischen Entities der Datenbank. + +### Code Beispiel + +#### BusinessQuery & DTOs +```php +namespace App\Logic\Sales\Order\Query; + +use App\Logic\Common\UseCaseInterface; +use App\Logic\Sales\Order\Dto\GetOrdersRequest; +use App\Logic\Sales\Order\Dto\GetOrdersResponse; +use App\Logic\Sales\Order\Manager\OrderManager; + +readonly class GetOrdersQuery implements UseCaseInterface +{ + public function __construct(private OrderManager $orderManager) {} + + public function execute(mixed $request): GetOrdersResponse + { + if (!$request instanceof GetOrdersRequest) { + throw new \InvalidArgumentException('Invalid request type'); + } + + $orders = $this->orderManager->findOrders($request->filter, $request->page); + + return new GetOrdersResponse(orders: $orders); + } +} +``` + +#### Manager & Provider +```php +namespace App\Logic\Sales\Order\Manager; + +use App\Data\Sales\Order\Provider\OrderProvider; + +readonly class OrderManager +{ + public function __construct(private OrderProvider $orderProvider) {} + + public function findOrders(array $filters, int $page): array + { + // Cache-Logik hier... + return $this->orderProvider->fetchOrders($filters, $page); + } +} + +// --- Data Layer --- +namespace App\Data\Sales\Order\Provider; + +readonly class OrderProvider +{ + public function fetchOrders(array $filters, int $page): array + { + // DB Abfrage und Mapping zu Business-Models + return []; + } +} +``` ```