Re[13]: Инициализация приложения - внедрение зависимостей в D
От: vmpire Россия  
Дата: 10.11.23 18:53
Оценка:
Здравствуйте, ·, Вы писали:

V>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?

·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
В любом случае эта проблема не зависит от наличия или отсутствия DI

V>>·>Никаких осязаемых преимуществ конкретно контейнер не даёт.

V>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
·>Так мой поинт, что никогда не даёт.
Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.

V>>·>Ну можно так выразиться, хотя неясно почему "контейнер", нет ничего контейнерного (словаря-то нет!). Это и есть хорошо, что статический. Динамика это в php и javascript, зачем это тащить в компилируемые ЯП — неясно.

V>>Словарь — это всего лишь один из возможных механизмов реализации. Если контейнер не будет библиотекой для использования в произвольных проектах, а делается для одного раза, то словарь будет только лишним.
·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
Как я писал уже в ответе ТС, простейший вариант — это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.

V>>·>Подавляющее большинство связывания будет через Constructor Injection. Т.е. ты тупо не сможешь создать объект в коде не имея нужных ему зависимостей.

V>>Пример:
·>
V>>IDatabase myDatabase = null;
·>

·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):
Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.

V>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.

·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.

·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.

·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
Re[14]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 10.11.23 21:30
Оценка:
Здравствуйте, vmpire, Вы писали:

V>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?

V>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>В любом случае эта проблема не зависит от наличия или отсутствия DI
Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка". Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.

V>>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.

V>·>Так мой поинт, что никогда не даёт.
V>Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
V>Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.
Угу, т.к. все эти обобщённые реализации — по сути переливание из пустого в порожнее.

V>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.

V>Как я писал уже в ответе ТС, простейший вариант -
Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.

V>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.

Это как-то не очень подходит под общепринятое понятие IoC-контейнер.

V>·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):

V>Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
И получилась яркая иллюстрация, внезапно. Ты показал типичный код который обычно логически соответствует типичной конфигурации контейнера и сразу бросилось в глаза — какой же кривой косячный код, и насколько же он хрупкий и где что может пойти не так. Так никто вменяемый писать не будет и реьвю такое уж точно не пройдёт.
А вот если это говно завернуть блестящей обёрткой IoC-фреймворка — так внезапно — конфеткой называть начинают.

V>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.

Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.

V>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.

V>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.

V>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.

V>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.

V>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.

О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.

V>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.

V>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.

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

V>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
wiring code — основан на DI тоже.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 10.11.2023 21:34 · . Предыдущая версия . Еще …
Отредактировано 10.11.2023 21:32 · . Предыдущая версия .
Re[15]: Инициализация приложения - внедрение зависимостей в
От: vmpire Россия  
Дата: 11.11.23 01:30
Оценка:
Здравствуйте, ·, Вы писали:

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


V>>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?

V>>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>>В любом случае эта проблема не зависит от наличия или отсутствия DI
·>Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
·>Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка".
Да, именно это
·>Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в ·>которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
В данном подвопросе было не про гибкость, а про то, что в обоих вариантах можно забыть что-нибудь инициализировать и будет падение в рантайме.

V>>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.

V>>Как я писал уже в ответе ТС, простейший вариант -
·>Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
Результат этого выражения нужно где-то хранить. Вот для этого поля и классы.

V>>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.

·>Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
Специально попытался найти официальное определение — не нашёл.
Поэтому я понимаю буквально: IoC-контейнер — контейнер, хранящий объекты, используемые для реализации IoC

V>>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.

·>Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
Ещё и не такой пишут, поверьте.

V>>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.

V>>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
·>Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
Потому, что Вы продолжаете цепляться к конкретному коду и не хотите понимать идею. А идея в том, что инициализация может быть сложной, иметь вложенные вызовы, внешние зависимости и т.п. И в этой реализации могут быть ошибки. В том числе и не обнаруживаемые компилятором. Или обнаруживаемые, но не ошибкой, а warningом, которые индусы игнорируют.

V>>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.

V>>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.

V>>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.

·>О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
Вот с этим я согласен. Когда в контейнер начинают валить всё подряд — получается свалка.

V>>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.

V>>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
·>Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
Это ровно то (второй пример), чем занимается DI фреймворк.

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

V>>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
·>wiring code — основан на DI тоже.
Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.
Re[16]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 11.11.23 18:53
Оценка:
Здравствуйте, vmpire, Вы писали:

