Dependency Inversion Principle. Принцип инверсии зависимостей в разработке::Журнал СА
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Наука и технологии
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Дата-центры  

Дата-центры: есть ли опасность утечки данных?

Российские компании уже несколько лет испытывают дефицит вычислительных мощностей. Рост числа проектов,

 Читать далее...

Книжная полка  

Защиты много не бывает

Среди книжных новинок издательства «БХВ» есть несколько изданий, посвященных методам социальной инженерии

 Читать далее...

Событие  

В банке рассола ждет сисадмина с полей фрактал-кукумбер

Читайте впечатления о слете ДСА 2024, рассказанные волонтером и участником слета

 Читать далее...

Организация бесперебойной работы  

Бесперебойная работа ИТ-инфраструктуры в режиме 24/7 Как обеспечить ее в нынешних условиях?

Год назад ИТ-компания «Крок» провела исследование «Ключевые тренды сервисного рынка 2023». Результаты

 Читать далее...

Книжная полка  

Читайте и познавайте мир технологий!

Издательство «БХВ» продолжает радовать выпуском интересных и полезных, к тому же прекрасно

 Читать далее...

СУБД PostgreSQL  

СУБД Postgres Pro

Сертификация по новым требованиям ФСТЭК и роль администратора без доступа к данным

 Читать далее...

Критическая инфраструктура  

КИИ для оператора связи. Готовы ли компании к повышению уровня кибербезопасности?

Похоже, что провайдеры и операторы связи начали забывать о требованиях законодательства

 Читать далее...

Архитектура ПО  

Архитектурные метрики. Качество архитектуры и способность системы к эволюционированию

Обычно соответствие программного продукта требованиям мы проверяем через скоуп вполне себе понятных

 Читать далее...

Как хорошо вы это знаете  

Что вам известно о разработках компании ARinteg?

Компания ARinteg (ООО «АРинтег») – системный интегратор на российском рынке ИБ –

 Читать далее...

Графические редакторы  

Рисование абстрактных гор в стиле Paper Cut

Векторный графический редактор Inkscape – яркий представитель той прослойки open source, с

 Читать далее...

День сисадмина  

Учите матчасть! Или как стать системным администратором

Лето – время не только отпусков, но и хорошая возможность определиться с профессией

 Читать далее...

День сисадмина  

Живой айтишник – это всегда движение. Остановка смерти подобна

Наши авторы рассказывают о своем опыте и дают советы начинающим системным администраторам.

 Читать далее...

Виртуализация  

Рынок решений для виртуализации

По данным «Обзора российского рынка инфраструктурного ПО и перспектив его развития», сделанного

 Читать далее...

Книжная полка  

Как стать креативным и востребованным

Издательский дом «Питер» предлагает новинки компьютерной литературы, а также книги по бизнесу

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 6403
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 7109
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 4388
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 3085
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 3880
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 3895
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 6384
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 3231
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 3526
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 7358
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 10721
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 12443
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 14092
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 9191
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 7140
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 5444
Комментарии: 3
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 4681
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 3494
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 3209
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 3448
Комментарии: 0
Рецензия на книгу «MongoDB в действии»

 Читать далее...

02.12.2013г.
Просмотров: 3089
Комментарии: 0
Не думай о минутах свысока

 Читать далее...

Друзья сайта  

 Dependency Inversion Principle. Принцип инверсии зависимостей в разработке

Архив номеров / 2024 / Выпуск №5 (258) / Dependency Inversion Principle. Принцип инверсии зависимостей в разработке

Рубрика: Разработка /  Принципы проектирования


 ВИЗИТКА 




Ольга Федорова,
технический лидер «Альфа банка»

 

Dependency Inversion Principle
Принцип инверсии зависимостей в разработке

Мы подошли к последнему принципу проектирования приложений из серии SOLID – Dependency Inversion или «Инверсия зависимостей». 

 

Как обычно, начнем с оригинальной формулировки Роберта Мартина, которая звучит следующим образом: модули верхнего уровня не должны зависеть от модулей нижнего уровня. И те и другие должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Звучит прекрасно, но, как обычно, слишком теоретично. Давайте обратимся к конкретным примерам.

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

public class EmployeeManager {
   private PostgreSQLDatabase database;
   public EmployeeManager() {
       this.database = new PostgreSQLDatabase();
   }
   public void addEmployee(Employee employee) {
       database.add(employee);
   }
   public List<Employee> getAllEmployees() {
       return database.getAll();
   }
}

Итак, все работает, все счастливы. В один непрекрасный день вы сталкиваетесь с необходимостью перейти на другую базу данных, например, MongoDB. Да, здесь можно задать вопрос, как получилось так, что внезапно с SQL- решения надо уходить на NoSQL? Но, как показывает практика, в жизни может быть все что угодно.

Например, некоторые команды используют PostgreSQL для хранения данных в формате jsonb, а разработчики базы вполне себе такие решения позволяют, так что подобная смена стека еще далеко не самый странный вариант.

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

