docs: enforce 3-4 dependency limit for UseCases and introduce Orchestrator pattern
This commit is contained in:
@@ -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 3–4 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+).
|
||||||
|
|||||||
Reference in New Issue
Block a user