Re[9]: О пользе Dependency Injection
От: varenikAA  
Дата: 15.01.21 02:42
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>причем тут c#? а на ява или с++ ни монолиты? Большинство проектов.. учитывая популярность Unity сейчас можно сказать что большинство проектов на шарпе — полный гавнокод от школьников. Шарп тут не причем как ЯП.


Большинство ЯП монолиты, из модульных только оберон знаю ))
ЯП хороший, но требует огромного опыта для написание простого и надежного кода. Поэтому думаю начинать изучение программирования лучше с лиспа или F#.

_>Но вот если есть конструктор у App, а я явно не вижу место его вызова — меня это напрягает. Таких неявных мест должно быть по минимуму.


Вчера как раз в чате F# осбуждали, тоже считают это не очень хорошая концепция

https://translate.google.com/translate?sl=auto&tl=ru&u=https://blog.ploeh.dk/2017/02/02/dependency-rejection/

Но тут правда про другое немного, если я правильно понял. и автор часто утверждает, что на сишарпе такое сложно реализовать.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[9]: О пользе Dependency Injection
От: varenikAA  
Дата: 15.01.21 03:06
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Все равно ни понял. Контексты всегда были и без DI (Control.Parent, Control.Application, Request.Host и т.д). Добирайся нихочу.

_>Но вот если есть конструктор у App, а я явно не вижу место его вызова — меня это напрягает. Таких неявных мест должно быть по минимуму.

Понял, а то у ТС вообще неопнятно на что он жалуется. ну это субъективно. так то во всех учебниках учат что надо избегать явного создания объектов.
Взять теже фабрики, билдеры они тоже зло?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 15.01.2021 3:07 Разраб . Предыдущая версия .
Re[8]: О пользе Dependency Injection
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.01.21 07:16
Оценка: +1 :)
Здравствуйте, Sharov, Вы писали:

S>А DI то тут причем? Не вижу связи с оптимизацией sql запросов, что правильно, и DI. Тоже самое отменно может быть

S>и без плюшек DI.
Ну, во-первых, давайте всё же не путать "DI" и "DI Container".
Сама по себе DI ничего плохого не содержит.
А вот "плюшки DI" — это уже, как правило, и есть DI Container. И аргумент тут как раз был именно такой — "вот я просто взял, добавил аргумент IDBConnection в свой конструктор, и мне не надо думать, откуда он возьмётся — контейнер его мне притащит, как собака тапки".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: О пользе Dependency Injection
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.01.21 07:29
Оценка: +1
Здравствуйте, Somescout, Вы писали:
S>Да потому же — вы говорите про 27 коннектов и 300 запросов, хотя как раз DI позволяет в такой ситуации переиспользовать один контекст с одним соединением и кэшированием запросов.
Ухты. Ещё и кэширование запросов? Расскажите, что вы имеете в виду, а то я уже представил себе всяких ужасов.
Вот вы, скажем, Безумный Макс: Дорога Ярости смотрели? То, что вы описываете, выглядит наоборот: дорога крайне удобная, а вот в конце — всё как в фильме: муть, взрывы, кишки, и прочее.
сделать "а шандарахну-ка я тут запросец в базу".
S>Ок, а если в этом месте нужны данные из базы — что именно вы предлагаете с этим делать?
Предлагаю добавить нужные данные во viewModel, и соответствующим образом подкорректировать код порождения viewModel, который уже ходит в базу. Потому что каждый roundTrip между апп-сервером и СУБД — это увеличение времени удержания соединения (если мы сумели привинтить повторное использование соединения). Внезапно окажется, что
1. В 70% случаев нужные нам данные уже есть во viewModel, просто кто-то поленился повнимательнее в неё посмотреть
2. В 20% случаев можно просто добавить ещё одно поле в уже существующий select, не изменив время исполнения запроса
3. В 10% случаев можно добавить ещё один селект в тот батч, который строит viewModel, минимально изменив время исполнения запроса.
4. В самом редком случае нам прямо потребуется специальный отдельный запрос, который мы пошлём уже после того, как получили ответы на предыдущие запросы.
S>Нет, вы докопались до DbContext(знал бы что вас на нём заклинит — написал бы DAO или "Сервис получения данных (с) (tm)")
Было бы ещё хуже. Признайтесь честно — вы профилировали когда-нибудь SQL трафик ентерпрайз-приложения? Тридцатилетние архитекторы выходят из этой комнаты седыми.
И чем больше у нас там DAO или сервисов получения данных — тем ужаснее выходит результат.
S>То есть с компонентными системами нахлебались, а с процедурными, которые тянут напрямую связи во все зависимые компоненты — нет.
До компонентных систем я нахлебался с "неявными связями" — это когда у нас есть набор переменных различной степени глобальности, и обращения к ним рассеяны по коду без малейшей разметки.
Ну, я и сам так писал — на клиппере. Меня извиняет только то, что мне было 11 лет. То же самое я наблюдал в ентерпрайз решениях на классическом ASP — это когда в Global.asa есть dbconn, и connectionStr. И ещё dbconn2 в global.inc, незнамо для чего.
И каждая страничка либо берёт dbconn, либо dbconn2, либо открывает своё подключение через connectionStr.
Понять, почему так — хз. Скорее всего, тупо из-за некомпетентности разработчиков. Исправить это — упаси меня байт: там пара тысяч таких страничек, разобраться, кто от кого зависит — нафиг-нафиг.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: О пользе Dependency Injection
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.01.21 07:35
Оценка:
Здравствуйте, IT, Вы писали:

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