V>·>Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в ·>которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.

V>В данном подвопросе было не про гибкость, а про то, что в обоих вариантах можно забыть что-нибудь инициализировать и будет падение в рантайме.
А я говорю о том, что с вариантом wiring кода можно написать код так, что забыть будет невозможно и падения в рантайме произойти не может. А в случае фреймворка — код написать нормально нельзя никак. В этом и есть принципиальная разница.

V>·>Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.

V>Результат этого выражения нужно где-то хранить. Вот для этого поля и классы.
Ну как минимум — в локальной переменной или тупо однострочник void main(String args[]){new App(new Dependency()).start(args);}.

V>·>Это как-то не очень подходит под общепринятое понятие IoC-контейнер.

V>Специально попытался найти официальное определение — не нашёл.
Это понятие родилось где-то в Spring, стоит читать его доку.

V>Поэтому я понимаю буквально: IoC-контейнер — контейнер, хранящий объекты, используемые для реализации IoC

Ну типа того. А wiring код может ничего не хранить. Он просто соединяет компоненты.

V>>>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.

V>·>Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>Ещё и не такой пишут, поверьте.
Верю, конечно. Но если в проекте пишут такой код, то проблемы с wiring-ом будут незаметны на фоне всего остального.

V>>>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.

V>·>Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>Потому, что Вы продолжаете цепляться к конкретному коду и не хотите понимать идею. А идея в том, что инициализация может быть сложной, иметь вложенные вызовы, внешние зависимости и т.п. И в этой реализации могут быть ошибки. В том числе и не обнаруживаемые компилятором. Или обнаруживаемые, но не ошибкой, а warningом, которые индусы игнорируют.
Сложная инициализация wiring-кодом пишется и тестируется гораздо проще, чем на фреймворке. Но, повторюсь, на wiring код можно хотя бы натравить инструменты и найти ошибки-варнинги. С фреймворком будет говно и никак ни проанализировать, ни исправить, единственный надёжный тест — запустить на проде и поглядеть что поломалось.

V>>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.

V>·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.
Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.

V>>>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.

V>·>О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>Вот с этим я согласен. Когда в контейнер начинают валить всё подряд — получается свалка.
А ты видел когда-то что-то другое? Контекст контейнера это огромный словарь всего подряд со всего приложения, и всё публично — что угодно может зависеть от чего угодно, т.к. всё в одной свалке. Возможности структуризации контекста практически отсутствуют.

V>>>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.

V>>>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
V>·>Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>Это ровно то (второй пример), чем занимается DI фреймворк.
Да боже. Не "DI фреймворк", а "IoC фреймворк". SL и DI это два противоположных подхода реализации IoC принципа. Не знаю что ты имеешь в виду, но в этом топике примеров кода SL не было.
"дай мне ссылку на реализацию интерфейса IБазаДанных" — это SL: var db = serviceLocator.GetService<IБазаДанных>().

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

V>>>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
V>·>wiring code — основан на DI тоже.
V>Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.
Я не знаю что такое DI-контейнер. На всякий случай: "dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally"
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[17]: Инициализация приложения - внедрение зависимостей в
От: vmpire Россия  
Дата: 11.11.23 20:19
Оценка:
Здравствуйте, ·, Вы писали:

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


V>>·>Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в ·>которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.

V>>В данном подвопросе было не про гибкость, а про то, что в обоих вариантах можно забыть что-нибудь инициализировать и будет падение в рантайме.
·>А я говорю о том, что с вариантом wiring кода можно написать код так, что забыть будет невозможно и падения в рантайме произойти не может. А в случае фреймворка — код написать нормально нельзя никак. В этом и есть принципиальная разница.
естественно, свой код всегда более гибкий чем любой фреймворк.

V>>·>Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.

V>>Результат этого выражения нужно где-то хранить. Вот для этого поля и классы.
·>Ну как минимум — в локальной переменной или тупо однострочник void main(String args[]){new App(new Dependency()).start(args);}.
Ну, однострочник и одна переменная для сколь-нибудь крупного приложения — это несерьёзно.

V>>·>Это как-то не очень подходит под общепринятое понятие IoC-контейнер.

V>>Специально попытался найти официальное определение — не нашёл.
·>Это понятие родилось где-то в Spring, стоит читать его доку.
Читал. Именно определения не нашёл.


V>>>>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.

