Почему лучше использовать внедрение зависимостей (DI) вместо создания новых экземпляров классов напрямую?

Какая из следующих методик использования сервисов в проекте является более целесообразной: применение создания экземпляра сервиса внутри функций классов с помощью (new MyService())->getData(), или передача сервиса через конструктор класса или метод контроллера?
  • 8 февраля 2024 г. 10:10
Ответы на вопрос 2
Внедрение зависимостей (Dependency Injection, DI) предпочтительнее прямого создания экземпляров классов по нескольким причинам:

1. Повышение модульности и гибкости: использование DI позволяет классам быть менее зависимыми от конкретных реализаций сервисов, с которыми они работают. Это означает, что вы можете легче изменять или заменять зависимости без изменения класса, который их использует.

2. Улучшение тестируемости: когда вы внедряете зависимости, становится проще проводить модульное тестирование, поскольку можно легко заменять реальные реализации сервисов на моки или заглушки.

3. Управление жизненным циклом: фреймворки, поддерживающие DI, обычно предоставляют удобные средства для управления жизненным циклом объектов. Например, они могут автоматически создавать синглтоны или управлять временем жизни объекта в соответствии с контекстом (например, запросом).

4. Лучшая организация кода: DI позволяет разработчикам более чётко выразить намерения по использованию зависимостей и улучшает читаемость кода.

5. Облегчение интеграции: использование DI облегчает интегрирование с различными фреймворками и инструментами, которые также используют DI для настройки и связывания компонентов.

Теперь касаемо того, как лучше использовать сервисы в проекте. В общем случае сервисы предпочтительнее передавать через конструктор класса или метод контроллера (подход Dependency Injection), вместо того чтобы создавать их экземпляры напрямую в методах класса с помощью `(new MyService())->getData()`. Это обеспечивает ряд преимуществ, которые были перечислены выше, а именно:

- Зависимости становятся явными и легко анализируемыми.
- Упрощается подмена реальных экземпляров сервисов на моки в тестах.
- Сокращается связность (coupling) между классами, т.к. они не несут ответственности за создание экземпляров своих зависимостей.
- Повышается гибкость, так как замена или изменение используемого сервиса требует изменений только в местах, где внедряется зависимость, но не в коде, который эту зависимость использует.

Использование DI фреймворков или контейнеров может дополнительно упростить управление зависимостями, делая код чище, изменяемее и более удобное для поддержки.
Вот почему: PHPunit замокать класс внутри тестируемого класса? 
Бонус-раунд: DI упрощает работу с зависимостями зависимостей. Если ваш MyService принимает какой-нибудь логер в зависимостях, который в свою очередь ожидает какой-нибудь драйвер файловой системы, вы задолбаетесь собирать их через new.
Похожие вопросы