Ответ
В архитектуре приложений для выполнения действий при создании сущности я использую события (Events) или хуки жизненного цикла (Lifecycle Hooks) в ORM. Это позволяет отделить побочную логику (логирование, отправку уведомлений, вычисление производных полей) от основной бизнес-логики создания.
Пример с событиями в рамках чистой архитектуры:
// 1. Создаем событие
class ProductWasCreated {
public function __construct(public Product $product) {}
}
// 2. Сервис создания продукта генерирует событие
class CreateProductService {
public function __construct(private EventDispatcher $dispatcher) {}
public function execute(CreateProductCommand $command): Product {
$product = new Product($command->name, $command->price);
// ... сохранение в репозитории
$this->dispatcher->dispatch(new ProductWasCreated($product));
return $product;
}
}
// 3. Отдельный обработчик реагирует на событие
class SendWelcomeEmailOnProductCreation {
public function __invoke(ProductWasCreated $event): void {
$product = $event->product;
// Отправка email, запись в аудит-лог и т.д.
}
}
Плюсы подхода:
- Гибкость и расширяемость: Новые действия добавляются как независимые обработчики, не изменяя основной код.
- Тестируемость: Логику создания и побочные действия можно тестировать изолированно.
- Асинхронность: Обработчики можно вынести в очередь задач (например, через RabbitMQ), чтобы не блокировать ответ пользователю.
Для простых случаев в рамках фреймворка (например, Laravel Eloquent или Doctrine) можно использовать встроенные хуки creating/created или аннотации @PrePersist.
Ответ 18+ 🔞
Ну и хули тут думать, архитектура же, ёпта! Когда сущность создаётся, а тебе надо ещё кучу всякой хуйни по сторонам сделать — логирование там, письма разослать, соседям сообщить — то самый отстойный вариант — это всё впихнуть в один сервис. Получится пиздопроебибна каша, в которой через полгода нихуя не разберёшься.
Вот смотри, нормальные пацаны для этого используют события (Events) или хуки жизненного цикла (Lifecycle Hooks) в ORM. Суть простая: основная логика делает своё дело — создаёт продукт, а потом кричит на всю деревню: «Эй, мужики, продукт создан!». А уже кто хочет — тот и реагирует. Чисто, изящно, волнение ебать как снижается.
Вот тебе пример, как это в чистой архитектуре выглядит, чтобы мозг не взорвался:
// 1. Сначала объявляем событие. Типа, официальная бумажка.
class ProductWasCreated {
public function __construct(public Product $product) {}
}
// 2. Сервис, который создаёт продукт. Он тупо работает и шумит.
class CreateProductService {
public function __construct(private EventDispatcher $dispatcher) {}
public function execute(CreateProductCommand $command): Product {
$product = new Product($command->name, $command->price);
// ... тут он сохраняет это добро в базу через репозиторий
// А вот тут магия! Кидаем событие в мир.
$this->dispatcher->dispatch(new ProductWasCreated($product));
return $product;
}
}
// 3. А это уже какой-то другой мудак, который подслушал событие и делает свою фигню.
class SendWelcomeEmailOnProductCreation {
public function __invoke(ProductWasCreated $event): void {
$product = $event->product;
// И пошло-поехало: письма, логи, оповещения — делай что хочешь.
}
}
А теперь, бля, почему это овердохуища круто:
- Гибкость пиздец: Захотел добавить новое действие — написал новый обработчик и подписал его на событие. Основной код сервиса даже не чихнул. Никакого «а давайте сюда ещё строчку».
- Тестируется на ура: Сервис создания тестируешь отдельно, каждый обработчик — отдельно. Никаких танцев с бубном вокруг монолита.
- Можно не тормозить пользователя: Обработчики-то можно в очередь задач засунуть (типа RabbitMQ). Создал продукт — сразу отдал ответ, а письма там пусть в фоне шлются, хоть минуту. Пользователь доволен, удивление пиздец какое.
Ну а если проект маленький и навороченный фреймворк под капотом (Laravel Eloquent или Doctrine), то можно и родными хуками воспользоваться — creating/created или там аннотациями @PrePersist. Но это уже как бы для лёгких случаев, когда не хочется заморачиваться с полноценной шиной событий. Главное — принцип понял? Отделяй мух от котлет, основную логику от побочной, и жить станет проще.