Найти тему
47 подписчиков

Dependency Injection


Один из двух знаменитых DI. Не путать с Dependency Inversion из SOLID.

Dependency Injection (или внедрение зависимостей) — это подход к проектировке классов, в котором зависимости объекту даются внешней сущностью.

Многие по неизвестной мне причине связывают всё в куче, и что DI без Composition Root или DI Containers не существует. Хотя изначально это вообще про другое и другие проблемы решает. Тут проще привести несколько примеров кода.

Примеры нарушения DI:

public class Foo
{
private Bar _Bar = new Bar();
}

public class Foo
{
private Bar _Bar = Bar.Instance;
}

Примеры кода по DI:

public class Foo
{
private IBar _bar;

public Foo(IBar bar)
{
_bar = bar;
}
}

public class Foo : MonoBehaviour
{
[SerializeField] private AbstractBar _bar;
}

Тут может возникнуть у кого-то короткое замыкание. Как это [SerializeField] DI? А где Zenject? DI — это вообще концепция проверяемая и соблюдаемая в рамках класса. Это просто внешнее внедрение зависимости. Абстрактный класс и сериализованное поле позволяет нам сделать такое внешнее внедрение. Позволяет подсунуть туда мок объект, написать юнит тест и так далее. Просто у нас в качестве места, где мы внедряем наши зависимости используются конфиги (префабы) и это опять-так не code-first подход, а config-first.

Неудобство в Unity вводить DI через [SerializeField] в том, что юнити не умеет в SerializeField с интерфейсами и так получится только с абстрактными классами. И у этого есть логика, так как интерфейс нельзя сериализовать. Хотя к этой концепции у меня есть вопросы. Так как если есть конкретный инстанс объекта и конкретная реализация на уровне сборки или на уровне рантайма, которая испоьзуется в качестве имплементации интерфейса, то в чём проблема её сериализовать?

В целом ничто не мешает написать свой Composition Root или Dependency Injection Container, но есть удобные и готовые типа того же Zenject.

#термин
1 минута