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