Здравствуйте, ·, Вы писали:
·>Здравствуйте, vmpire, Вы писали:
V>>>·>Верно. А в нормальном wiring коде такие ошибки просто подсвечиваются красным как ошибка компиляции ещё в процессе набора кода.
V>>Это просто баланс интересов. Минимальное дублирование кода и отделение логики создания объектов ценой потенциальных ошибок в рантайме.
·>Дублирование ортогонально контейнеру. Можно и написать wiring код без дублирования, а можно надублировать конфигурацию контейра. Что кстати, мне нередко доводилось наблюдать — почти одинаковые конфигурации для тестов/прода; в итоге тесты работают, а прод падает, внезапно.
Вы точно не путаете проблему DI контейнера как такового с проблемой его инициализации из XML или JSON? XML/JSON это практически однозначно зло, кроме, может быть, очень редких специфичных случаев.
Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
А если они не в одном файле, то и wiring код может отличаться.
·>Никаких осязаемых преимуществ конкретно контейнер не даёт.
В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
V>>>·>Если ты умеешь избегать дублирование кода в принципе, то это же умение точно так же работает и для wiring-кода.
V>>Я как раз проникся. Как только мы в этом wiring коде отделяем логику создания объектов с целью его переиспользования от логики их связи, мы как раз и получаем самый обыкновенный DI контейнер, разве что статический.
·>Ну можно так выразиться, хотя неясно почему "контейнер", нет ничего контейнерного (словаря-то нет!). Это и есть хорошо, что статический. Динамика это в php и javascript, зачем это тащить в компилируемые ЯП — неясно.
Словарь — это всего лишь один из возможных механизмов реализации. Если контейнер не будет библиотекой для использования в произвольных проектах, а делается для одного раза, то словарь будет только лишним.
V>>Точнее, контейнером станет набор переменных, в которых лежат созданные объекты перед тем, как их связали.
V>>С семи же потенциальными проблемами рантайма(забыли создать объект, который потом пытаемся связать).
·>Подавляющее большинство связывания будет через Constructor Injection. Т.е. ты тупо не сможешь создать объект в коде не имея нужных ему зависимостей.
Пример:
ILogger myLogger = new MyCoolLogger();
IDatabase myDatabase = null;
switch (configuredDatabase) {
case "mysql": myDatabase = new MySqlDatabase(myLogger); break;
case "yoursql": myDatabase = new YourSqlDatabase(myLogger); break;
}
// Через 100 строчек кода
var myBusinessObject = new MyBusiness(myDatabase, myLogger);
По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>>Тут, правда, поможет новая фишка C# про nullable reference types, но только в не очень сложных случаях.
·>Ты видимо связывание через Property Injection? Тоже хак, который надо избегать.
Боже упаси, конечно, нет. Я про
вот это
V>>>>>и неудобен, когда нужно закодировать разное время жизни объектов и при этом создавать их по требованию.
V>>>·>Эээ... Фабрика/билдер?
V>>Ну и напишете вручную тот же код, который уже есть в DI фреймворке. И в чём тогда плюсы?
·>Что этот код явный и работает явно. И отлаживается как обычный код, и тестами покрывается, и стектрейсы явные и т.п.
Код явный — это, конечно, хорошо. Но с таким аргументом лучше вообще библиотеками не пользоваться, а то мало ли что там внутри. Впрочем, я лично знал человека, который писал свою реализацию списка на C# толко потому, что в своей реализации он понимает, как она работает.
При отладке и содержимое контейнера прекрасно видно. А в логах — не всё ли равно какой там будет класс, свой или библиотечный?
С трейсами то же самое.
Так что на мой взгляд оно эквивалентно.