V>>·>Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>>Ещё и не такой пишут, поверьте.
·>Верю, конечно. Но если в проекте пишут такой код, то проблемы с wiring-ом будут незаметны на фоне всего остального.
Пожалуй, да.

V>>>>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.

V>>·>Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>>Потому, что Вы продолжаете цепляться к конкретному коду и не хотите понимать идею. А идея в том, что инициализация может быть сложной, иметь вложенные вызовы, внешние зависимости и т.п. И в этой реализации могут быть ошибки. В том числе и не обнаруживаемые компилятором. Или обнаруживаемые, но не ошибкой, а warningом, которые индусы игнорируют.
·>Сложная инициализация wiring-кодом пишется и тестируется гораздо проще, чем на фреймворке. Но, повторюсь, на wiring код можно хотя бы натравить инструменты и найти ошибки-варнинги. С фреймворком будет говно и никак ни проанализировать, ни исправить, единственный надёжный тест — запустить на проде и поглядеть что поломалось.
К сожалению, инициализация в тестовом режиме не проверит инициализацию в проде. Просто потом, что это другая инициализация.

V>>>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.

V>>·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>>Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.
·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.
ок, скажу совсем просто: нужно передать фабрику в 2 конструктора. Для этого её нужно сохранить в переменной, так ведь? Эта переменная и будет точкой хранения.

V>>>>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.

V>>·>О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>>Вот с этим я согласен. Когда в контейнер начинают валить всё подряд — получается свалка.
·>А ты видел когда-то что-то другое? Контекст контейнера это огромный словарь всего подряд со всего приложения, и всё публично — что угодно может зависеть от чего угодно, т.к. всё в одной свалке. Возможности структуризации контекста практически отсутствуют.
Другое я видел, пожалуй, только в своих приложениях для себя.

V>>>>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.

V>>>>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
V>>·>Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>>Это ровно то (второй пример), чем занимается DI фреймворк.
·>Да боже. Не "DI фреймворк", а "IoC фреймворк". SL и DI это два противоположных подхода реализации IoC принципа. Не знаю что ты имеешь в виду, но в этом топике примеров кода SL не было.
·>"дай мне ссылку на реализацию интерфейса IБазаДанных" — это SL: var db = serviceLocator.GetService<IБазаДанных>().
Понятно, меня не поняли. Забей на название, проще кодом.
Первый стиль (свой класс):
class Services
{
   public IDatabase Database { get; set; }
   public ILogger Logger { get; set; }
}

Использование:
var db = myServices.Database;


Второй стиль (готовая библиотека)
class Services
{
   public T Get<T>();
}

Использование:
var db = myServices.Get<IDatabase>();



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

V>>>>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
V>>·>wiring code — основан на DI тоже.
V>>Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.
·>Я не знаю что такое DI-контейнер. На всякий случай: "dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally"
Имелся в виду IoC контейнер. Я иногда ошибочно пишу DI контейнер
Re[18]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 11.11.23 21:07
Оценка:
Здравствуйте, vmpire, Вы писали:

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

V>естественно, свой код всегда более гибкий чем любой фреймворк.
Дело не в гибкости как таковой, а в том, что фреймворк — это рантайм логика и оно падает в рантайм. Поэтому там принципиально ничего невозможно проверить компилятором.

V>>>Результат этого выражения нужно где-то хранить. Вот для этого поля и классы.

V>·>Ну как минимум — в локальной переменной или тупо однострочник void main(String args[]){new App(new Dependency()).start(args);}.
V>Ну, однострочник и одна переменная для сколь-нибудь крупного приложения — это несерьёзно.
Да не важно. В крупном проекте wiring код будет просто крупные куски собирать. А крупные куски иметь свой wiring-код и т.п. Т.е. это просто будет объекты ЯП в памяти. Никакого специальоного словаря-контейнера нет. Ничего нигде не хранится. Ну ладно, хранится в memory heap, как собственно и все другие объекты в приложении.

V>>>Специально попытался найти официальное определение — не нашёл.

V>·>Это понятие родилось где-то в Spring, стоит читать его доку.
V>Читал. Именно определения не нашёл.
Ну потому что официального особо ничего нет... Но это вроде терпимо как некое описание:
IoC creates the objects, configures and assembles their dependencies, manages their entire life cycle. The Container uses Dependency Injection to manage the components that make up the application.

V>·>Верю, конечно. Но если в проекте пишут такой код, то проблемы с wiring-ом будут незаметны на фоне всего остального.

V>Пожалуй, да.
Именно, всё можно сломать и испоганить. Поэтому я и пытаюсь повернуть разговор в русло "а как же делать хорошо?". Так вот фреймворк сделать хорошо — не позволяет, принципиально. Хорошо можно делать wiring-кодом.

V>·>Сложная инициализация wiring-кодом пишется и тестируется гораздо проще, чем на фреймворке. Но, повторюсь, на wiring код можно хотя бы натравить инструменты и найти ошибки-варнинги. С фреймворком будет говно и никак ни проанализировать, ни исправить, единственный надёжный тест — запустить на проде и поглядеть что поломалось.

V>К сожалению, инициализация в тестовом режиме не проверит инициализацию в проде. Просто потом, что это другая инициализация.
Примерно то же самое можно сказать о любом коде "обработка данных в тестовом режиме не проверит обработку данных в проде. Просто потому, что это другие данные". Но ведь более менее работающий код таки умудряются иногда писать.

Так вот, инициализация это такой же код как и всё остальное. Раз умеешь качественно писать на ЯП код бизнес-логики, то в чём проблема писать код инициализации — не понимаю.

V>>>>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.

V>·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.
V>ок, скажу совсем просто: нужно передать фабрику в 2 конструктора. Для этого её нужно сохранить в переменной, так ведь? Эта переменная и будет точкой хранения.
Т.е. если тебе значение sin(x) нужно передать в две функции, то его нужно сохранить в переменной. Значит нужен библиотечный или самописный контейнер для хранения sin(x)??!
Пойми простую мысль:
var y = sin(x);
var a = f1(y);
var b = f2(y);

и
var factory = new RequestContextFactory(db);
var thing1 = new Thing1(factory);
var thing2 = new Thing2(factory);

Отличается только именами символов.

V>·>А ты видел когда-то что-то другое? Контекст контейнера это огромный словарь всего подряд со всего приложения, и всё публично — что угодно может зависеть от чего угодно, т.к. всё в одной свалке. Возможности структуризации контекста практически отсутствуют.

V>Другое я видел, пожалуй, только в своих приложениях для себя.
Т.е. на практике именно глобальная свалка.

V>·>Да боже. Не "DI фреймворк", а "IoC фреймворк". SL и DI это два противоположных подхода реализации IoC принципа. Не знаю что ты имеешь в виду, но в этом топике примеров кода SL не было.

V>·>"дай мне ссылку на реализацию интерфейса IБазаДанных" — это SL: var db = serviceLocator.GetService<IБазаДанных>().
V>Понятно, меня не поняли. Забей на название, проще кодом.
V>Первый стиль (свой класс):
Это вообще неясно что такое и зачем так делать. Особенно наличие setter-ов удивляет.

V>Второй стиль (готовая библиотека)

V>var db = myServices.Get<IDatabase>();

Это и есть антипаттерн SL. Так не надо делать. Это противоположность DI.

V>>>·>wiring code — основан на DI тоже.

V>>>Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.
V>·>Я не знаю что такое DI-контейнер. На всякий случай: "dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally"
V>Имелся в виду IoC контейнер. Я иногда ошибочно пишу DI контейнер
Значит я не понял твою мысль здесь...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[19]: Инициализация приложения - внедрение зависимостей в
От: vmpire Россия  
Дата: 13.11.23 11:27
Оценка:
Здравствуйте, ·, Вы писали:

V>>>>Специально попытался найти официальное определение — не нашёл.

V>>·>Это понятие родилось где-то в Spring, стоит читать его доку.
V>>Читал. Именно определения не нашёл.
·>Ну потому что официального особо ничего нет... Но это вроде терпимо как некое описание:
·>IoC creates the objects, configures and assembles their dependencies, manages their entire life cycle. The Container uses Dependency Injection to manage the components that make up the application.
Это только описание конкретной реализации. А общего термина с определением, похоже. нет

·>Поэтому я и пытаюсь повернуть разговор в русло "а как же делать хорошо?". Так вот фреймворк сделать хорошо — не позволяет, принципиально. Хорошо можно делать wiring-кодом.

Я бы сказал, фреймворк не позволяет делать так, как хочется (потому он, собственно, и фреймворк).
Делать приемлемо (путсь не хорошо) фреймворк позволяет.