M>>Хотелось бы real life пример бизнес приложения, или хотя бы CRUD hello world без DI.


IT>Давай ты нам приведёшь такой пример с DI, а мы его переделаем без DI.

Ну так привели же уже. Вон, прямо в википедии чёрным по белому написано "смотрите, какой ужас получается при Внедрении зависимости при помощи фреймворка".
Берём, выкидываем нафиг говноXML, возвращаемся на шаг "без использования dependency injection" и получаем нормальный императивный код.
В котором внесение изменений в конструктор двигателя подскажет нам, что поменять в конструкторе автомобиля. И прямо в IDE, даже до запуска компилятора.
Если вдруг нам потребуется конструировать автомобили с разными типами двигателей (а нам потребуется? Ну, вот по правде?), то мы перейдём к "внедрению зависимости вручную" — и у нас все зависимости продолжат оставаться под контролем компилятора.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: О пользе Dependency Injection
От: barn_czn  
Дата: 15.01.21 08:10
Оценка: +2
Здравствуйте, varenikAA, Вы писали:

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


_>>Все равно ни понял. Контексты всегда были и без DI (Control.Parent, Control.Application, Request.Host и т.д). Добирайся нихочу.

_>>Но вот если есть конструктор у App, а я явно не вижу место его вызова — меня это напрягает. Таких неявных мест должно быть по минимуму.

AA>Понял, а то у ТС вообще неопнятно на что он жалуется. ну это субъективно. так то во всех учебниках учат что надо избегать явного создания объектов.


я таких учебников не читал.

AA>Взять теже фабрики, билдеры они тоже зло?


Что есть фабрика? Если это метод который внутри вызывает new MyClass, потом этот метод передается как делегат — отлично, потому что эта связь явная и ее легко отследить.
А если это в каком то магическом месте неявно задано, как с DI, — я не понимаю.

Дальше, говорят что плюс в том что из любого места я могу получить(создать) любой инстанс. Но простите, в таком случае ваша архитектура превратилась в кучу глобальных переменных где Всё доступно Отовсюду. Как же тогда быть с принципами разграничений? В определенном месте кода должно доступно только то что необходимо, что передали явно, что доступно по ссылочным связям.
Re[11]: О пользе Dependency Injection
От: Somescout  
Дата: 15.01.21 08:21
Оценка: +3
Здравствуйте, Sinclair, Вы писали:

