Ответ
Доменный слой — это ядро приложения, содержащее бизнес-логику, правила и сущности предметной области. Он полностью независим от инфраструктуры (БД, HTTP, фреймворка) и слоя представления. В моих проектах на PHP (часто с DDD-подходом) он включает:
- Сущности (Entities): Объекты с идентификатором, жизненным циклом (например,
User,Order). - Объекты-значения (Value Objects): Неизменяемые объекты без идентификатора (например,
EmailAddress,Money). - Агрегаты (Aggregates): Кластер связанных сущностей и VO с корневым агрегатом (например,
Orderкак корень сOrderItemвнутри). - Доменные сервисы (Domain Services): Логика, не принадлежащая естественным образом какой-либо сущности.
- События домена (Domain Events): Факты, произошедшие в домене (например,
OrderWasPlaced).
Пример сущности Order с бизнес-правилами:
class Order
{
private string $id;
private OrderStatus $status;
/** @var OrderLine[] */
private array $lines = [];
private ?DateTimeImmutable $paidAt = null;
private function __construct(string $id) {
$this->id = $id;
$this->status = OrderStatus::NEW;
}
public static function create(string $id): self {
return new self($id);
}
public function addLine(Product $product, int $quantity): void {
// Доменное правило: нельзя изменить оплаченный заказ
if ($this->status === OrderStatus::PAID) {
throw new DomainException('Cannot modify a paid order.');
}
// Доменное правило: минимальное количество
if ($quantity < 1) {
throw new DomainException('Quantity must be at least 1.');
}
$this->lines[] = new OrderLine($product, $quantity);
}
public function markAsPaid(): void {
// Доменное правило: оплатить можно только новый заказ
if ($this->status !== OrderStatus::NEW) {
throw new DomainException('Only new orders can be paid.');
}
$this->status = OrderStatus::PAID;
$this->paidAt = new DateTimeImmutable();
$this->recordEvent(new OrderPaid($this->id)); // Генерация события
}
public function totalAmount(): Money {
// Вычисление на основе правил домена
$total = Money::USD(0);
foreach ($this->lines as $line) {
$total = $total->add($line->subtotal());
}
return $total;
}
}
Главный принцип: Доменный слой — это самая важная и стабильная часть. Его можно протестировать изолированно, без БД или веб-сервера, что я и делаю с помощью юнит-тестов.