docs: enforce 3-4 dependency limit for UseCases and introduce Orchestrator pattern

This commit is contained in:
2026-07-17 12:37:33 +02:00
parent 0da6f5c10e
commit 8f99d4ec97
+46
View File
@@ -10,6 +10,52 @@ Das UseCase Pattern bildet das Herzstück der Business-Logik. Zusammen mit dem R
- **Eingabe/Ausgabe**: Daten werden strikt über DTOs (Data Transfer Objects) ausgetauscht. - **Eingabe/Ausgabe**: Daten werden strikt über DTOs (Data Transfer Objects) ausgetauscht.
- **Rückgabewert**: Ein UseCase gibt entweder ein Response-DTO zurück oder `void` (bei reinen Schreiboperationen). Die PHP-Signatur ist native typisiert, sodass zur Laufzeit keine `instanceof`-Prüfungen nötig sind. - **Rückgabewert**: Ein UseCase gibt entweder ein Response-DTO zurück oder `void` (bei reinen Schreiboperationen). Die PHP-Signatur ist native typisiert, sodass zur Laufzeit keine `instanceof`-Prüfungen nötig sind.
- **Fehlerbehandlung**: Business-Fehler werden über spezifische **Domain-Exceptions** signalisiert. - **Fehlerbehandlung**: Business-Fehler werden über spezifische **Domain-Exceptions** signalisiert.
- **Dependency Limitation**: Ein UseCase sollte maximal 34 Dependencies injizieren. Ab 5+ Dependencies wird dringend empfohlen, einen **Orchestrator** einzusetzen.
### Orchestrator Pattern (Optional für komplexe Koordination)
Wenn ein UseCase die Zuständigkeit mehrerer Domänen abdeckt (z. B. `Sales`, `Stock` und `Accounting` gleichzeitig), sollte er diese Manager nicht einzeln injizieren.
- **Ort**: `src/Logic/{Module}/{Feature}/Orchestrator/`
- **Zweck**: Bündelt mehrere Manager zu einer einzigen fachlichen Operation (z. B. `OrderFulfillmentOrchestrator`).
- **Vorteil**: Reduziert den UseCase-Konstruktor auf eine einzige Abhängigkeit und isoliert komplexe Multi-Domain-Logik, was die Testbarkeit massiv verbessert.
```php
// src/Logic/Sales/Order/Orchestrator/
readonly class OrderFulfillmentOrchestrator
{
public function __construct(
private OrderManagerInterface $orders,
private StockManagerInterface $stock,
private TransactionManagerInterface $transactions,
) {}
public function fulfillOrder(CreateOrderRequest $request): Order
{
return $this->transactions->execute(function() use ($request) {
if (!$this->stock->isSufficient($request->items)) {
throw new InsufficientStockException();
}
// Business Model anlegen & persistieren
$order = new Order(/* ... */);
return $this->orders->create($order);
});
}
}
// Der UseCase profitiert von der schlanken Injektion:
readonly class CreateOrderUseCase {
public function __construct(
private OrderFulfillmentOrchestrator $orchestrator,
private EventDispatcherInterface $eventDispatcher,
) {}
public function execute(CreateOrderRequest $request): CreateOrderResponse {
$order = $this->orchestrator->fulfillOrder($request);
$this->eventDispatcher->dispatch(new OrderCreatedEvent(orderId: $order->id));
return new CreateOrderResponse(orderId: $order->id);
}
}
```
### DTOs (Data Transfer Objects) ### DTOs (Data Transfer Objects)
- **Typ**: Readonly-Klassen (PHP 8.2+). - **Typ**: Readonly-Klassen (PHP 8.2+).