S>Вот вы, скажем, Безумный Макс: Дорога Ярости смотрели? То, что вы описываете, выглядит наоборот: дорога крайне удобная, а вот в конце — всё как в фильме: муть, взрывы, кишки, и прочее.

Чувствую сколь-нибудь конструктивного диалога с вами не выйдет, поэтому просто закончу его на этом.
ARI ARI ARI... Arrivederci!
Re[6]: О пользе Dependency Injection
От: Sharov Россия  
Дата: 15.01.21 08:43
Оценка:
Здравствуйте, SkyDance, Вы писали:


SD>PS: написанное выше относится только к слову "конфигурация". Но не с dependency injection. Эта идиома по сути своей представляет не что иное как способ задавать интерфейс (API). Почему придумали новый термин... ну, сразу вот это вспоминается:


А какой был старый термин?
Кодом людям нужно помогать!
Re[4]: О пользе Dependency Injection
От: MadHuman Россия  
Дата: 15.01.21 08:55
Оценка:
Здравствуйте, IT, Вы писали:

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


ARK>>Это меня на текущем проекте просто достало. Чуваки с золотыми молотками суют это уродство во все щели — и куда надо, и куда не надо (на самом деле почти никуда не надо). Гора интерфейсов, за которыми найти не возможно просто ничего. Тьфу.


IT>Я такое при возможности выкорчёвываю нещадно. На самом деле есть очень простой и эффективный критерий правильно написанной бизнес логики. Если логически законченный функционал бизнес логики легко извлекается из одного проекта и спокойно переносится в другой, то это правильно написанная бизнес логика. Если же для переезда в соседний дом нужно перетащить с собой весь подъезд, то это не код, а кусок оверинжениринга.

Обычно функционал бизнес-логики сильно приколочен гвоздями к структуре данных (т.е. подъезду). Это и мешает переносу.
А если начнем "абстрагироваться" от конкретной структуры данных вводя промежуточные абстракции-структуры, то в пределе снова приходим к оверинжинирингу и упомянутой вами ранее проблеме

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

Re[5]: О пользе Dependency Injection
От: petroa  
Дата: 15.01.21 10:42
Оценка:
IT>Ты не правильно ставишь вопрос. Т.к. это ты добавляешь в проект новый инструмент, то вопрос должен ставится как "какую проблему этот инструмент решает, какие негативные последсвия вносит и каково их соотношение". Т.е. польза, вред, что больше.

А если, например, так? Если максимально "близко к телу". Представим, что определение всей конфигурации IoC-контейнера происходит в одном файле, кодом (не через xml, аннотации и прочую муть, просто в каком-то классе с конфигурацией модулей).
— определение реализации для интерфейсов или просто регистрация классов (самих по себе) в контейнере.
— конфигурирование времени жизни объектов классов/реализаций классов (правил инстанциации — синглтон, сессионный, по одному на каждую зависимость и т.д.), зарегистрированных в контейнере.
— автоматическое удовлетворение зависимостей между всеми классами, в соответствии с определенными выше правилами по времени жизни/созданию при автоматическом конструировании объекта из контейнера.

Таким образом:
— вся конфигурация наглядна и все правила описаны кодом в одном файле. Это, конечно, может не так явно, как "Class class = new Class", но ведь у этого "явного" подхода тоже есть минусы (отсутствие "единого языка", т.е. api который даёт готовый ioc-контейнер). Подход с конфигурированием IoC-контейнера в одном файле может быть непонятен скорее из-за того, что он не так традиционен, конечно.
— по мере роста приложения все новые компоненты (т.е. классы) продолжают регистрироваться и описываться в одном месте, в этом классе-конфиге, наглядно (к этому принуждает в т.ч. архитектура приложения, работающая с контейнером для создания объектов).
— при создании компонента (класса) с зависимостями, зарегистрированными в ioc-контейнере, все эти зависимости отслеживаются и создаются автоматически согласно конфигурации ioc-контейнером (кажется, начинаю повторяться )
— конфигурацию можно иметь отдельную (или на основе первой) для тестов, подсовывая при регистрации для интерфейсов другие реализации, ну и прочее в таком роде.

