From 4682029017278cec72fdb4ae48d4b7bfc54c2235 Mon Sep 17 00:00:00 2001 From: Jens Date: Thu, 16 Jul 2026 18:25:37 +0200 Subject: [PATCH] Add OrderManagerInterface to Manager example; type all dependencies on interfaces --- architektur-patterns.md | 53 +++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/architektur-patterns.md b/architektur-patterns.md index 968ef73..1f9024e 100644 --- a/architektur-patterns.md +++ b/architektur-patterns.md @@ -132,11 +132,11 @@ 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; +use App\Logic\Sales\Order\Manager\OrderManagerInterface; readonly class GetOrdersQuery implements UseCaseInterface { - public function __construct(private OrderManager $orderManager) {} + public function __construct(private OrderManagerInterface $orderManager) {} public function execute(mixed $request): GetOrdersResponse { @@ -151,16 +151,27 @@ readonly class GetOrdersQuery implements UseCaseInterface } ``` -#### Manager (Read + Cache) +#### Manager Interface (Logic Layer) ```php namespace App\Logic\Sales\Order\Manager; -use App\Data\Sales\Order\Provider\OrderProvider; +interface OrderManagerInterface +{ + public function findOrders(array $filters, int $page): array; + public function invalidateCache(): void; +} +``` -readonly class OrderManager +#### Manager Implementierung (Read + Cache) +```php +namespace App\Logic\Sales\Order\Manager; + +use App\Logic\Sales\Order\OrderProviderInterface; + +readonly class OrderManager implements OrderManagerInterface { public function __construct( - private OrderProvider $orderProvider, + private OrderProviderInterface $orderProvider, // private CacheInterface $cache, <-- Symfony/PSR-6 Cache (injected via DI) ) {} @@ -276,12 +287,12 @@ namespace App\Logic\Sales\Order\UseCase; use App\Logic\Common\UseCaseInterface; use App\Logic\Sales\Order\Dto\CreateOrderRequest; use App\Logic\Sales\Order\Dto\CreateOrderResponse; -use App\Logic\Sales\Order\Manager\OrderManager; +use App\Logic\Sales\Order\Manager\OrderManagerInterface; readonly class CreateOrderUseCase implements UseCaseInterface { public function __construct( - private OrderManager $orderManager, + private OrderManagerInterface $orderManager, // TransactionManager ggf. für Multi-Processor-Szenarien ) {} @@ -417,28 +428,28 @@ interface TransactionManagerInterface } ``` -#### 2. Anwendung im UseCase (`src/Logic`) -Der UseCase nutzt den TransactionManager, um sicherzustellen, dass entweder alle oder keine Änderungen persistiert werden (All-or-Nothing). +#### Anwendung im UseCase (`src/Logic`) +Der UseCase nutzt den TransactionManager, um sicherzustellen, dass entweder alle oder keine Änderungen persistiert werden (All-or-Nothing). Die Orchestrierung zwischen Managern erfolgt innerhalb der Transaktions-Closure. ```php readonly class CreateOrderUseCase implements UseCaseInterface { public function __construct( private TransactionManagerInterface $transactionManager, - private OrderProcessorInterface $orderProcessor, - private StockProcessorInterface $stockProcessor + private OrderManager $orderManager, + private StockManager $stockManager ) {} public function execute(mixed $request): CreateOrderResponse { return $this->transactionManager->transactional(function() use ($request) { - // 1. Produktbestand reduzieren - $this->stockProcessor->reduceStock($request->items); - - // 2. Bestellung anlegen - $order = $this->orderProcessor->save($request->toModel()); - - return new CreateOrderResponse(orderId: $order->id); + // 1. Produktbestand reduzieren (Manager orchestriert Processor + Cache) + $this->stockManager->reduceStockForOrder($request->items); + + // 2. Bestellung anlegen (Manager orchestriert Processor + Cache) + $order = $this->orderManager->createOrder($request); + + return new CreateOrderResponse(orderId: $order.id); }); } } @@ -466,9 +477,11 @@ readonly class DoctrineTransactionManager implements TransactionManagerInterface ### Vorteile - **Kein Leaking**: Die Logic Layer weiß nicht, dass Doctrine verwendet wird. -- **Atomarität**: Mehrere Processor können konsistent in einer Transaktion kombiniert werden. +- **Atomarität**: Mehrere Manager können konsistent in einer Transaktion orchestriert werden. - **Testbarkeit**: Der TransactionManager kann in Unit Tests einfach durch einen Mock ersetzt werden, der den Closure direkt ausführt. +Die Manager-Konzepte werden in Sektion 3 (Write Pattern) detailliert beschrieben. Die UseCases arbeiten auf Managern, die ihrerseits Processors aufrufen. + ## 6. Entity vs. Business Model (`src/Data` $\rightarrow$ `src/Logic`) Um die Geschäftslogik vollständig vom Framework und dem ORM zu entkoppeln, wird eine strikte Trennung zwischen Persistenz-Objekten (Entities) und Domänen-Objekten (Business Models) eingeführt.