Читал ли книгу Эванса «Domain-Driven Design»?

Ответ

Да, "Domain-Driven Design: Tackling Complexity in the Heart of Software" Эрика Эванса — это классика, которая сильно повлияла на мой подход к проектированию сложных бизнес-систем. Ключевая ценность книги — введение единого языка (Ubiquitous Language) между разработчиками и экспертами предметной области и тактические паттерны для его отражения в коде.

В PHP-проектах я применяю такие паттерны DDD, как:

  • Value Objects для представления неделимых, неизменяемых концепций (Email, Money).
  • Aggregates для инкапсуляции инвариантов и управления целостностью группы связанных сущностей.
// Пример Value Object и Aggregate Root
final class Email implements Stringable {
    private function __construct(private string $value) {}

    public static function fromString(string $value): self {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Invalid email');
        }
        return new self($value);
    }
    public function __toString(): string { return $this->value; }
}

class Order // Aggregate Root
{
    private array $lineItems = [];
    private OrderStatus $status;

    public function addLineItem(ProductId $productId, Quantity $qty, Price $price): void {
        // Инвариант: нельзя добавлять товары в завершенный заказ
        if ($this->status->isFinal()) {
            throw new OrderAlreadyFinalizedException();
        }
        $this->lineItems[] = new LineItem($productId, $qty, $price);
    }
}

Книга Эванса задает стратегический каркас, а для практической реализации в PHP я также рекомендую книги Вона Вернона и примеры из фреймворков, таких как Broadway (для CQRS/Event Sourcing).

Ответ 18+ 🔞

А, "Domain-Driven Design" Эрика Эванса! Ну это, ёпта, прям фундамент, на котором мозги у многих встали с правильной стороны. Книга-то, конечно, не для слабаков — читаешь и чувствуешь, как из ушей пар идёт, но оно того стоит, честно.

Вот в чём её главный фокус, который многих накрывает, как медный таз: она заставляет тебя говорить с бизнесменами и экспертами на одном языке. Не на этом своём программистском жаргоне, где всё "модели", "сервисы" и "репозитории", а на нормальном человеческом, который в бизнесе используют. Это и есть тот самый "единый язык" (Ubiquitous Language). И потом ты этот язык прямо в код пишешь, чтобы он не был оторван от реальности, как хуй с горы. Без этого получается пиздопроебибна: ты одно имел в виду, заказчик — другое, а в итоге система работает, но не так, и всем пиздец.

В PHP-то как это выглядит? Ну, например, эти ваши Value Objects. Это же просто песня! Вместо того чтобы таскать строку $email по всему коду и в каждом методе проверять, а валидная ли она, ты создаёшь объект Email. Один раз проверяешь при создании — и всё, потом можешь спать спокойно. Он неизменяемый, сам себя контролирует. Красота!

// Вот смотри, как это просто и элегантно
final class Email implements Stringable {
    private function __construct(private string $value) {}

    public static function fromString(string $value): self {
        // Один раз, при рождении, проверяем — и забываем
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Ну и что это за хуйню ты мне подсунул? Это не email!');
        }
        return new self($value);
    }
    public function __toString(): string { return $this->value; }
}

А ещё есть Aggregates (Агрегаты). Вот это, блядь, мощнейшая штука для контроля над своим куском данных. Представь себе заказ (Order) в интернет-магазине. В нём есть сам заказ, список товаров, статус... Так вот, Агрегат — это такой главный по тарелке, который следит, чтобы внутри его группы всё было по правилам. Нельзя просто так взять и изменить товар в завершённом заказе. Агрегат тебе не даст, он инварианты проверяет.

class Order // Вот он, корень агрегата (Aggregate Root), главный
{
    private array $lineItems = [];
    private OrderStatus $status;

    public function addLineItem(ProductId $productId, Quantity $qty, Price $price): void {
        // А вот и инвариант: в завершённый заказ хуй что добавишь!
        if ($this->status->isFinal()) {
            throw new OrderAlreadyFinalizedException('Ты чё, охренел? Заказ уже закрыт!');
        }
        $this->lineItems[] = new LineItem($productId, $qty, $price);
    }
}

Эванс, конечно, гений, он стратегию построил. Но чтобы не бздеть при реализации, особенно в PHP, надо и других авторов почитать. Вон Вернон, например, хорошо так тактические паттерны разжёвывает. И смотреть на готовые примеры из фреймворков вроде Broadway — там прямо живые примеры, как это CQRS да Event Sourcing в дело воплощать. Без этого можно в теории утонуть, ебать мои старые костыли.