V>>·>Сложная инициализация wiring-кодом пишется и тестируется гораздо проще, чем на фреймворке. Но, повторюсь, на wiring код можно хотя бы натравить инструменты и найти ошибки-варнинги. С фреймворком будет говно и никак ни проанализировать, ни исправить, единственный надёжный тест — запустить на проде и поглядеть что поломалось.

V>>К сожалению, инициализация в тестовом режиме не проверит инициализацию в проде. Просто потом, что это другая инициализация.
·>Примерно то же самое можно сказать о любом коде "обработка данных в тестовом режиме не проверит обработку данных в проде. Просто потому, что это другие данные". Но ведь более менее работающий код таки умудряются иногда писать.

·>Так вот, инициализация это такой же код как и всё остальное. Раз умеешь качественно писать на ЯП код бизнес-логики, то в чём проблема писать код инициализации — не понимаю.


V>>>>>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.

V>>·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.
V>>ок, скажу совсем просто: нужно передать фабрику в 2 конструктора. Для этого её нужно сохранить в переменной, так ведь? Эта переменная и будет точкой хранения.
·>Т.е. если тебе значение sin(x) нужно передать в две функции, то его нужно сохранить в переменной. Значит нужен библиотечный или самописный контейнер для хранения sin(x)??!
·>Пойми простую мысль:
·>
·>var y = sin(x);
·>var a = f1(y);
·>var b = f2(y);
·>

·>и
·>
·>var factory = new RequestContextFactory(db);
·>var thing1 = new Thing1(factory);
·>var thing2 = new Thing2(factory);
·>

·>Отличается только именами символов.
Именно! И вот в этом случае переменная y (или factory) и будет той самой переменной, о которой я говорю.
Это и будет примитивный IoC контейнер, в данном простейшем случае — из одной переменной.


V>>Второй стиль (готовая библиотека)

·>
V>>var db = myServices.Get<IDatabase>();
·>

·>Это и есть антипаттерн SL. Так не надо делать. Это противоположность DI.
У MS такой вариант как раз и называется Dependency Injection

V>>>>Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.

V>>·>Я не знаю что такое DI-контейнер. На всякий случай: "dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally"
V>>Имелся в виду IoC контейнер. Я иногда ошибочно пишу DI контейнер
·>Значит я не понял твою мысль здесь...
Да мысль простая. Если пишете, например, ASP.NET приложение, которое в своей основе имеет IoC контейнер с сервисами, то не использовать его не получится.
Re[20]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 13.11.23 12:38
Оценка:
Здравствуйте, vmpire, Вы писали:

V>·>Ну потому что официального особо ничего нет... Но это вроде терпимо как некое описание:

V>·>IoC creates the objects, configures and assembles their dependencies, manages their entire life cycle. The Container uses Dependency Injection to manage the components that make up the application.
V>Это только описание конкретной реализации. А общего термина с определением, похоже. нет
Ну в целом ясно о чём речь. Это не строгая теория, а просто терминология.

V>·>Поэтому я и пытаюсь повернуть разговор в русло "а как же делать хорошо?". Так вот фреймворк сделать хорошо — не позволяет, принципиально. Хорошо можно делать wiring-кодом.

V>Я бы сказал, фреймворк не позволяет делать так, как хочется (потому он, собственно, и фреймворк).
V>Делать приемлемо (путсь не хорошо) фреймворк позволяет.
Ок. Это уже у кого какие стандарты качества. Я считаю, что падения в проде — неприемлимо.

V>·>Так вот, инициализация это такой же код как и всё остальное. Раз умеешь качественно писать на ЯП код бизнес-логики, то в чём проблема писать код инициализации — не понимаю.


V>·>Отличается только именами символов.

V>Именно! И вот в этом случае переменная y (или factory) и будет той самой переменной, о которой я говорю.
V>Это и будет примитивный IoC контейнер, в данном простейшем случае — из одной переменной.
Тогда это словоблудие. Любой код в котором есть локальная переменная является IoC-конейнером. Бред же.

V>·>Это и есть антипаттерн SL. Так не надо делать. Это противоположность DI.

V>У MS такой вариант как раз и называется Dependency Injection
Ты просто невнимательно читаешь. Открой секцию Recommendations и там явно написано то, что я говорю: don't invoke GetService to obtain a service instance when you can use DI instead.

V>>>Имелся в виду IoC контейнер. Я иногда ошибочно пишу DI контейнер

