Прямо и просто

Я работаю инженером-программистом уже несколько лет, но время от времени мне нравится возвращаться к основам. Мы все знаем, что должны следовать НАДЕЖНЫМ принципам старого доброго дядюшки Боба, но общие знания не всегда являются общепринятой практикой.

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

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

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

Чтобы проиллюстрировать эту концепцию, давайте предположим, что вы инженер-программист. У вас есть две зависимости: ваш редактор кода и ваша еда. Вы не хотите зацикливаться на VSCode для всего и не хотите есть пиццу весь день. Кроме того, что произойдет, если они изменят детали реализации пиццы, и теперь это будет ужасно?

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

Внедрение зависимости

Внедрение зависимостей — это шаблон проектирования, который позволяет нам отделить создание от использования. Это позволяет нам «внедрять» необходимые объекты во время выполнения, не беспокоясь об их создании самостоятельно. Он также имеет тенденцию работать рука об руку с принципом инверсии зависимостей.

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

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

К счастью для вас, у вас есть внедрение зависимостей!
Вам не нужно готовить пиццу или создавать редактор кода — вы можете предположить, что он уже создан для вас и внедрен именно там, где вам это нужно.
Кроме того, вы не застряли с пиццей и VSCode на вечность. Вы можете быть агностиком к еде и позволить конфигурации решать, собираетесь ли вы сегодня есть (или получать инъекцию, ДАААААА) пиццу или рамен.

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

Однако я так и не осветил, почему это называется «инверсия», что именно здесь инвертировано? Что ж, я обещал вам историю! (не волнуйтесь, он короткий)

Почему мы называем эту зависимость «инверсией»?

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

В этой архитектуре компоненты более высокого уровня напрямую зависели от компонентов более низкого уровня для выполнения сложной задачи.

Приготовление пиццы — старый способ VS «перевернутый» способ

Чтобы проиллюстрировать «инверсию», взгляните на функцию preparePizza ниже:

Функция высокого уровня полагается на две конкретные реализации для выполнения своей задачи.

Теперь давайте посмотрим на пример, использующий внедрение зависимостей и инверсию зависимостей:

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

Что мы сегодня узнали

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

Я надеюсь, что вы нашли эту статью полезной, и до следующего раза, чтобы она была прямолинейной и простой!