Какие метрики кода важны для оценки качества?php-90

CQRS

Суть паттерна

CQRS — это архитектурный паттерн, разделяющий операции чтения (Query) и записи (Command) в разные модели.

Основные принципы:

  1. Разделение моделей:

    • Командная модель (для изменения состояния)
    • Читающая модель (для отображения данных)
  2. Разные каналы:

    • Команды (вызывают изменения)
    • Запросы (не изменяют состояние)

Реализация в PHP:

// Command
class CreateUserHandler
{
    public function __construct(private UserRepository $users) {}

    public function handle(CreateUserCommand $command): void
    {
        $user = User::create($command->email, $command->password);
        $this->users->save($user);
    }
}

// Query
class UserListQueryHandler
{
    public function __construct(private UserReadModel $readModel) {}

    public function handle(UserListQuery $query): array
    {
        return $this->readModel->findAll($query->limit, $query->offset);
    }
}

Преимущества:

  • Масштабируемость (разные БД для чтения/записи)
  • Оптимизация под конкретные задачи
  • Более чистая архитектура

Event Sourcing

Суть паттерна

Хранение состояния системы как последовательности событий, а не текущего состояния.

Ключевые компоненты:

  1. События (Events) — факты, которые уже произошли
  2. Агрегаты (Aggregates) — обрабатывают команды и генерируют события
  3. Event Store — хранилище событий
  4. Projections — преобразуют события в читаемые модели

Пример реализации:

class UserAggregate
{
    private array $events = [];

    public static function create(UserId $id, string $email): self
    {
        $user = new self();
        $user->record(new UserCreated($id, $email));
        return $user;
    }

    private function record(object $event): void
    {
        $this->events[] = $event;
    }

    public function getEvents(): array
    {
        return $this->events;
    }
}

class EventStore
{
    public function append(AggregateId $id, array $events): void
    {
        // Сохранение событий
    }
}

Процесс восстановления состояния:

class UserAggregateReconstructor
{
    public function reconstruct(UserId $id, array $events): UserAggregate
    {
        $user = new UserAggregate();

        foreach ($events as $event) {
            $user->apply($event);
        }

        return $user;
    }
}

Комбинация CQRS и Event Sourcing

Типичная архитектура:

  1. Command Side:

    • Принимает команды
    • Генерирует события
    • Сохраняет в Event Store
  2. Query Side:

    • Слушает события
    • Обновляет читаемые модели
    • Оптимизирован для запросов

Пример потока данных:

// 1. Обработка команды
$command = new CreateUserCommand('test@example.com');
$handler->handle($command);

// 2. Генерация события
$events = $aggregate->getEvents();
$eventStore->append($userId, $events);

// 3. Обновление проекции
$projector->handleEvents($events);

Практические аспекты

Когда использовать:

  • CQRS: Когда нагрузка чтения/записи сильно различается
  • Event Sourcing: Когда важна полная история изменений

Сложности:

  1. Сложность реализации
  2. Согласованность данных (Eventual Consistency)
  3. Миграции данных

Инструменты для PHP:

  • Broadway (CQRS/ES framework)
  • Prooph (Event Sourcing toolkit)
  • Symfony Messenger (для обработки команд/событий)

Резюмируем:

CQRS и Event Sourcing — мощные паттерны для сложных систем. CQRS разделяет ответственность за чтение и запись, а Event Sourcing сохраняет историю изменений как последовательность событий. Вместе они обеспечивают масштабируемость, гибкость и надежность, но требуют более сложной архитектуры и подходят не для всех проектов.