Инверсия зависимостей, хорошо примененная, дает гибкость и стабильность на уровне всей архитектуры вашего приложения. Это позволит вашему приложению развиваться более безопасно и стабильно.
Традиционная многоуровневая архитектура
Традиционно интерфейс многоуровневой архитектуры зависел от бизнес-уровня, а это, в свою очередь, зависело от уровня доступа к данным.
http://xurxodev.com/content/images/2016/02/Traditional-Layered.png
Вы должны понимать слой, пакет или библиотеку. Посмотрим, как будет выглядеть код.
У нас будет библиотека или пакет для уровня доступа к данным.
// DataAccessLayer.dll
public class ProductDAO {
}
И другая бизнес-логика уровня библиотеки или пакета, которая зависит от уровня доступа к данным.
// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO {
private ProductDAO productDAO;
}
Многоуровневая архитектура с инверсией зависимостей
Инверсия зависимости указывает на следующее:
Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Что такое модули высокого уровня и низкого уровня? Мышление модулей, таких как библиотеки или пакеты, высокоуровневым модулем будут те, которые традиционно имеют зависимости и низкоуровневые, от которых они зависят.
Другими словами, высокий уровень модуля - это место, где вызывается действие, и низкий уровень, где оно выполняется.
Разумный вывод, который следует сделать из этого принципа, заключается в том, что между конкрециями не должно быть никакой зависимости, но должна быть зависимость от абстракции. Но в соответствии с подходом, который мы используем, мы можем неправильно использовать зависимость от инвестиций, но это абстракция.
Представьте, что мы адаптируем наш код следующим образом:
У нас будет библиотека или пакет для уровня доступа к данным, который определяет абстракцию.
// DataAccessLayer.dll
public interface IProductDAO
public class ProductDAO : IProductDAO{
}
И другая бизнес-логика уровня библиотеки или пакета, которая зависит от уровня доступа к данным.
// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO {
private IProductDAO productDAO;
}
Хотя мы зависим от абстракции, зависимость между бизнесом и доступом к данным остается неизменной.
http://xurxodev.com/content/images/2016/02/Traditional-Layered.png
Чтобы получить инверсию зависимостей, интерфейс персистентности должен быть определен в модуле или пакете, где эта логика или домен высокого уровня, а не в модуле низкого уровня.
Сначала определите, что такое уровень домена, и абстракция его связи определяется постоянством.
// Domain.dll
public interface IProductRepository;
using DataAccessLayer;
public class ProductBO {
private IProductRepository productRepository;
}
После того как постоянный слой зависит от домена, теперь можно инвертировать, если определена зависимость.
// Persistence.dll
public class ProductDAO : IProductRepository{
}
http://xurxodev.com/content/images/2016/02/Dependency-Inversion-Layers.png
Углубление принципа
Важно хорошо усвоить концепцию, углубляя цель и выгоды. Если мы останемся в механике и изучим типичный репозиторий, мы не сможем определить, где мы можем применить принцип зависимости.
Но почему мы инвертируем зависимость? Какова основная цель помимо конкретных примеров?
Обычно позволяет наиболее стабильным вещам, не зависящим от менее стабильных, меняться чаще.
Для типа персистентности легче изменить либо базу данных, либо технологию для доступа к той же базе данных, чем логика домена или действия, предназначенные для связи с постоянством. Из-за этого зависимость меняется на противоположную, потому что легче изменить постоянство, если это изменение произойдет. Таким образом, нам не придется менять домен. Доменный слой является наиболее стабильным из всех, поэтому он не должен зависеть ни от чего.
Но есть не только этот пример хранилища. Существует много сценариев, в которых применяется этот принцип, и существуют архитектуры, основанные на этом принципе.
Архитектура
Существуют архитектуры, в которых инверсия зависимостей является ключом к ее определению. Во всех доменах это самое важное, и именно абстракции будут указывать протокол связи между доменом и остальными пакетами или библиотеками.
Чистая архитектура
В Чистая архитектура домен расположен в центре, и если вы посмотрите в направлении стрелок, указывающих зависимость, станет ясно, какие слои являются наиболее важными и стабильными. Наружные слои считаются нестабильными инструментами, поэтому избегайте их зависимости.
Шестиугольная архитектура
То же самое происходит с гексагональной архитектурой, где домен также расположен в центральной части, а порты являются абстракциями связи от внешнего мира домино. Здесь снова очевидно, что домен является наиболее устойчивым, а традиционная зависимость инвертирована.