Re[9]: О "наивном" DI и об архитектурном бессилии
От: Tom Россия http://www.RSDN.ru
Дата: 02.09.16 11:26
Оценка:
·>SL. В подавляющем числе случаев он не нужен. Проблема — он делает зависимости неявными.
? Что такое SL?

·>[методы-инициализаторы и property injection. Проблема — добавляет в объект опасное состояние "создан, но не очень-то ещё создан".

Абсолютно согласен, зло злейшее. В 99% только Constructor Injection. Правда есть пару случаев когда из за "чужёго кривого дизайна" приходится использовать property injection но это исключение.

·>Магические строки. Ничем не лучше магических чисел.

Давай с самого начала, есть ощущение что ты не понимаешь откуда там при регистрации взялись строки. Есть 2 принципиально разных случая. Случай 1 — я хочу что бы в контейнере была зарегистрирована только одна реализация интерфейса X. В этом случае никаких строк ненадо, обычная регистрация. Если я хочу переопределить предыдущую регистрацию, например в тесте то я так же выполняю обычную регистрацию без каких либо имён ака строк. Но что делать если:
a) Я хочу зарегистрировать в контейнере 2 реализации одного и того же интерфейса. Как сказать контейнеру что я хочу не "перезаписать" предыдущую регистрацию а сделать их две. И более того, как эти 2 регистрации идентифицировать, как потом если вдруг надо зарезолвить конкретную регистарцию. Ведь иногда мне могут понадобиться все регистрации интерфейса аля IEnumerable<IFoo> а иногда нужно взять конкретную (таких случаев вагон). Вот для этого и придумали имена. Да конечно надо как то регистрации отличать друг от друга и ничего проще строк тут нету. Что бы эти строки перестали быть магическими — вынеси их в константу и используй эту константу как при регистарции так и при резолве.

·>Сканирование сборок. В подавляющем числе случаев он не нужен. Доставляет столько удовольствия исследовать что куда залетело и почему. Притом это можно исследовать только на запущенной системе в данном (часто prod) окружении.

Ничего не понимаю что куда залетело. В общем случае фича которая называется auto wire работает прекрасно. Регистрируешь только то что отличается от принятых в контейнере конвенций.

·>Циклические зависимости. С DI+CI сделать цикл невозможно. Заставляет аккуратнее подходить к архитектуре приложения, а не всякие lazy/PI, которые тебе циклы создадут на ура.

Эммм а где антипаттерн? И причём тут контейнеры с DI. Если у тебя циклические зависимости то это проблема не контейнера а проблема твоего дизайна. Но даже в этом случае контейнер может подставить тебе плечо, ты можешь резолвить Lazy<T> и фактически резолв будет сделан в момент использования.

Tom>>Вот тебе прмиер. Есть обьект IFoo. Ну или IPlugin для наглядности. Есть пара его реализаций, одна из них использует unmanaget ресурсы и требует реализации IDisposable а другая нет. Кроме как калечного решения в виде наследованияч IPlugin от IDisposable для ручного управления зависимостями я не вижу.


·>Не понял. Давай более конкретный пример. Вот код:

На стадии проектирования интерфейса и своей реализации интерфейса ты НЕ знаешь будут ли другие реализации которым может потребоваться очистка ресурсов. Это основная идея. В случае исполдьзования контейнера, обычно, на запрос создаётся так называемый child container который разрушается при окончании обработки запроса и который при разрушении вызовет Dispose у обьектов которые были в нём зарезолвлены. Причём он вызовет Dispose естественно вне зависимости от того унаследован интерфейс от IDsiposable или нет. В случае когда у тебя контейнера нет тебе надо либо самому писать такой функционал но это не возможно так как без контейнера нет единственного класса который контролирует время жизни всех обьектов. Либо наследовать интерфейс от IDisposable в тех местах где ты предпологаешь в реализациях может понадобится очистка ресурсов, но это жутко криво ибо во первых ты по сути не должен знать и не знаешь где очистка может понадобится а во вторых сам факт наследования от IDisposable это ад адский.


Tom>>·>Единственное для чего эти контейнеры могут быть хороши это всякое Assembly Scanning, но реально проектов, где это необходимо — очень мало.

Tom>>Контейнеры много чего могут но это бесполезно обьяснять человеку у которого в голове установка что они зло.
·>Но это всё не надо использовать. Контейнеры можно использовать для каких-то сложных случаев, только в довольно маленьком чётко отделённом контексте, в плагинном менеджере каком-нибудь например. Но пихать везде — антипаттерн.
Так, то что это вдруг антипатотерн — это придумал ты. Основная масса современных разработчиков с этим не согласна

Tom>>·>Зато полная поддержка компилятора и IDE. А неудобно только с непривычки.

Tom>>new это огромные трудности при написании тестов. Я про Integration тесты.
Tom>>Руками собирать всё дерево зависимостей? Вопрос нахера, если я 2-мя движениями мышки могу в тесте подменить любую зависимость.
·>Нет, просто пишешь классы-модули, которые делают wiring тестируемых поддеревьев зависимостей. И тестируешь именно их. Иначе интеграционные тесты тестируют тестовый wiring.
О чём и речь, без контейнера тебе надо собирать деревья зависимостей руками. Зачем это делать если это умеет делать контейнер.
Народная мудрось
всем все никому ничего(с).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.