PHP

Простой рецепт отвязывания логики приложения от фреймворка

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

Три простых правила

Чтобы отвязаться от фреймворка вам нужно следовать только этим простым правилам:
  1. Все службы должны получить все свои зависимости и значения конфигурации через аргументы конструктора. Когда зависимость использует IO, вы должны ввести для нее абстракцию.
  2. Другие типы объектов не должны иметь служебных обязанностей.
  3. Контекстная информация всегда должна передаваться в качестве аргументов метода.

Подробное объяснение

Правило 1

Гарантирует, что вы никогда не будете извлекать службу специально, например, используя Container::get(UserRepository::class). Это необходимо для отвязки от фреймворка, поскольку глобальный статический объект, возвращающий Вам сервис, по определению зависит от фреймворка. То же самое верно и для выборки значений конфигурации (например, Config::get('email.default_sender')).

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

Правило 2

Помимо служб существует несколько других типов объектов, таких как сущности, объекты значений, доменные события и объекты передачи данных, которые не несут ответственности за обслуживание. Ни у кого из них не должно быть обязанностей по обслуживанию, потому что это означает, что они либо будут вызывать службы через какой-то глобальный статический объект, либо им нужна специальная настройка фреймворка/ORM, что означает, что они не могут использоваться изолированно и не переживут серьезного обновления фреймворка или переключения. Примером объекта, который не следует правилу 2, является модель Active Record, которая может выглядеть как сущность, но способна сохранять себя, что на самом деле является обязанностью службы.

Правило 3

Контекстная информация обычно выводится из текущего веб-запроса или сеанса пользователя, например идентификатор пользователя, который в данный момент вошел в систему. Вместо того чтобы извлекать эти данные всякий раз, когда они вам нужны (например, Auth::getUser()->getId()), вы должны передавать их из метода в метод в качестве обычного аргумента.

Вместе взятые, правила 1, 2 и 3 гарантируют, что для каждого метода совершенно ясно, что он делает, какие данные ему нужны и на какие служебные зависимости он полагается для выполнения своей работы. Кроме того, ни одна из зависимостей или аргументов метода не будет зависеть от фреймворка или библиотеки, а это означает, что ваш код приложения будет эффективно отвязан от фреймворка.

Вывод

Если вы спросите меня, эти правила действительно очень просты, и они не требуют много дополнительной работы по сравнению с жесткой привязкой всего к текущему набору установленных пакетов вашего проекта. Так почему бы не следовать им, если вы знаете, что ваш проект должен соответствовать текущим стандартам через 3 года?

P.S. Следование этим правилам дает вам гораздо больше, чем просто разделение фреймворка: все становится тестируемым изолированно, тесты полностью детерминированы и, следовательно, очень стабильны, и они действительно быстро запускаются.

https://matthiasnoback.nl/2020/09/simple-recipe-for-framework-decoupling/

PHP

Leave a reply