V>·>Значит я не понял твою мысль здесь...
V>Да мысль простая. Если пишете, например, ASP.NET приложение, которое в своей основе имеет IoC контейнер с сервисами, то не использовать его не получится.
Ну, неужели нельзя писать ASP.NET приложение в основе которого нет контейра?.. Неуежли платформа окончательно заиндусятилась?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Инициализация приложения - внедрение зависимостей в DDD
От: zelenprog  
Дата: 14.11.23 05:46
Оценка:
Z>>Можно ли написать свой класс типа "самопальный" контейнер?
V>Конечно, это совсем несложно. Потому их уже и написали кучу.
V>Простейший контейнер — это словарь, где ключ — тип интерфейса, а значение — экземпляр реализующего класса или функция его создания.
V>А если список типов фиксирован, а универсальность контейнера не нужна, то ещё проще, даже без словаря. Просто обычный класс или структура с полями, указывающими на текущие реализации нужных интерфейсов.

Z>>Тогда получается, что каждый класс программы должен иметь ссылку на этот объект "самопального" контейнера?

V>каждый, где нужно его содержимое.

Тут проблема возникает в следующем.
Как сделать, чтобы этот класс был доступен для всех классов, в которых может понадобиться зависимость? Ведь вложенность классов может быть очень глубокой.
Передавать этот класс как параметр всех методов?

Дело в том, что в "моей" среде нету статических классов, которые были бы доступны отовсюду
Re[17]: Инициализация приложения - внедрение зависимостей в
От: zelenprog  
Дата: 14.11.23 06:26
Оценка:
V>>·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>>Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.
·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.

Это будет какая-то одна "глобальная" Фабрика?
Или надо сделать много фабрик — по фабрике на каждую зависимость?
Re[21]: Инициализация приложения - внедрение зависимостей в
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.11.23 06:50
Оценка:
Здравствуйте, ·, Вы писали:

·>Ну, неужели нельзя писать ASP.NET приложение в основе которого нет контейра?

Да, DI — часть ASP.NET
Re: Инициализация приложения - внедрение зависимостей в DDD
От: zelenprog  
Дата: 14.11.23 07:41
Оценка:
Вынесу обсуждение следующего момента в отдельную ветку.

V>>·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.

V>>Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.
·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.

Это будет какая-то одна "глобальная" Фабрика?
Или надо сделать много фабрик — по фабрике на каждую зависимость?

Прочитал по этой проблеме вот эту статью:
https://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html

Там говорится, что wiring-код — это не решение проблемы, так как проблема просто выносится на уровень выше.
Так как вызывающий код становится зависимым от фабрики. Не понятно как инициализировать поведение фабрики так, чтобы она в этом месте создала нужный экземпляр объекта.
Именно поэтому и пришли к контейнерам.

Вот цитата из статьи:

... this is the core of the problem. By having multiple services in your system and multiple dependencies between various classes, this approach would end up in an object graph where each class depends on all possible services because possibly one of its dependant classes (or the class two, three or more nodes away in the dependency graph) depends on it!

Can you see it? You just can’t rethrow the responsibility to satisfy class dependencies to the client of the class because the client has its clients and they have their clients, too. The sole point of writing this entry is to show how to stop this madness of endless explicit dependencies which would flood your system.

...

And to cope with the issue we are going to introduce a factory. The factory will let its clients to create instances of the service. But we don’t want a concrete factory as it would end up with one, specific way of providing instances. Instead, we want the factory to be parametrized. We want a concrete implementation of the factory to be provided for the system.


В итоге все равно приходим к тому, что нужна какая-то глобальная переменная, в которой все это "настраивается".
Верно?
Re[18]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 14.11.23 09:26
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>·>Чё? wiring-код ничего не вызывает, кроме конструкторов (ну ладно, ещё может билдеры сложных компонент). Вызовы логики происходят внутри связываемых компонент и ни в wiring-коде, ни в конфиге фреймворка их быть не должно. Т.е. в wiring-коде эту фабрику не надо использовать — её надо только создать и передать конструкторам других компонент.

Z>Это будет какая-то одна "глобальная" Фабрика?
Z>Или надо сделать много фабрик — по фабрике на каждую зависимость?
Нет, конечно. Фабрика в данном случае — для создания контекста запроса.
Читай как и для чего применяется https://en.wikipedia.org/wiki/Factory_method_pattern
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 14.11.2023 9:29 · . Предыдущая версия .
Re[22]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 14.11.23 09:27
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>·>Ну, неужели нельзя писать ASP.NET приложение в основе которого нет контейра?

