IT заметки по программированию
IT заметки по программированию
IT заметки по программированию
IT заметки по программированию

Понимание принципа инверсии зависимостей

Низкоуровневые модули теперь зависят от абстракций, а не наоборот

Принцип инверсии зависимостей (Dependency Inversion Principle, DIP) говорит, что:

  • Высокоуровневые модули (логика) не должны зависеть от низкоуровневых (деталей реализации). Оба должны зависеть от абстракций.
  • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Плохой код без инверсии зависимостей

Допустим, у нас есть сервис, который работает напрямую с базой данных:

Проблемы:

  • Сервис жёстко привязан к MySQL.
  • Если нужно заменить MySQL на PostgreSQL, придётся менять код.
  • Код сложно тестировать, потому что нельзя подставить фейковую реализацию.

Правильный код с инверсией зависимостей

Сначала создаём абстракцию (интерфейс):

Теперь сервис будет зависеть не от конкретной базы данных, а от интерфейса:

Теперь реализуем этот интерфейс для MySQL:

И для PostgreSQL:

Теперь мы можем легко менять реализацию без изменения кода сервиса:

Раньше высокоуровневый модуль (UserService) зависел от деталей (MySQL). Теперь детали (MySQL, PostgreSQL) зависят от абстракции (UserRepository).

Это и есть инверсия зависимостей: теперь низкоуровневые модули должны реализовать интерфейс, который диктует высокоуровневый модуль.

Когда мы говорим «API (или БД или любой другой низкоуровневый модуль) зависит от интерфейса», мы имеем в виду, что он реализует этот интерфейс.

То есть, вместо того чтобы логика программы жёстко зависела от конкретного API-клиента или базы данных, мы сначала создаём абстракцию (интерфейс), а потом реализация API или БД «подстраивается» (зависит) под него.


🔹 Пример: как API зависит от интерфейса

Допустим, у нас есть сервис, который получает данные либо из API, либо из БД.

Создаём интерфейс (DataSource)

Теперь не сервис зависит от API или БД, а API и БД зависят от интерфейса:

API-клиент реализует этот интерфейс

Теперь API зависит от интерфейса, потому что оно реализует DataSource:

БД тоже реализует интерфейс

Точно так же БД теперь зависит от интерфейса:

Сервис работает через интерфейс

Теперь наш сервис вообще не знает, API это или БД — он работает только с DataSource:

Запускаем код

Теперь можно легко переключаться между API и БД:

Вывод

API и БД теперь «зависят» от интерфейса, потому что они обязаны его реализовать.
Сервис теперь не знает деталей реализации, а работает через интерфейс.
Мы можем легко подставлять другие реализации без изменения кода DataService.

То есть «зависимость» в этом контексте — это не «использование», а «подчинение интерфейсу».

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *