Re[8]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 13.01.21 23:01
Оценка: +2
M>>>покажите пример, а мы посмотрим.
МП>>это не вполне легально по нынешним временам
МП>>но всё что я сам писал было без DI кроме мест в проектах где это было уже мне навязано через легаси

M>Не обязательно весь проект, просто пример как вы пишите классы решающие бизнес задачи, как передаете в них зависимости?


это всё решается грамотной иерархией сборок по слоям
есть уровень простейших объектов, data-object
сборки этого уровня никуда не ссылаются
есть уровень helper'ов, DAL и технической логики
сборки этого уровня могут ссылаться на сборки предыдущего уровня
и есть уровень содержательной бизнес логики, который уже может ссылаться на все предыдущие уровни, но по необходимому минимуму

циклических зависимостей тут в идеале вообще возникнуть не должно
но если возникают, вы же знаете как их решать?
(создание интерфейса нужной функциональности, вынос его в нижестоящий слой, а реализация может быть и в вышестоящем слое)


M>В каком месте приложения конструируете зависимости?


я их не конструирую, а избегаю
но речь я так понял о конструирования высокоуровневых объектов?
ну так там и конструирую где они нужны
либо если это кеш — при инициализации или обновлении кэша

    var a = new A(12, "6")
    {
        Field1 = new B(),
        Field2 = C.Instance;
    }



M>Зачем делаете это руками если есть контейнер который справится с этим сам и без проблем?


с чем это он справится сам?
он явные аргументы конструирования перенесёт в отдельное место (совершенно неявное)
чем создаст шов в восприятии
а то и вообще в конфиг файл

но суть работы по инициализации всё равно нужно будет делать
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Re[7]: Бизнес приложение
От: Министр Промышленности СССР  
Дата: 13.01.21 23:05
Оценка: 6 (1) -1
M>>Нормальное DI как раз и работает через конструкторы. Как вообще можно писать бизнес приложения без DI ума не приложу, покажите пример, а мы посмотрим.

S>Для банковского или шире, финансового ПО, где требования меняются часто, может и критично. Для любых других приложений может и не надо.


в таком описании становится понятно, что оставление DI в проекте есть ни что иное как технических долг...
просто по завершении работ по быстро обновимшимся требованиям забили болт на реформирование структуры классов по сборкам
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Re[6]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 13.01.21 23:15
Оценка: +3
МП>>>>нормальные обычные конструкторы,
МП>>>>ну либо статические конструкторы,

МП>>вопрос был в разрезе целесообразности использования DI


T>до этого момента, когда ты спрашивал про DI-фреймворки, всё было правильно,

T>а сейчас съехал в сторону
T>передача зависимостей в конструкторе это такое же средство реализации DI

да, но без шва
всё ясно понятно как именно откуда берётся в том же месте где ты это раскопал
а не в другом отдельном
а то и вообще не найдёшь поиском кто конструктор вызывает

зачем ещё и тянуть в проект дополнительные DI фреймворки при этом...
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Re[4]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 13.01.21 23:22
Оценка:
vsb>У меня есть один объект. Например назовём его UserDao. И есть второй объект. Назовём его AuthService. Для AuthService нужна ссылка на UserDao. Каким образом он эту ссылку получит?

  цитирование
vsb>Сконструировать он его не может. Во-первых я просто не хочу, чтобы в системе было много UserDao, например там может быть кеширование или ещё что угодно. Во-вторых для создания UserDao мне нужно соединение к БД, возможно ещё что-то. Передавать всю эту кучу скопом в AuthService (и в любой другой объект, которому нужен UserDao) это маразм.
vsb>Если я правильно понял про "статические конструкторы", ты предлагаешь сделать что-то вроде UserDao.getInstance(). То бишь реестр объектов, причём плохой и неудобный реестр. Так делать можно, но при этом возникает уйма проблем:

vsb>1. Такой код сложно тестировать. Если я хочу, чтобы AuthService принимал фейковый UserDao, мне нужно вызывать в тесте UserDao.setInstance(testUserDao). При этом мне в принципе нужно помнить при тестировании AuthService про все его зависимости. А ещё надо не забыть по окончании работы теста убрать все эти тестовые переменные, иначе это может поломать другие тесты. Ещё возникают вопросы с многопоточностью. В общем проблем много. Решать как-то их, наверное, можно, но неудобно.


vsb>2. Такой код сложно переиспользовать. Если мне всё же понадобится в реальном коде другой UserDao конкретно для AuthService, то это будет просто невозможно сделать в рамках данного подхода.


vsb>3. Непонятно, собственно, к чему мы пришли в итоге. У нас есть вызов UserDao.getInstance(), который возвращает что-то. Что он возвращает? Неизвестно. Кто-то там ему сделал setInstance раньше, его и возвращает. Какая разница с DI в плане понимания работы кода? Никакой разницы.


vsb>4. Сложно понять, от чего зависит AuthService. Нужно внимательно читать его код, изучать список импортов. В случае с DI ты просто смотришь на параметры конструктора и всё как на ладони. Это бывает удобно.


    var userDao = DatabaseHelper.GetUserDao();

    var authService = new AuthService(userDao);


https://www.youtube.com/watch?v=-Jh0EN1De4Q
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Отредактировано 13.01.2021 23:23 Министр Промышленности из Minecraft'а . Предыдущая версия .
Re[7]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 13.01.21 23:37
Оценка: 1 (1) +4
AK>>При чём здесь строковые константы? Я не понимаю.
AK>>Можете дать какой-нибудь пример?

S>Я похоже переврал, что конкретно можно делать только resolve по имени, что ослабляло бы типизацию.

S>Но вот дискуссия на SO, которую я считаю релевантной -- https://stackoverflow.com/a/4988337/241446
S>В частности вот это:
S>

S>Errors are pushed to run-time. If you configure your Guice module incorrectly (circular reference, bad binding, ...) most of the errors are not uncovered during compile-time. Instead, the errors are exposed when the program is actually run.

S>Т.е. из-за DI некоторые ошибки будут заметны на стадии исполнения, нежели при компиляции. Вероятно это ТС имел в виду.

я имел в виду банальную задачу:
есть фарш исторического кода, который неправильно работает
ты разбираешься в какой момент всё идёт неправильно, отслеживаешь объекты где используются, откуда получаются
и вот на 7м-13м уровне вложенности вызывов ты понимаешь, тебе надо срочно знать откуда берётся значение вот в этом объекте
прыг F12 (у меня это решарперовский GoToDefinition)
ага есть конструктор прыг Alt+F7 (у меня это FindUsages) а хрен тебе — он вызывается неявно в рамках DI
и хорошо если ты это ещё знаешь
а то вполне можешь подумать "ага, значит инициализируется не здесь", и пойти исследовать фарш дальше вглубь!
и это убийственно
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Отредактировано 14.01.2021 12:12 Министр Промышленности из Minecraft'а . Предыдущая версия .
Re[2]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 13.01.21 23:43
Оценка:
МП>>кто-то может популярно расписать преимущества либо природу явления популярности?
МП>>(часть плюсов знаю и гипотезы-то я имею, но мнение всё равно такое)

САД>инструмент должен решать задачу.

САД>DI не везде нужен, особенно в вин-формах, имхо.

да, спасибо, я хотел видимо именно это подтверждение


САД>но вот тебе пример из недавнего с нашего проекта.

САД>есть сервис, пусть будет MyService, который делает достаточно долгий запрос за статическими данными.
САД>есть интерфейс, понятное дело, IMyService.
САД>этот сервис используется в большом количестве мест проекта. через интеферйс, понятное дело, не напрямую создавая инстанс.
САД>запустив нагрузочное тестирование, мы поняли, что мы упираемся в производительность этого сервиса, и если бы мы закешировали данные, получили бы приличный прирост производительности.
САД>дальше, мы создали над MyService обычный декоратор, аля MyServiceWithCache, который так же реализует IMyService интерфейс. всё что там нужно было, поменять регистрацию в DI в одном месте.
САД>дальше, везде подхватилась новая реализаций, реализация нашего декоратора. приложение взлетело.

ок, хотя можно было это решить и без DI фреймворка в проекте
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Re: О пользе Dependency Injection
От: Somescout  
Дата: 13.01.21 23:55
Оценка: 6 (1) +3
Здравствуйте, Министр Промышленности, Вы писали:

МП>кто-то может популярно расписать преимущества либо природу явления популярности?

МП>(часть плюсов знаю и гипотезы-то я имею, но мнение всё равно такое)

Банальная лень. Допустим мне в глубинах компонентов понадобился доступ к базе (оставим пока в сторонке вопросы архитектуры), как мне получить контекст базы без DI? Ок, я могу создать её просто конструктором, но нужна строка подключения. Которая задана в конфигурации. Которая взята из файла/реестра/сервера. Следовательно чтобы просто создать контекст, мне нужно сначала прочитать конфигурацию, получить из неё строку подключения, а затем уже подключиться к базе. Выглядит геморройно (а уж сколько веселья при рефракторинге, если потребуется поменять способ построения контекста).

А можно вместо этого просто прописать в конструкторе требование к наличию этого объекта — и всё, DI автоматически создаст его без каких-либо телодвижений.

И это даже не касаясь вопроса о scope'ах — какой контекст мне нужен transient или scoped? И как в принципе создать второй без DI?

В общем узнать в своё время о существовании DI было крайне приятно.
ARI ARI ARI... Arrivederci!
Re[5]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 00:01
Оценка: -1
Здравствуйте, Министр Промышленности, Вы писали:

МП>
МП>    var userDao = DatabaseHelper.GetUserDao();

МП>    var authService = new AuthService(userDao);
МП>


Это, вобще-то, и есть dependency injection. Только вы это вручную делаете, и фактически переносите проблемы на уровень выше: теперь вызывающий код в обязательном порядке должен иметь ссылку на базу (напрямую или через DatabaseHelper), и сам должен получить userDao — что поменялось в итоге от такой перетасовки? Ничего — все проблемы ровно на том же месте.
ARI ARI ARI... Arrivederci!
Re[2]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 14.01.21 00:21
Оценка:
МП>>Они затрудняют распутывание кода,
МП>>понижают гибкость автоматического рефакторинга (в частности ReSharper-ом)
МП>>и это не перекрывается гибкостью подстановки mock-объектов

IT>Распутывание кода и рефакторинг в основном затрудняет тотальное использование интерфейсов, которые так любят использовать в DI фреймворках.


ну это захламляет, да, но достаточно на методе сделать "Find Usages advanced"
а вот неявное вызывание конструктора реально сбивает с толку


IT>В результате имеем — неумеха с золотым молотком пишет со всем старанием бизнес логику в стиле универсального всемогутера.

IT>Какждый раз когда я вижу в проекте использование DI фреймворков и IoC контейнеров у меня возникакет именно такое впечатление.

да, такое же впечатление
только я даже не уверен что авторы старали всемогутор, а не штамповали мантры
Властитель слабый и лукавый,
Плешивый щёголь, враг труда,
Нечаянно пригретый славой,
Над нами царствовал тогда.... (А.С. Пушкин ? )
Re[5]: О пользе Dependency Injection
От: vsb Казахстан  
Дата: 14.01.21 04:54
Оценка: 3 (1) +4 -1
Здравствуйте, Министр Промышленности, Вы писали:

МП>
МП>    var userDao = DatabaseHelper.GetUserDao();

МП>    var authService = new AuthService(userDao);
МП>


Поздравляю, вы только что показали пример использования паттерна Dependency Injection.

А фреймворк даст возможность не писать эти две строчки. Которые разрастутся в сотни и тысячи строк однотипного скучного кода в реальном приложении с десятками-сотнями объектов. Если писать это вручную, нужно будет самому продумывать порядок создания объектов, причём этот порядок с развитием приложения может меняться. В этом нет ничего сложного, особенно если пользоваться setter-ами, а не конструкторами (тогда можно не задумываться про порядок создания объектов и круговые зависимости), но этот код легко генерируется, поэтому и пользуются фреймворками. Но вы можете не пользоваться и писать всё руками, DI от этого не исчезнет.
Отредактировано 14.01.2021 6:04 vsb . Предыдущая версия . Еще …
Отредактировано 14.01.2021 6:03 vsb . Предыдущая версия .
Re[2]: О пользе Dependency Injection
От: TG  
Дата: 14.01.21 06:04
Оценка:
Здравствуйте, Somescout, Вы писали:

МП>>кто-то может популярно расписать преимущества либо природу явления популярности?

МП>>(часть плюсов знаю и гипотезы-то я имею, но мнение всё равно такое)

S>Банальная лень. Допустим мне в глубинах компонентов понадобился доступ к базе (оставим пока в сторонке вопросы архитектуры), как мне получить контекст базы без DI?


А почему оставим-то? Это очень интересный вопрос.
Или получается, что DI полезен только вот в таких "хитрых" архитектурах?
А если что-то пилить с нуля, то можно и обойтись без DI?
Re[2]: О пользе Dependency Injection
От: Poopy Joe Бельгия  
Дата: 14.01.21 06:36
Оценка: 72 (1) +7 :)
Здравствуйте, Somescout, Вы писали:

S>Банальная лень. Допустим мне в глубинах компонентов понадобился доступ к базе (оставим пока в сторонке вопросы архитектуры), как мне получить контекст базы без DI?

Отличное описание. DI это костыль, когда лень думать об архитектуре, но не лень потом все это разгребать и отлаживать.
Re[3]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 06:56
Оценка:
Здравствуйте, TG, Вы писали:

S>>Банальная лень. Допустим мне в глубинах компонентов понадобился доступ к базе (оставим пока в сторонке вопросы архитектуры), как мне получить контекст базы без DI?


TG>А почему оставим-то? Это очень интересный вопрос.

Потому что пример абстрактный.

TG>Или получается, что DI полезен только вот в таких "хитрых" архитектурах?

Что "хитрого" в такой архитектуре?

TG>А если что-то пилить с нуля, то можно и обойтись без DI?

Обойтись можно без чего угодно, вопрос в удобстве. Если хотите, например, можете прокидывать базу (или сервис доступа к данным, или любую другую службу) сверху вниз, или конструировать на месте, или использовать статические репозитарии — всё можно. Только нафига усложнять себе же жизнь?
ARI ARI ARI... Arrivederci!
Re[3]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 06:59
Оценка: +1
Здравствуйте, Poopy Joe, Вы писали:

S>>Банальная лень. Допустим мне в глубинах компонентов понадобился доступ к базе (оставим пока в сторонке вопросы архитектуры), как мне получить контекст базы без DI?

PJ>Отличное описание. DI это костыль, когда лень думать об архитектуре, но не лень потом все это разгребать и отлаживать.
Да считайте как угодно. Я успел прочитать несколько ваших комментариев — не вижу смысла спорить с троллем.
ARI ARI ARI... Arrivederci!
Re[4]: О пользе Dependency Injection
От: TG  
Дата: 14.01.21 07:20
Оценка: +1
Здравствуйте, Somescout, Вы писали:

TG>>А почему оставим-то? Это очень интересный вопрос.

S>Потому что пример абстрактный.
Обсуждать абстрактные примеры не интересно.
Если люди видят пользу от DI, то в чем проблема привести конкретный пример, где он давал бы видимые преимущества и привносил не очень много проблем.

TG>>Или получается, что DI полезен только вот в таких "хитрых" архитектурах?

S>Что "хитрого" в такой архитектуре?
Фраза "Допустим мне в глубинах компонентов понадобился доступ к базе" намекает, что при проектировании несколько подзабыли принципы SOLID, разделение на слои и т.д. И если сделано это осознанно, то было бы опять же интересно посмотреть на конкретный кейс.
Re[5]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 07:35
Оценка:
Здравствуйте, TG, Вы писали:

TG>Фраза "Допустим мне в глубинах компонентов понадобился доступ к базе" намекает, что при проектировании несколько подзабыли принципы SOLID, разделение на слои и т.д.

А можете объяснить — в чём именно вы увидели нарушение SOLID?

TG>И если сделано это осознанно, то было бы опять же интересно посмотреть на конкретный кейс.

Ок, простой пример: на веб странице компонент должен выводить имя текущего пользователя. Он должен его откуда-то получить: либо вы при рендеринге каждой страницы прокидываете эту информацию ему вручную, либо компонент так или иначе (через DI, репозиторий, синглтон) получает эту информацию сам.
ARI ARI ARI... Arrivederci!
Re[3]: О пользе Dependency Injection
От: СвободуАнжелеДевис СССР  
Дата: 14.01.21 08:09
Оценка: +1
МП>ок, хотя можно было это решить и без DI фреймворка в проекте

да всё что угодно можно сделать без DI. вопрос в проекте.
его размере, тестировании.
у нас есть солюшен на 30+ проджектов. авто-регистрация зависимостей очень облегчает жизнь
Нет времени на раскачку!
Re: О пользе Dependency Injection
От: elmal  
Дата: 14.01.21 08:12
Оценка: +2
Здравствуйте, Министр Промышленности, Вы писали:

МП>Они затрудняют распутывание кода,

Абсолютно не затрудняют на практике. Нет, возможно и можно что то там наворотить при желании, но это нужно специально стараться.

МП>понижают гибкость автоматического рефакторинга (в частности ReSharper-ом)

Не понижают, прекрасно все рефакторится.

У них основной недостаток — это завязанность на DI фреймворк или библиотеки, соответственно если ты хочешь часть кода на одном проекте, использовать в другом проекте, в котором другой DI фреймворк или такого нет вовсе — будут некоторые проблемы, придется пошаманить. Плюс недостаток — это некоторое незначительное увеличение размеров кода, без DI будет короче, если забить на тесты.

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

Собственно я живу без DI уже более 5 лет. Но у меня не энтерпрайз, могу позволить, плюс не исключено что придется переписывать на язык типа Rust некоторые части, плюс у меня язык специфический, плюс части кода потом уходят в библиотеки и используются в других проектах. При этом иногда жалел, что не стал тяжелую артиллерию подключать — через определенное количество времени уже понадобились навороченные фичи, и пришлось в результате некоторые лисапеды городить.
Re[6]: О пользе Dependency Injection
От: barn_czn  
Дата: 14.01.21 08:14
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>Здравствуйте, Министр Промышленности, Вы писали:


МП>>а реальная необходимость бывает редко и всего в 2-3 местах системы


AA>Очевидно, что DI это реализация принципа инверсии зависимостей.

AA>Если у вас возникают циклические зависимости между компонентами, то вам не избежать DI.

Конкретный пример пож-та, чтобы спор был не абстрактным.
Re: О пользе Dependency Injection
От: barn_czn  
Дата: 14.01.21 08:16
Оценка:
МП>понижают гибкость автоматического рефакторинга (в частности ReSharper-ом)

Совершенно согласен. Но еще больше бесит привязанность к конкретным DI фреймворкам.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.