feat: define Read Pattern (BusinessQuery -> Manager -> Provider)
This commit is contained in:
@@ -94,4 +94,83 @@ readonly class CreateOrderResponse
|
|||||||
public string $orderId,
|
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 [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user