Add OrderManagerInterface to Manager example; type all dependencies on interfaces

This commit is contained in:
2026-07-16 18:25:37 +02:00
parent 9e14bd4a71
commit 4682029017
+31 -18
View File
@@ -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);
// 1. Produktbestand reduzieren (Manager orchestriert Processor + Cache)
$this->stockManager->reduceStockForOrder($request->items);
// 2. Bestellung anlegen
$order = $this->orderProcessor->save($request->toModel());
// 2. Bestellung anlegen (Manager orchestriert Processor + Cache)
$order = $this->orderManager->createOrder($request);
return new CreateOrderResponse(orderId: $order->id);
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.