Назад к вопросам
Middle+
90
questionbank

Что такое агрегат?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Агрегат в предметно-ориентированном проектировании (DDD) — это кластер связанных объектов, которые рассматриваются как единое целое с точки зрения целостности данных. У каждого агрегата есть корневой объект-сущность (Aggregate Root), который является единственной точкой доступа к другим объектам внутри агрегата. Все изменения внутри агрегата должны происходить через корневой объект для поддержания инвариантов (правил целостности).

Ключевые характеристики:

  • Корневой объект (Aggregate Root): Единственная точка доступа к компонентам агрегата.
  • Инкапсуляция: Внутренние объекты агрегата не должны быть доступны извне напрямую.
  • Граница согласованности: Агрегат определяет границу, внутри которой поддерживаются инварианты. Изменения внутри агрегата транзакционно согласованы.
  • Изоляция: Напрямую взаимодействовать с объектами другого агрегата нельзя, только через их корневые объекты или через сервисы домена.

Пример:

<?php

// Корневой объект агрегата "Заказ"
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
    {
        // Проверка инвариантов, например, количество > 0
        if ($quantity <= 0) {
            throw new InvalidArgumentException("Количество должно быть больше нуля.");
        }

        $this->items[] = new OrderItem($productId, $quantity, $price);
    }

    public function confirm(): void
    {
        // Проверка инвариантов перед изменением статуса
        if ($this->status !== OrderStatus::Pending) {
            throw new DomainException("Заказ уже не в статусе 'Ожидание'.");
        }

        // Логика подтверждения, например, проверка наличия товаров
        $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;
    }
}

// Внутренний объект агрегата "Строка заказа"
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;
    }
}

// Value Objects (для примера)
final class OrderId {}
final class CustomerId {}
final class ProductId {}
final class Money {}
enum OrderStatus { case Pending; case Confirmed; case Cancelled; }