G>Да, DI — часть ASP.NET
Сочувствую. Даже на Spring можно писать нормально, без использования IoC-контейнера.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[23]: Инициализация приложения - внедрение зависимостей в
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.11.23 10:03
Оценка:
Здравствуйте, ·, Вы писали:

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


G>>·>Ну, неужели нельзя писать ASP.NET приложение в основе которого нет контейра?

G>>Да, DI — часть ASP.NET
·>Сочувствую. Даже на Spring можно писать нормально, без использования IoC-контейнера.
Не очень понято что значит "нормально"? Как передавать общий функцонал в разные компоненты? Синглтонам?
Re[24]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 14.11.23 13:31
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>·>Ну, неужели нельзя писать ASP.NET приложение в основе которого нет контейра?

G>>>Да, DI — часть ASP.NET
G>·>Сочувствую. Даже на Spring можно писать нормально, без использования IoC-контейнера.
G>Не очень понято что значит "нормально"? Как передавать общий функцонал в разные компоненты? Синглтонам?
Через параметры конструктора же. Просто явно, с проверкой компилятором, а не магией контейнера.
var commonDb = new Database(config);
var myBusinessObject1 = new MyBusiness1(commonDb);
var myBusinessObject2 = new MyBusiness2(commonDb, config);
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[25]: Инициализация приложения - внедрение зависимостей в
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.11.23 14:10
Оценка:
Здравствуйте, ·, Вы писали:

G>>Не очень понято что значит "нормально"? Как передавать общий функцонал в разные компоненты? Синглтонам?

·>Через параметры конструктора же. Просто явно, с проверкой компилятором, а не магией контейнера.
·>
·>var commonDb = new Database(config);
·>var myBusinessObject1 = new MyBusiness1(commonDb);
·>var myBusinessObject2 = new MyBusiness2(commonDb, config);
·>

Это пусть в никуда. Параметров станет слишком много раньше чем вы рассчитываете, а добавление сервиса станет адом.
Собственно поэтому и появились синглтоны в плюсах, а в языках с рефлексией и метаданными — DI.
Re: Инициализация приложения - внедрение зависимостей в DDD
От: Разраб  
Дата: 14.11.23 14:22
Оценка:
Здравствуйте, zelenprog, Вы писали:


Z>Но там используется незнакомая мне технология.


Z>Как правильно надо сделать?


https://smarly.net/dependency-injection-in-net
https://fsharpforfunandprofit.com/posts/dependencies/

а вообще, да, в самом простом исполнении: апп держит ссылки на все модули, модули через апп могут найти(по имени, типу и т.п.) нужный модуль.
я так делал на C# работало как часы.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[26]: Инициализация приложения - внедрение зависимостей в
От: · Великобритания  
Дата: 14.11.23 14:27
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Это пусть в никуда. Параметров станет слишком много раньше чем вы рассчитываете,

Это путь надёжного кода. А что плохого в большом количестве параметров? Хорошо в том, что код проверяется компилятором, удобно навигируется в IDE и даже если вдруг понадобилось — проходится отладичком и т.п.

G>а добавление сервиса станет адом.

Не станет. С чего вдруг? Хотя если у вас у каждого сервиса десятки зависимостей, то да.. Но это не "станет адом", а покажет какой же у вас ад в архитектуре.

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

Синглтоны появились как логическое продолжение глобальных переменных, думаю из тех времён, когда локальные переменные ещё не придумали.
Ты тоже путаешь DI и IoC-конейнер. DI — нужен и ему не нужна рефлексия. Мой код выше — с DI. IoC-конейнер — не нужен.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 14.11.2023 14:28 · . Предыдущая версия .
Re[27]: Инициализация приложения - внедрение зависимостей в
От: Разраб  
Дата: 14.11.23 14:33
Оценка:
Здравствуйте, ·, Вы писали:

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


G>>Это пусть в никуда. Параметров станет слишком много раньше чем вы рассчитываете,

·>Это путь надёжного кода. А что плохого в большом количестве параметров?

Зачему, что параметр может быть один(типа конекста). кложуристы так любят делать.
их хеш-мапа форсит так делать, ибо легко ключики добавляются.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.