Re[2]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 08:25
Оценка:
Здравствуйте, IT, Вы писали:

IT>А раз так, то как же можно получить информацию о кастомере без DI фреймворка и пары IoC контейнеров? Никак не можно.

Кстати, а если действительно никак не можно — например информация о кастомере разбросана по нескольким сервисам?
ARI ARI ARI... Arrivederci!
Re[7]: О пользе Dependency Injection
От: varenikAA  
Дата: 14.01.21 09:04
Оценка:
Здравствуйте, barn_czn, Вы писали:


_>Конкретный пример пож-та, чтобы спор был не абстрактным.


Я аообще не понял о чем собственно спор, вот яркий пример и заодно определение

https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8#%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80_%D0%BA%D0%BE%D0%B4%D0%B0_%D0%BD%D0%B0_Java

Может ТС что-то другое имел ввиду.

Бесить не должно, т.к. это архитектура как бы, на старте выбрана. уже никуда, только переписывать с нуля (правило 3-х версий )
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 14.01.2021 9:04 Разраб . Предыдущая версия .
Re[7]: О пользе Dependency Injection
От: varenikAA  
Дата: 14.01.21 09:21
Оценка: +1
Здравствуйте, barn_czn, Вы писали:

_>Конкретный пример пож-та, чтобы спор был не абстрактным.


И да, еще больше примеров в книжке "Роберт Мартин — Чистая архитектура — 2018", после ее прочтения сомнения отпадают.
Так или иначе зависимости будут, использовать для этого ФВ или делать свой велосипед это уже от архитектора зависит.
Хотя да, большинство проектов на C# это монолиты.
В корэ использую стандартный DI очень доволен. можно в любом месте приложения получить ссылку на любой объект не задумываясь.

https://github.com/altbodhi/HostAppExample/blob/master/Program.cs

Безобразно, но единообразно.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[9]: О пользе Dependency Injection
От: microuser  
Дата: 14.01.21 09:27
Оценка: +3
Здравствуйте, Министр Промышленности, Вы писали:

M>>>>покажите пример, а мы посмотрим.

МП>>>это не вполне легально по нынешним временам
МП>>>но всё что я сам писал было без DI кроме мест в проектах где это было уже мне навязано через легаси

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


МП>это всё решается грамотной иерархией сборок по слоям

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

МП>циклических зависимостей тут в идеале вообще возникнуть не должно

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

Пока что вы описали чистую архитектуру, а я спрашивал не как вы организуете слои, а как передаете зависимости в конкретные классы.

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


МП>я их не конструирую, а избегаю

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

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



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


МП>с чем это он справится сам?

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

МП>но суть работы по инициализации всё равно нужно будет делать


Например есть у нас некий полезный класс у которого две зависимости:

class Service
{
    public Service(IDependency1 dependency1, IDependency2 dependency2)
    {
    }

    public void DoSomeWork()
    {
        //...
    }
}



Как вы предлагаете создавать экземпляр этого класса? Руками писать new Service(new Dependency1(...), new Dependency2(...)), при чем у каждой зависимости есть свой конструктор с другими зависимостями. А если потом в этой цепочке где то поменяется сигнатура конструктора — придется исправлять все места где он вызывается. Вопрос зачем такие сложности, если задачу создания объектов можно поручить фреймворку который сделает это все совершенно прозрачно?
Re[3]: О пользе Dependency Injection
От: microuser  
Дата: 14.01.21 09:40
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Здравствуйте, Somescout, Вы писали:


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

PJ>Отличное описание. DI это костыль, когда лень думать об архитектуре, но не лень потом все это разгребать и отлаживать.

Интересно было бы посмотреть на вашу архитектуру которая делает DI не нужным.
Re[10]: О пользе Dependency Injection
От: Министр Промышленности СССР  
Дата: 14.01.21 09:57
Оценка:
M>Пока что вы описали чистую архитектуру, а я спрашивал не как вы организуете слои, а как передаете зависимости в конкретные классы.
M>Например есть у нас некий полезный класс у которого две зависимости:

M>
M>class Service
M>{
M>    public Service(IDependency1 dependency1, IDependency2 dependency2)
M>    {
M>    }

M>    public void DoSomeWork()
M>    {
M>        //...
M>    }
M>}
M>



M>Как вы предлагаете создавать экземпляр этого класса? Руками писать new Service(new Dependency1(...), new Dependency2(...)), при чем у каждой зависимости есть свой конструктор с другими зависимостями.


ну в общем да, именно так и писать
если инициализация будет объемистой, то вынести в инициализирующий статический helper метод и везде использовать его


M>А если потом в этой цепочке где то поменяется сигнатура конструктора — придется исправлять все места где он вызывается. Вопрос зачем такие сложности, если задачу создания объектов можно поручить фреймворку который сделает это все совершенно прозрачно?


если поменятся сигнатура, то об этом напомнит даже не компилятор, Решарпер до компилирования, или даже просто IDE
и модификация окажется механической работой, не затрачивающей самый главный ресурс — моральные силы разрабочитка
Re[11]: О пользе Dependency Injection
От: microuser  
Дата: 14.01.21 10:20
Оценка:
Здравствуйте, Министр Промышленности, Вы писали:

M>>Пока что вы описали чистую архитектуру, а я спрашивал не как вы организуете слои, а как передаете зависимости в конкретные классы.

M>>Например есть у нас некий полезный класс у которого две зависимости:

M>>
M>>class Service
M>>{
M>>    public Service(IDependency1 dependency1, IDependency2 dependency2)
M>>    {
M>>    }

M>>    public void DoSomeWork()
M>>    {
M>>        //...
M>>    }
M>>}
M>>



M>>Как вы предлагаете создавать экземпляр этого класса? Руками писать new Service(new Dependency1(...), new Dependency2(...)), при чем у каждой зависимости есть свой конструктор с другими зависимостями.


МП>ну в общем да, именно так и писать

МП>если инициализация будет объемистой, то вынести в инициализирующий статический helper метод и везде использовать его


M>>А если потом в этой цепочке где то поменяется сигнатура конструктора — придется исправлять все места где он вызывается. Вопрос зачем такие сложности, если задачу создания объектов можно поручить фреймворку который сделает это все совершенно прозрачно?


МП>если поменятся сигнатура, то об этом напомнит даже не компилятор, Решарпер до компилирования, или даже просто IDE

МП>и модификация окажется механической работой, не затрачивающей самый главный ресурс — моральные силы разрабочитка

Лишняя работа, больше boilerplate кода, как следствие ниже читаемость, а плюсы то есть?
Re[6]: О пользе Dependency Injection
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.21 11:13
Оценка: 72 (1) +7 -1
Здравствуйте, Somescout, Вы писали:
TG>>И если сделано это осознанно, то было бы опять же интересно посмотреть на конкретный кейс.
S>Ок, простой пример: на веб странице компонент должен выводить имя текущего пользователя. Он должен его откуда-то получить: либо вы при рендеринге каждой страницы прокидываете эту информацию ему вручную, либо компонент так или иначе (через DI, репозиторий, синглтон) получает эту информацию сам.
Ну это же прекрасный пример. Через три-четыре релиза у нас в топ жалоб выезжает "ваше приложение нещадно тормозит", привлекается команда высокооплачиваемых экспертов, которые после трёх месяцев расчистки конюшен констатирует очевидное: "у вас там каждая кнопка в гуе считает, что ей нужно лазить в базу/сторонний сервис/ещё куда-то, в итоге для построения одного экрана открывается 27 коннектов к базе, и исполняется более трёхсот SQL-запросов. Из них треть дублируют друг друга, а половина, хоть и не совпадает, может быть покрыта одним из более широких запросов". Рекомендация экспертов: "чётко разделить фазы построения гуя, доставая данные из базы минимальным количеством запросов и передавая визуальным компонентам готовую viewModel".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 11:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ну это же прекрасный пример. Через три-четыре релиза у нас в топ жалоб выезжает "ваше приложение нещадно тормозит", привлекается команда высокооплачиваемых экспертов, которые после трёх месяцев расчистки конюшен констатирует очевидное: "у вас там каждая кнопка в гуе считает, что ей нужно лазить в базу/сторонний сервис/ещё куда-то, в итоге для построения одного экрана открывается 27 коннектов к базе, и исполняется более трёхсот SQL-запросов. Из них треть дублируют друг друга, а половина, хоть и не совпадает, может быть покрыта одним из более широких запросов". Рекомендация экспертов: "чётко разделить фазы построения гуя, доставая данные из базы минимальным количеством запросов и передавая визуальным компонентам готовую viewModel".


Согласен. Это отличный повод не использовать DI.
ARI ARI ARI... Arrivederci!
Re[4]: О пользе Dependency Injection
От: Poopy Joe Бельгия  
Дата: 14.01.21 11:22
Оценка:
Здравствуйте, microuser, Вы писали:

M>Интересно было бы посмотреть на вашу архитектуру которая делает DI не нужным.

По мне, так DI не просто не нужен, а только вредит. У кода выше из-за DI сразу несколько проблем, причем на ровном месте: требуется состояние, неявная параметризация функций, смешивание бизнес-логики и сторонних эффектов, неявная зависимость от внешнего поведения.
Серебряной пули тут нет и каждые случай "необходимости" DI решается по разному, но при этом оставляя бизнес-функции чистыми. В общем случае все сводится к тому или иному виду композиции, а функция в параметрах получает то, что в случаи DI запрашивает сама из внешних источников. В языках где есть частичное применение параметров для этого вообще ничего специального делать не надо, но в том же c# можно возвращать Func вместо результата. Для логгера можно использовать монаду, пример.
Re[7]: О пользе Dependency Injection
От: Somescout  
Дата: 14.01.21 11:25
Оценка: +2
Здравствуйте, Sinclair, Вы писали:

S>Ну это же прекрасный пример. Через три-четыре релиза у нас в топ жалоб выезжает "ваше приложение нещадно тормозит", привлекается команда высокооплачиваемых экспертов, которые после трёх месяцев расчистки конюшен констатирует очевидное: "у вас там каждая кнопка в гуе считает, что ей нужно лазить в базу/сторонний сервис/ещё куда-то, в итоге для построения одного экрана открывается 27 коннектов к базе, и исполняется более трёхсот SQL-запросов. Из них треть дублируют друг друга, а половина, хоть и не совпадает, может быть покрыта одним из более широких запросов". Рекомендация экспертов: "чётко разделить фазы построения гуя, доставая данные из базы минимальным количеством запросов и передавая визуальным компонентам готовую viewModel".


Добавлю ещё дополнительно: само собой я не в курсе необходимости кэширования данных, не знаю о том что нужно минимизировать количество коннектов, не в курсе что оптимизировать приложение (вопреки Кнуту) нужно с самого начала, а до простого примера нужно обязательно докопаться.

S>в итоге для построения одного экрана открывается 27 коннектов к базе, и исполняется более трёхсот SQL-запросов.

Про настройку времени жизни в DI и request-scope я так понимаю вы ни сном ни духом?
ARI ARI ARI... Arrivederci!
Отредактировано 14.01.2021 11:32 Somescout . Предыдущая версия .
Re[5]: О пользе Dependency Injection
От: microuser  
Дата: 14.01.21 13:17
Оценка: +1
Здравствуйте, Poopy Joe, Вы писали:

PJ>Здравствуйте, microuser, Вы писали:


M>>Интересно было бы посмотреть на вашу архитектуру которая делает DI не нужным.

PJ>По мне, так DI не просто не нужен, а только вредит. У кода выше из-за DI сразу несколько проблем, причем на ровном месте: требуется состояние, неявная параметризация функций, смешивание бизнес-логики и сторонних эффектов, неявная зависимость от внешнего поведения.
PJ>Серебряной пули тут нет и каждые случай "необходимости" DI решается по разному, но при этом оставляя бизнес-функции чистыми. В общем случае все сводится к тому или иному виду композиции, а функция в параметрах получает то, что в случаи DI запрашивает сама из внешних источников. В языках где есть частичное применение параметров для этого вообще ничего специального делать не надо, но в том же c# можно возвращать Func вместо результата. Для логгера можно использовать монаду, пример.

Не совсем понимаю связь между неявной параметризацией функций, смешиванием бизнес логики и зависимостей от внешнего поведения.
Все это вопросы архитектуры, а DI фреймворк лишь берет на себя ответственность за создание экземпляров объектов, работать он может в любой архитектуре.
Хотелось бы real life пример бизнес приложения, или хотя бы CRUD hello world без DI.
Re[8]: О пользе Dependency Injection
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.21 13:34
Оценка: +6
Здравствуйте, Somescout, Вы писали:
S>Про настройку времени жизни в DI и request-scope я так понимаю вы ни сном ни духом?
Нет, почему же. Просто приведённый пример не может служить аргументом в пользу DI-контейнеров. То, что в недрах гуя нет простого доступа к DBConnection — это хорошо, а не плохо. Так что нам не нужно средство, которое даёт эту невыносимую лёгкость сделать "а шандарахну-ка я тут запросец в базу".

А вообще, в целом, я согласен с теми из участников дискуссии, которые считают развитые DI-контейнеры всего лишь средством переноса сложности из исходного кода в конфигурацию.
Может быть, конечно, я преувеличиваю масштаб проблемы, но я в своё время нахлебался с системами, построенными по "чрезмерно компонентному" принципу. Типа "у нас есть набор универсальных кубиков, и мы в рантайме собираем из них нужное нам приложение". В итоге оказывается, что насквозь процедурный код инициализации зависимостей прекрасно отлаживается, рефакторится, и версионируется штатными средствами; а все чудеса "внешней конфигурации" — нет. Просто в рантайме почему-то в конкретный компонент уезжает не тот же самый DBConnection, что и у всех (или, наоборот, тот же самый, вместо нужного отдельного), или ещё какая пежня творится. А понять, кто в какой момент что там оверрайдит, и откуда взялись вот эти вот параметры конструктора — упражнение не для слабонервных.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: О пользе Dependency Injection
От: AlexRK  
Дата: 14.01.21 13:37
Оценка:
Здравствуйте, microuser, Вы писали:

M>Лишняя работа, больше boilerplate кода, как следствие ниже читаемость, а плюсы то есть?


Это все как раз про DI. Особенно читаемость — она там где-то в районе нуля.
Плюс лишние тормоза и еще потеря статической типизации в точке получения объекта.
Re[9]: О пользе Dependency Injection
От: AlexRK  
Дата: 14.01.21 13:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>То, что в недрах гуя нет простого доступа к DBConnection — это хорошо, а не плохо. Так что нам не нужно средство, которое даёт эту невыносимую лёгкость сделать "а шандарахну-ка я тут запросец в базу".


Плюс адин. Провоцирует на повышение связности на ровном месте. В результате на выходе Big Ball of Mud.
Re[13]: О пользе Dependency Injection
От: microuser  
Дата: 14.01.21 14:01
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, microuser, Вы писали:


M>>Лишняя работа, больше boilerplate кода, как следствие ниже читаемость, а плюсы то есть?


ARK>Это все как раз про DI. Особенно читаемость — она там где-то в районе нуля.

ARK>Плюс лишние тормоза и еще потеря статической типизации в точке получения объекта.

Как это читаемость будет меньше при большем количестве ничего не делающего кода?
Еще раз говорю, покажите реальный проект без DI или хотя бы CRUD заготовку.
Re: О пользе Dependency Injection
От: vmpire Россия  
Дата: 14.01.21 14:08
Оценка:
Здравствуйте, Министр Промышленности, Вы писали:

МП>С моей профессиональной точки зрения DI фреймворки не нужны.

Нужны. Но значительно реже, чем их реально применяют.

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

Да

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

МП>и это не перекрывается гибкостью подстановки mock-объектов
Да

МП>но обнаруживаю ярых адептов этого всего.

МП>уже и в вакансиях суют такое требование
Это всегда бывает. Когда хорошая мысль залетает в пустую голову, она занимает там всё свободное место.
DI фреймворк — это не универсальное решение всего. Это инструмент, который в каких-то случаях упрощает жизнь

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

МП>(часть плюсов знаю и гипотезы-то я имею, но мнение всё равно такое)
Преимущества описаны неоднократно и много где. Но там обычно забывают описать недостатки, на которые Вы как раз обратили внимание.
Природа популярности — хайп и увлечённость.
На мой взгляд, такие фреймворки хорошо применять тогда, когда есть реальная вероятность изменения конфигов этого фреймворка после поставки продукта.
Или в прнодукте возможны несколько конфигураций.
Например, в уже рабочем и установленном продукте поменять логгирование. Или подключить другой модуль платежей.
Или поставлять продукт разным заказчикам с кастомизированной бизнес-логикой.
В общем, те же ситуации, когда нужны по сути плагины.
Re[14]: О пользе Dependency Injection
От: AlexRK  
Дата: 14.01.21 14:14
Оценка:
Здравствуйте, microuser, Вы писали:

M>Как это читаемость будет меньше при большем количестве ничего не делающего кода?


Во-первых, количество кода не обязано быть больше. Это утверждение — не аксиома и нуждается в обосновании.
Во-вторых, читаемость зависит не только от количества кода.

M>Еще раз говорю, покажите реальный проект без DI или хотя бы CRUD заготовку.


Любой (почти) проект на гитхабе бери, там DI не будет никакого.
Re[2]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 14.01.21 14:20
Оценка: +1
Здравствуйте, Somescout, Вы писали:

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


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


Какая прелесть! А кто мешает один раз написать для базы данных какой-нибудь рапер/хелпер, который будет решать все эти вопросы без DI?
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 14.01.21 14:23
Оценка:
Здравствуйте, Somescout, Вы писали:

S>Это, вобще-то, и есть dependency injection. Только вы это вручную делаете, и фактически переносите проблемы на уровень выше: теперь вызывающий код в обязательном порядке должен иметь ссылку на базу (напрямую или через DatabaseHelper), и сам должен получить userDao — что поменялось в итоге от такой перетасовки? Ничего — все проблемы ровно на том же месте.


Как минимум поменялось то, что теперь это всё делается явно. Не надо гадать кто, где, когда, зачем. Этот код можно перенести в другой проект и он либо будет работать, либо не скомпилируется. А в случае с контейнерами он скорее всего скомпилируется, но работать не будет.
Если нам не помогут, то мы тоже никого не пощадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.