Одним из принципов SOLID является инверсия зависимостей (dip). В литературе по программированию и в интернете масса источников с детальным описанием этого принципа. И большинство кандидатов на собеседовании успешно отвечают заученными фразами на вопрос: "Что такое инверсия зависимости?". Но при практической реализации мгновенно возникает вопрос, а в чем же собственно заключается инверсия и как она программируется? Далее будет рассмотрен данный принцип более подробно.

Прямой ход зависимости

Сделаем небольшое отступление к истокам программирования. Самые первые программы, до появления полиморфизма и объектно-ориентированного подхода, выглядели примерно следующим образом.

Зависимости были направлены в одном направлении. Но возникает проблема, и не одна.

  1. Controller зависит от деталей реализации - методов calculateFulltimeSalary() и caclculatePartialTimeSalary().

  2. Нетрудно догадаться, что при добавлении нового типа работника нужно будет редактировать объект Controller.

  3. При добавлении очередного метода в Controller он быстро разрастется до небывалых размеров.

Поэтому в программе стали оделять те части, которые зависят от аппаратуры, данных, и т.п. Таким образом, скажем, при появлении нового принтера, достаточно было запрограммировать его управление (драйвер), а логика по подготовке документа для печати оставалась неизменной.

Инверсия зависимости

С появлением объектно-ориентированного подхода и полиморфизма стало возможным скрывать реализацию метода за интерфейсом класса. Именно поэтому в одном из самых популярных источников сказано, что классы должны зависеть от абстракций, а не от конкретных деталей [1], что привело примерно к следующей картине.

На схеме отражена суть инверсии - в какой-то момент времени стрелка зависимости становится направлена в обратном направлении.

Полиморфизм и ООО выходят за рамки данной статьи и обсуждаться не будут.

Заключение

Выучить наизусть фразу из любого источника по программированию и успешно пройти собеседование еще не означает наличие знания и понимания техники программирования. Более того, удивляет наличие огромного количества статей, которые не могут в краткой и ясной форме объяснить суть пятого из принципов SOLID [2]. Целью этой статьи была передача опыта и, что более важно, желание находится в среде образованных профессионалов, а не дилетантов.

Более того, вы всегда можете перейти к первой в поиске статье на эту тему [3].

Список источников

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

  2. SOLID

  3. Подробное руководство по инверсии зависимостей. Часть 1

Комментарии (8)


  1. lamerok
    19.12.2022 19:12
    +2

    Главное, что про С++, ведь инверсия зависимостей она только там.


  1. dopusteam
    19.12.2022 20:33
    +4

    Схема сильно упрощена, но в ней отражена суть инверсии - в какой-то момент времени стрелка становится направлена в обратном направлении

    Объяснение от бога, конечно


    1. AceRodstin Автор
      19.12.2022 21:45
      -1

      Очевидно, что речь идет про стрелку зависимости.


  1. AceRodstin Автор
    19.12.2022 21:05
    -4

    Написано в стиле источника [1]. Кратко и по-сути.

    С той лишь разницей, что показано, **где возникает инверсия**.


  1. lair
    19.12.2022 21:59
    +4

    В ваших диаграммах даже не понятно, что обозначает стрелочка. Что уж говорить о том, каким же волшебством она разворачивается?


  1. vin2809
    20.12.2022 08:08
    +1

    Мне одному кажется, что в статье пропущено 99 процентов текста?


  1. manyakRus
    20.12.2022 13:30

    Работник должен сам себе зарплату рассчитывать ?
    На первой схеме: Работник обращается - в отдел бухгалтерии - бухгалтеры заходят в программу 1С и расситывают зарплату.
    На второй схеме: Работник обращается - в отдел бухгалтерии - бухгалтеры говорят: посчитайте себе зарплату сами :-)

    т.е. первая схема лучше :-)


  1. gdt
    20.12.2022 19:59

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