Здравствуйте, 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 контейнер
Значит я не понял твою мысль здесь...