Понятно, что не все классы обязаны инстациироваться таким образом через сконфигурированный контейнер, конечно.

Т.е. мы (ценой добавления библиотеки, да) получаем в основном инструмент для а) более удобного (чем описание этого всего "своим языком" явно) конфигурирования интерфейсов/реализаций; б) следующего из предыдущего автоматического создания объектов по этим правилам ioc-контейнером, с соблюдением зависимостей между ними.

Это ведь вроде, так или иначе, придётся делать самому. Можно делегировать ioc-контейнеру. Интересно ваше мнение.
Re[8]: О пользе Dependency Injection
От: yenik  
Дата: 15.01.21 10:50
Оценка:
МП>я имел в виду банальную задачу:
МП>есть фарш исторического кода, который неправильно работает
МП>ты разбираешься в какой момент всё идёт неправильно, отслеживаешь объекты где используются, откуда получаются
МП>и вот на 7м-13м уровне вложенности вызывов ты понимаешь, тебе надо срочно знать откуда берётся значение вот в этом объекте
МП>прыг F12 (у меня это решарперовский GoToDefinition)
МП>ага есть конструктор прыг Alt+F7 (у меня это FindUsages) а хрен тебе — он вызывается неявно в рамках DI
МП>и хорошо если ты это ещё знаешь
МП>а то вполне можешь подумать "ага, значит инициализируется не здесь", и пойти исследовать фарш дальше вглубь!
МП>и это убийственно

ОК. Но при чём тут автоматический рефакторинг?

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


И почему
МП>и это не перекрывается гибкостью подстановки mock-объектов
?
Отредактировано 15.01.2021 10:53 yenik . Предыдущая версия .
Re[11]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:28
Оценка:
Здравствуйте, C0s, Вы писали:

IT>>Что здесь куда интегрировать?


C0s>при всём уважении у меня не повернётся язык назвать такой retriever-метод бизнес-логикой

C0s>по крайней мере, тяжело представить такой метод изменяющимся часто на протяжении жизни проекта

Это мне понятно. Когда в руках молоток, то всё кажется гвоздями. А раз так, то для реализации такой простой логики нужно ещё восемь интерфейсов, развесистую иерархию классов и десяток DTO объектов. Тут уж понятное дело без DI никуда.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:33
Оценка:
Здравствуйте, Somescout, Вы писали:

S>>>Ок, напишу я его, а прокинуть его как? И я опять же не понимаю: зачем "решать эти вопросы без DI" — как это облегчает работу?

IT>>Ты не правильно ставишь вопрос. Т.к. это ты добавляешь в проект новый инструмент, то вопрос должен ставится как "какую проблему этот инструмент решает, какие негативные последсвия вносит и каково их соотношение". Т.е. польза, вред, что больше.
S>Стоп. Давайте вы сначала покажете правильный (с вашей точки зрения) способ использования этого хелпера, а потом порассуждаем о достоинствах и недостатках. Иначе я буду просто предполагать, что вы предлагаете статический синглтон — и, думаю, не нужно говорить почему это плохая практика.

Не-не-не. Нам твои DI фреймворки нафиг не нужны и нам без них хорошо. Покажи, что мы не правы, приведи код, где DI фремворки рулят.
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:35
Оценка:
Здравствуйте, Somescout, Вы писали:

IT>>Давай мы сразу определимся. Речь идёт не о DI как таковом, а о DI фреймворках и всяческих IoC контейнерах. Ты сейчас про что?