Здесь мы и вспоминаем оригинальную формулировку Dependency Inversion. Суть заключается в том, чтобы модули верхнего уровня (например, EmployeeManager) не зависели от модулей нижнего уровня (например, PostgreSQLDatabase), а зависели от абстракций (интерфейсов). Это позволяет избежать жестких зависимостей и сделать систему более гибкой и поддерживаемой. В том числе обеспечив возможность легко проворачивать подобные замены практически незаметно для всей системы.

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

public interface Database {
   void add(Employee employee);
   List<Employee> getAll();
}

Теперь изменим класс PostgreSQLDatabase – таким образом, чтобы он реализовывал интерфейс Database.

public class PostgreSQLDatabase implements Database {
   @Override
   public void add(Employee employee) {
       // Реализация добавления сотрудника в PostgreSQL
   }

   @Override
   public List<Employee> getAll() {
       // Реализация получения всех сотрудников из PostgreSQL
   }
}

Аналогично, создадим класс MongoDBDatabase, который также будет реализовывать интерфейс Database.

public class MongoDBDatabase implements Database {
   @Override
   public void add(Employee employee) {
       // Реализация добавления сотрудника в MongoDB
   }

   @Override
   public List<Employee> getAll() {
       // Реализация получения всех сотрудников из MongoDB
   }
}

Теперь изменим класс EmployeeManager, чтобы он зависел от интерфейса Database.

public class EmployeeManager {
   private Database database;

   public EmployeeManager(Database database) {
       this.database = database;
   }

   public void addEmployee(Employee employee) {
       database.add(employee);
   }

   public List<Employee> getAllEmployees() {
       return database.getAll();
   }
}

Такой подход позволяет легко менять реализацию базы данных, не изменяя код класса EmployeeManager. А это положительно влияет и на уровень абстракций, способствуя появлению интерфейсов в нужных местах. Что, в свою очередь, как мы обсудили в предыдущей части статьи, невероятно важно для гибкой архитектуры приложения.

И, кроме того, чем меньше у вас жестко связанной логики, тем проще писать unit-тесты, в них не приходится использовать сложные моки. Да, много библиотек вам предоставят достаточно инструментов для создания моков любой сложности, но гораздо проще тестировать изначально класс с минимумом зависимостей.

Из полезных, но, возможно, не слишком очевидных примеров применения данного принципа в жизни, могу вспомнить такую вещь, как возможность динамически добавлять функциональность с помощью wrapper’ов. Например, поверх интерфейса запихать кэширование (здесь можно вспомнить стартеры Spring или любого другого похожего фреймворка).

Более того, как и другие принципы SOLID, Dependency Inversion применим не только на уровне отдельных классов или модулей, но и на уровне всей системы. Например, благодаря ему мы можем собрать / пересобрать проект любой сложности, просто переиспользуя уже заранее написанные адаптеры или их аналоги. Единственным исключением станут разве что классы-конфигурации.

Попробую продемонстрировать эту мысль на более жизненной ситуации. Допустим, пользователь изменил в банке свои настройки (вместо информирования по смс, захотел по email). Если инверсия зависимостей была реализована на системном уровне, то мы без особого труда можем собрать сервис из отдельных модулей. Переиспользуем всю ту же бизнес-логику, только на выходе сообщение будет отдельным модулем конвертироваться в письмо (а не в смску) и использоваться соответственно будет другая интеграция. В противном же случае, если все прибито гвоздями, скорее всего эта завязка на смс проходит красной нитью, а значит, перестраивать систему будет больно и долго.

В целом, на этом статью об инверсии зависимостей можно было бы заканчивать, если не одно но: DI – это не только Dependency Inversion, но еще и Dependency Injection. Если вы работаете на JVM- стеке, то с таким паттерном точно сталкивались не раз, это неотъемлемая часть экосистемы Spring. А заодно и прекрасный пример того, как, зачастую, в мире разработки не следуют собственному же принципу о понятном и удобном нейминге.

Dependency Inversion – это про разделение логики и внедрение абстракций. Dependency Injection – это про внедрение зависимостей, в рамках так называемого IoC (Inversion of Control). Основное отличие заключается в том, что DI, который (Dependency Injection) – это про контроль над зависимостями. Контроль, который можно осуществлять разными способами и не всегда вручную. Данную ответственность можно легко делегировать фреймворку. Мы еще вернемся к этой теме в будущих статьях.

А теперь предлагаю подвести итоги нашего цикла SOLID. Главное, что я хочу подчеркнуть: это в первую очередь не теоретическая аббревиатура, а системный подход достаточно высокого уровня абстракции. Каждый принцип логично дополняет другой и, несмотря на то, что любое архитектурное решение – это компромисс, использование SOLID определенно даст ряд преимуществ вашей разработке.


Ключевые слова: SOLID, DIP, Dependency Inversion Principle, Dependency Injection, Роберт Мартин 


Подпишитесь на журнал

Комментарии отсутствуют

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

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru