Middle+
Czym jest agregat?
sobes.tech AI
Odpowiedź od AI
Agregat w projektowaniu obiektowym (DDD) to klaster powiązanych obiektów, które są traktowane jako jednostka pod względem integralności danych. Każdy agregat ma obiekt korzeniowy (Root agregatu), który jest jedynym punktem dostępu do innych obiektów w ramach agregatu. Wszystkie zmiany w agregacie powinny być dokonywane przez obiekt korzeniowy, aby utrzymać invariants (zasady integralności).
Kluczowe cechy:
- Obiekt korzeniowy (Root agregatu): Jedyny punkt dostępu do komponentów agregatu.
- Enkapsulacja: Obiekty wewnętrzne agregatu nie powinny być dostępne bezpośrednio z zewnątrz.
- Granica spójności: Agregat definiuje granicę, w której utrzymywane są invariants. Zmiany w agregacie są transakcyjnie spójne.
- Izolacja: Nie można bezpośrednio wchodzić w interakcję z obiektami innego agregatu, tylko przez ich obiekty korzeniowe lub przez usługi domenowe.
Przykład:
<?php
// Obiekt korzeniowy agregatu "Zamówienie"
class Order
{
private OrderId $id;
private CustomerId $customerId;
/** @var OrderItem[] */
private array $items = [];
private OrderStatus $status;
public function __construct(OrderId $id, CustomerId $customerId)
{
$this->id = $id;
$this->customerId = $customerId;
$this->status = OrderStatus::Pending;
}
public function addItem(ProductId $productId, int $quantity, Money $price): void
{
// Sprawdzanie invariants, np. ilość > 0
if ($quantity <= 0) {
throw new InvalidArgumentException("Ilość musi być większa od zera.");
}
$this->items[] = new OrderItem($productId, $quantity, $price);
}
public function confirm(): void
{
// Sprawdzanie invariants przed zmianą statusu
if ($this->status !== OrderStatus::Pending) {
throw new DomainException("Zamówienie nie jest już w statusie 'Oczekiwanie'.");
}
// Logika potwierdzenia, np. sprawdzenie dostępności towarów
$this->status = OrderStatus::Confirmed;
}
public function getId(): OrderId
{
return $this->id;
}
public function getStatus(): OrderStatus
{
return $this->status;
}
/** @return OrderItem[] */
public function getItems(): array
{
return $this->items;
}
}
// Obiekt wewnętrzny agregatu "Pozycja zamówienia"
class OrderItem
{
private ProductId $productId;
private int $quantity;
private Money $price;
public function __construct(ProductId $productId, int $quantity, Money $price)
{
$this->productId = $productId;
$this->quantity = $quantity;
$this->price = $price;
}
public function getProductId(): ProductId
{
return $this->productId;
}
public function getQuantity(): int
{
return $this->quantity;
}
public function getPrice(): Money
{
return $this->price;
}
}
// Obiekty wartości (przykład)
final class OrderId {}
final class CustomerId {}
final class ProductId {}
final class Money {}
enum OrderStatus { case Pending; case Confirmed; case Cancelled; }