S>О них в том числе. Я просто действительно не понимаю что именно вас в них смущает: у меня два проекта, когда из первого, построенного на DI потребовалось перенести компоненты во второй (без DI) — не возникло никаких проблем, я просто руками конструировал все объекты.

Т.е. чтобы перенести код пришлось его не слабо так переписать. Правильно?
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:38
Оценка:
Здравствуйте, Somescout, Вы писали:

S>Да я вроде уже в первом же комментарии это объяснял — вам не нужно конструировать контекст базы непосредственно внизу. А если абстрагироваться через интерфейсы, то компонент может вообще не знать с чем именно он работает — есть интерфейс для получения данных, он его и использует. А что за ним прячется: сама база, кэш или сервис — его не касается.


При желании можно абстрагироваться даже от интерфейсов. Но я не буду говорить как, не дай боже вам это понравится.
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:40
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ну так привели же уже. Вон, прямо в википедии чёрным по белому написано "смотрите, какой ужас получается при Внедрении зависимости при помощи фреймворка".


Я уже по этому поводу отписался. Они даже на простейшем примере умудрились всё запутать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 14:49
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>Обычно функционал бизнес-логики сильно приколочен гвоздями к структуре данных (т.е. подъезду). Это и мешает переносу.


Правильно. Поэтому данные нужно тоже чётко различать. Есть данные общие для всего приложения. Как правило они не так многочисленны и их структура более стабильна. Их можно оформить в виде отдельного компонента. Структуры данных, специфичные для конкретной бизнес логики, могут (и должны) находиться где-нибудь поблизости или, как минимум, обособленно.

MH>А если начнем "абстрагироваться" от конкретной структуры данных вводя промежуточные абстракции-структуры, то в пределе снова приходим к оверинжинирингу и упомянутой вами ранее проблеме


А вот этого не надо.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 15:10
Оценка: 11 (2) +1
Здравствуйте, petroa, Вы писали:

P>Это ведь вроде, так или иначе, придётся делать самому. Можно делегировать ioc-контейнеру. Интересно ваше мнение.


Дело не в конфигурации. Обрати внимание, нелюбители DI фреймворков сетуют прежде всего на то, что с таким кодом сложно разбираться. Это действительно так. Это сложно понять, если ты написал пару проектов исключительно как писатель и не занимался их поддержкой продолжительное время. А ещё лучше это прочувствовать на чужом коде. Вот представь, у тебя есть простейший код:

class Foo
{
    public Foo(Bar b)
    {
        if (!b.IsValid)
            throw ...
    }
}

Код кидает исключение. Твоя задача — найти причину. Если код без DI фрейворков, то эта задача из разряда примитивных. Shift-F12 в студии (R#?) покажет тебе абсолютно все вызовы конструктора и далее по цепочке можно раскрутить всё даже без необходимости запускать этот код. Если же используется DI фреймворк, то для того, чтобы понять что происходит необходимо запускать как минимум отладчик. При этом возникает несколько проблем.

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

При наихудшем сценарии проблему всё равно придётся решать путём анализа кода, но в случае с DI фреймворком это на порядок сложнее.

И здесь я опять вынужден повторить свой вопрос. Какую проблему решают DI фреймворки, которая по своей значимости способна перевесить вносимые в проект неудобства?
Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 18.01.2021 14:34 IT . Предыдущая версия .
Re[10]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 15:19
Оценка:
Здравствуйте, microuser, Вы писали:

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


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

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


Можно я ещё немного добавлю полезности? Спасибо!

enum SourceType
{
    Foo,
    ar
}

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

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


Как DI фреймворк разрулит ситуацию для разных sourceType?
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: О пользе Dependency Injection
От: IT Россия linq2db.com
Дата: 15.01.21 15:24
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Потому что конфигурирование и есть кодирование.

SD>Более того, "конфигурирование" требует ровно того же тестирования, что и "кодирование", и ровно такого же процесса выкатывания изменений.

Можно пример тестирования конфигурации Production?
Если нам не помогут, то мы тоже никого не пощадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.