Comments 5
Спасибо за перевод.
Дино только почему то не рассмотрел один аспект DI.
На практике классы (в особенности сервисы) зависят от более чем одного класса, что приводит к тому, что конструктор объекта содержит много параметров. Это снижает удобство пользования классом.
Можно, конечно, вместо параметров конструктора сделать свойства объекта, но это черевато тем, что будут забывать заполнять эти свойства перед использованием объекта, не говоря о том, что эти свойства будут смешиваться с «рабочими» свойствами объекта.
Проблему количества параметров в конструкторе обычно решают за счёт более умных библиотек DI, которые через рефлексию умеют разбирать конструктор и для каждого из параметров опять через себя создавать/находить экземпляры классов:
Но, как мы понимаем, это повышает стоимость конструирования одного такого класса. На сколько? Если честно, я не смотрел код работы современных DI библиотек, но единственным способом сделать скорость приличной можно только если код для создания подобных классов конструировать сразу в MSIL «налету» и кэшировать полученный кусок CLR-кода для повтороного использования (т.е. для повтороного создания объекта того же типа).
К тому же, не всегда все методы класса используют все те объекты, которые нужно передавать в конструктор.
В общем, это может быть для кого «preemptive optimization», но не лишним будет об этом помнить.
И ещё о чём не сказал Дино (об этом, вроде, Фаулер писал): главный плюс DI в том, что объект описанный подобным образом можно отдавать «другим» разработчикам — даже если у них не настроен DI (не зарегистрированны типы) можно будет создать экземпляр объекта самим. А вот с ServiceLocator нотацией будет сложнее — нужно будет ещё и инфрастуктуру для ServiceLocator настраивать.
В общем, ничего плохого в ServiceLocator нет, но рекомендуется на ServiceLocator писать только то, что будет использоваться внутри системы — это проще и лаконичнее. А DI вариант хорош прежде всего для тех, кто пишет библиотеки для сторонних приложений.
Дино только почему то не рассмотрел один аспект DI.
На практике классы (в особенности сервисы) зависят от более чем одного класса, что приводит к тому, что конструктор объекта содержит много параметров. Это снижает удобство пользования классом.
public class MyClass
{
public MyClass (IRepository rep, IService service, ILogger logger, ISettings settings, ICache cache, ITrace trace)
...
}
Можно, конечно, вместо параметров конструктора сделать свойства объекта, но это черевато тем, что будут забывать заполнять эти свойства перед использованием объекта, не говоря о том, что эти свойства будут смешиваться с «рабочими» свойствами объекта.
Проблему количества параметров в конструкторе обычно решают за счёт более умных библиотек DI, которые через рефлексию умеют разбирать конструктор и для каждого из параметров опять через себя создавать/находить экземпляры классов:
// регистрация - один раз на запуск приложения
builder.RegisterType<MyRepository> ().As<IRepository> ();
builder.RegisterType<MyService> ().As<IService> ();
builder.RegisterType<MyLogger> ().As<ILogger> ();
builder.RegisterType<MySettings> ().As<ISettings> ();
builder.RegisterType<MyCache> ().As<ICache> ();
builder.RegisterType<MyTrace> ().As<ITrace> ();
builder.RegisterType<MyClass> ();
// получение экземпляра класса
var obj = resolver.Resolve<MyClass> ();
Но, как мы понимаем, это повышает стоимость конструирования одного такого класса. На сколько? Если честно, я не смотрел код работы современных DI библиотек, но единственным способом сделать скорость приличной можно только если код для создания подобных классов конструировать сразу в MSIL «налету» и кэшировать полученный кусок CLR-кода для повтороного использования (т.е. для повтороного создания объекта того же типа).
К тому же, не всегда все методы класса используют все те объекты, которые нужно передавать в конструктор.
В общем, это может быть для кого «preemptive optimization», но не лишним будет об этом помнить.
И ещё о чём не сказал Дино (об этом, вроде, Фаулер писал): главный плюс DI в том, что объект описанный подобным образом можно отдавать «другим» разработчикам — даже если у них не настроен DI (не зарегистрированны типы) можно будет создать экземпляр объекта самим. А вот с ServiceLocator нотацией будет сложнее — нужно будет ещё и инфрастуктуру для ServiceLocator настраивать.
В общем, ничего плохого в ServiceLocator нет, но рекомендуется на ServiceLocator писать только то, что будет использоваться внутри системы — это проще и лаконичнее. А DI вариант хорош прежде всего для тех, кто пишет библиотеки для сторонних приложений.
+1
Хорошее и правильное дополнение. Спасибо.
0
На практике, если класс имеет слишком много зависимостей — это bad design. Чаще всего это свойственно каким-то божественным объектам, нарушающим SRP. В этому случае имеет смысл подумать над пересмотром архитектуры системы.
0
Автор закинул это в гугл-переводчик и решил выложить на хабр, ОК
0
Sign up to leave a comment.
ASP.NET MVC: Преобразование или инъекции? Вот в чем вопрос