Опанування подієвого роз'єднання (Event-Driven Decoupling) у Laravel

Ваші контролери Laravel часто перетворюються на «сміттєзвалища» для бізнес-логіки.

Ви починаєте з простого процесу реєстрації. Незабаром ви додаєте сповіщення електронною поштою, сповіщення у Slack, журнали аудиту та API-виклики в один єдиний метод. Це створює «товстий» контролер (fat controller).

«Товсті» контролери роблять ваш код крихким. Їх важко тестувати. Вони порушують принцип єдиної відповідальності (Single Responsibility Principle).

Вам не потрібні складні інструменти на кшталт RabbitMQ, щоб виправити це. Laravel має вбудовану систему подій, яка задовольняє більшість потреб.

Проблема жорсткого зв'язку (tight coupling): Якщо API розсилки новин працює повільно, реєстрація користувача також сповільнюється. Якщо сервіс електронної пошти дає збій, весь запит завершується помилкою.

Рішення: Подієво-орієнтована архітектура (Event-Driven Architecture).

Події виступають як проміжний шар. Ваш контролер оголошує про дію. Слухачі (listeners) реагують на цю дію незалежно.

«Тонкий» контролер виглядає так:

public function register(RegisterRequest $request) { $user = User::create($request->validated());

UserRegistered::dispatch($user);

return response()->json(['message' => 'Success'], 201);

}

Тепер контролер займається лише збереженням даних. Його не хвилюють побічні ефекти.

Ви отримуєте три основні переваги:

  • Продуктивність: Користувачі отримують відповідь миттєво. Важкі завдання виконуються у фоновому режимі за допомогою інтерфейсу ShouldQueue.
  • Стійкість: Якщо сервіс недоступний, слухач може повторити завдання, не порушуючи роботу основного додатка.
  • Розширюваність: Ви можете додавати нові функції, наприклад push-сповіщення, просто додавши нового слухача. Вам не потрібно змінювати оригінальний контролер.

Рекомендації (Best practices), яких варто дотримуватися:

  • Зосередьтеся на побічних ефектах: Використовуйте події для пост-обробки. Не використовуйте їх для основної логіки, яка має виконутися миттєво.
  • Використовуйте описові назви: Використовуйте назви у минулому часі, як-от OrderPlaced або UserRegistered. Це вказує на те, що дія вже відбулася.
  • Уникайте надмірної абстракції: Якщо фрагмент коду простий і використовується лише в одному місці, виклик функції кращий за подію.

Використовуйте Eloquent Observers для змін у базі даних. Використовуйте Events для бізнес-дій.

Рефакторинг на події — це про стабільність. Це робить ваш код легшим для налагодження та швидшим для тестування.

Оберіть сьогодні один «шумний» побічний ефект у своєму контролері та перенесіть його в слухача.

Спробуйте цей приклад у пісочниці: https://onlinephp.io/c/1f7b2

Джерело: https://dev.to/codecraft_diary_3d13677fb/beyond-fat-controllers-mastering-event-driven-decoupling-in-laravel-2dd6