Здравствуйте, ·, Вы писали:
·>Здравствуйте, vmpire, Вы писали:
V>>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
V>>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>>В любом случае эта проблема не зависит от наличия или отсутствия DI
·>Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
·>Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка".
Да, именно это
·>Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в ·>которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
В данном подвопросе было не про гибкость, а про то, что в обоих вариантах можно забыть что-нибудь инициализировать и будет падение в рантайме.
V>>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
V>>Как я писал уже в ответе ТС, простейший вариант -
·>Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
Результат этого выражения нужно где-то хранить. Вот для этого поля и классы.
V>>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.
·>Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
Специально попытался найти официальное определение — не нашёл.
Поэтому я понимаю буквально: IoC-контейнер — контейнер, хранящий объекты, используемые для реализации IoC
V>>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.
·>Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
Ещё и не такой пишут, поверьте.
V>>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
·>Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
Потому, что Вы продолжаете цепляться к конкретному коду и не хотите понимать идею. А идея в том, что инициализация может быть сложной, иметь вложенные вызовы, внешние зависимости и т.п. И в этой реализации могут быть ошибки. В том числе и не обнаруживаемые компилятором. Или обнаруживаемые, но не ошибкой, а warningом, которые индусы игнорируют.
V>>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.
V>>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
·>Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
Ну как зачем? А как эту фабрику использовать? Эту Func<> ведь нужно как-то вызвать, правильно? А для этого присвоить переменной.
V>>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
·>О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
Вот с этим я согласен. Когда в контейнер начинают валить всё подряд — получается свалка.
V>>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
V>>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
·>Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
Это ровно то (второй пример), чем занимается DI фреймворк.
V>>Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
V>>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
·>wiring code — основан на DI тоже.
Это не важно, я про фреймворк. Если он внутри использует DI контейнер, то довольно сложно избежать его использования.