Погрузитесь в популярный шаблон проектирования

Этот пост является частью 5 серии о принципах SOLID.
Вы можете найти пост 4 здесь, пост 3 здесь, пост 2 здесь и пост 1 здесь.

Наконец-то мы достигли последнего из принципов SOLID. Как обычно, начнем с определения:

Принцип 5 называется принципом обращения зависимостей. Определение состоит из двух частей:

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

Б. Абстракции не должны зависеть от деталей. Детали (конкретные реализации) должны зависеть от абстракций.

Источник: Принцип инверсии зависимостей — Википедия

В традиционной архитектуре программного обеспечения мы разрабатываем компоненты более низкого уровня для использования/потребления компонентами более высокого уровня. Другими словами, компоненты более высокого уровня зависят от компонентов более низкого уровня. Эта зависимость вызывает тесную связь в программном обеспечении. Как поясняется в принципе один, мы стремимся добиться слабой связанности, чтобы упростить разработку, поддержку и изменение кода в будущем.

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

Время для некоторого кода и конкретного примера!

Код

Рассмотрим следующий пример, где мы моделируем робота:

Класс Robot имеет только одну функцию get_energy.
Мы моделируем Apple, от которого робот может получать энергию.

Теперь в какой-то момент роботу надоест есть яблоки.
Поэтому мы добавляем класс Chocolate, чтобы предложить роботу больше вариантов еды.

Однако обратите внимание, что происходит с методом get_energy. Мы должны передать строку в качестве параметра, указывающую, что съест робот. Кроме того, мы должны использовать ветвление if-else для двух разных съедобных объектов. Теперь вы можете себе представить, если будет добавлено больше съестных припасов, нам понадобится больше веток else. Это не хороший дизайн.

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

На данный момент наша архитектура выглядит следующим образом:

Решение

Чтобы решить эту проблему, нам нужно ввести уровень абстракции.
Модифицируем архитектуру следующим образом:

Код выглядит так:

Мы создаем интерфейс Eatable, который реализуется как Apple, так и Chocolate.
Мы меняем сигнатуру метода get_energy, чтобы он ожидал аргумент типа Eatable вместо str. Это означает, что мы можем избавиться от ветвления if-else. Кроме того, поскольку все съедобные объекты реализуют интерфейс Eatable, мы уверены, что не будет поломки кода при изменении на Chocolate или Apple.

Заключение

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

Принцип:

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

Наконец-то мы дошли до конца!

Надеюсь, вам понравился этот пост и все предыдущие посты о принципах SOLID.

Первоначально опубликовано на https://haseebkamal.com