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"
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.