Узнайте, являются ли Model Observers в Laravel плохой практикой

Узнайте, являются ли Model Observers в Laravel плохой практикой

11 ноября 2022 г.

Laravel предоставляет интересный способ автоматизации общих событий модели внутри вашего приложения с помощью отправляемых событий, событий закрытия и наблюдателей< /а>.

Несмотря на то, что такое готовое решение звучит круто, в некоторых случаях это будет иметь неприятные последствия для вашего проекта, если вы склонны перегружать эту функцию бизнес-логикой.


TL;DR

Наиболее распространенные побочные эффекты можно наблюдать при написании и запуске модульных и функциональных тестов для вашего приложения Laravel. Эта статья продемонстрирует этот сценарий.


Наш пример

Обработка измерений температуры с устройств Интернета вещей, сохранение их в базе данных и выполнение дополнительных расчетов после использования каждого образца.

Наши бизнес-требования:


Это наш пример модели и миграции:

Теперь каждый раз, когда мы сохраняем образец, мы хотим сохранить среднюю температуру для последних 10 образцов в другой модели, Avg Temperature:

Мы можем добиться этого, просто присоединив событие к состоянию created модели Sample:

Теперь добавим прослушиватель с логикой пересчета среднего:

Теперь наша наивная реализация контроллера, **пропускающая проверку и все хорошие шаблоны разработки**, будет выглядеть так:

Мы также можем написать тест функций, который подтвердит, что наш маршрут API работает должным образом — образец сохраняется и средний образец сохраняется:

Test run results

Выглядит прекрасно, правда?


Теперь, когда что-то пойдет не так

Представьте, что второй разработчик в вашей команде собирается написать модульный тест, в котором он хочет проверить расчеты средней температуры.

Для выполнения этой работы он извлекает сервис из класса слушателя:

У него есть написанный модульный тест, в котором он хочет заполнить 100 образцов одновременно с интервалом в 1 минуту:

The test fails on line 28

Это довольно простой пример, и его можно исправить, отключив событие модели или сымитировав весь фасад события на специальной основе.

Для любого более-менее крупного проекта такие варианты болезненны — всегда нужно помнить, что ваша модель создает побочные эффекты.

Представьте, что такое событие создает побочные эффекты в другой базе данных или внешней службе через вызов API. Каждый раз, когда вы создаете образец с фабрикой, вам приходится иметь дело с имитацией внешних вызовов.

У нас есть сочетание плохого шаблона разработки событий модели и недостаточного разделения кода.


Рефакторинг и разделение нашего примера

Для лучшей видимости мы создадим второй набор моделей в нашем проекте и новый маршрут.

Во-первых, мы удаляем событие модели из нашей модели Sample, теперь она выглядит так:

Затем мы создаем службу, которая будет отвечать за потребление новых образцов:

Обратите внимание, что наша служба теперь отвечает за запуск события в случае успеха.

Наш новый обработчик маршрута будет выглядеть так:

Класс запроса:

Теперь мы повторяем тесты нашего второго разработчика с новым маршрутом и можем подтвердить, что он проходит:

Passing unit test


Заключение

Что было улучшено:


Как это помогает:

Репозиторий с кодом можно найти здесь: https://github.com/dkhorev/model-observers-bad-practice .


Также опубликовано здесь


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE