Здравствуйте, VladD2, Вы писали:
VD>Так за все приходится платить. Разбираться в коде созданном на базе большинства DI действительно сложнее. По уму нужно делать статический DI, который резолвил бы зависимости во время компиляции. Это сняло бы много проблем. Но современные мэйстрим-языки на это не особо рассчитаны. Вот и появляются строковые конфиги. Ошибки при загрузке. Непонимание того почему тут подсунули некоторый тип, а не иной. И т.п.
Что значит "статический DI" ? Он из коробки такой, а ломает его IoC, который вообще может из файла конфигурироваться.
Здравствуйте, Sharov, Вы писали:
S>Что значит "статический DI" ? Он из коробки такой, а ломает его IoC, который вообще может из файла конфигурироваться.
Из коробки его нет. Все DI — это IoC. Обратное не верно. Не пори чушь. Причем обязанности поддерживать конфигурацию на текстовых файлах у них нет. Это твои домыслы. Это не более чем особенность реализации.
По ходу ты не понимаешь того что лежит за DI. Основная фича DI — это расчет графа зависимостей и автоматическое создание объектов в последовательности зависимостей. Так вот этот процесс можно осуществлять как в рантайме, так и во время компиляции. Последнее дает больше контроля и избавляет от кучи проблем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Из коробки его нет. Все DI — это IoC. Обратное не верно. Не пори чушь.
Это почему не верно?
VD>Причем обязанности поддерживать конфигурацию на текстовых файлах у них нет. Это твои домыслы. Это не более чем особенность реализации.
А если именно конфигурационные файлы используются для настройки графа?
VD>По ходу ты не понимаешь того что лежит за DI. Основная фича DI — это расчет графа зависимостей и автоматическое создание объектов в последовательности зависимостей. Так вот этот процесс можно осуществлять как в рантайме, так и во время компиляции. Последнее дает больше контроля и избавляет от кучи проблем.
Все именно так, согласен. Вот только этих графов может быть несколько, а не один. Проверить можно, наверное, только
если sealed классы используются, иначе это будет трудновато -- перебирать все возможные варианты, что может быть
долго.
Здравствуйте, VladD2, Вы писали:
VD>По ходу ты не понимаешь того что лежит за DI. Основная фича DI — это расчет графа зависимостей
Мде уж. Это у тебя полная путаница. Основная фича DI — это отделить конструирование компонентов от их использования.
VD>и автоматическое создание объектов в последовательности зависимостей.
А вот это уже называется автоматический DI, осуществляемый неким фреймоворком. Можно делать ручной DI. Я за него и топлю.
VD>Так вот этот процесс можно осуществлять как в рантайме, так и во время компиляции. Последнее дает больше контроля и избавляет от кучи проблем.
Т.е. тебе нужен ручной DI, фреймворки в топку.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Министр Промышленности, Вы писали:
МП>Они затрудняют распутывание кода,
Да.
МП>понижают гибкость автоматического рефакторинга (в частности ReSharper-ом)
Да.
МП>и это не перекрывается гибкостью подстановки mock-объектов
Моки тут вообще побоку.
МП>кто-то может популярно расписать преимущества либо природу явления популярности?
Главное преимущество — открытый интерфейс расширения. Т.е. если у тебя:
Расширяемая без перекомпиляции система
Поверхность расширения большая и постоянно существенно изменяющаяся
Есть потребность в том, чтобы кто то со стороны мог сделать не просто свое расширение в существующий extension point, но и добавить собственный extention point
то при попытке реализовать эти требования более менее качественно ты все равно придешь к чему то вроде DI контейнера.
Ну а популярность среди ориентированной на модность и молодежность аудитории объясняется просто — DI позволяет быстрее лопатить код, а морочится с его поддержкой в дальнейшем — это уже не модно и не молодежно.
Здравствуйте, gandjustas, Вы писали:
МП>>но обнаруживаю ярых адептов этого всего. МП>>уже и в вакансиях суют такое требование G>Уже? Доброе утро. Погугли что означает D в SOLID
Dependency Inversion. Ты бы сам погуглил сперва, а то вышло как обычно.
Здравствуйте, СвободуАнжелеДевис, Вы писали:
САД>но вот тебе пример из недавнего с нашего проекта. САД>есть сервис, пусть будет MyService, который делает достаточно долгий запрос за статическими данными. САД>есть интерфейс, понятное дело, IMyService. САД>этот сервис используется в большом количестве мест проекта. через интеферйс, понятное дело, не напрямую создавая инстанс. САД>запустив нагрузочное тестирование, мы поняли, что мы упираемся в производительность этого сервиса, и если бы мы закешировали данные, получили бы приличный прирост производительности. САД>дальше, мы создали над MyService обычный декоратор, аля MyServiceWithCache, который так же реализует IMyService интерфейс. всё что там нужно было, поменять регистрацию в DI в одном месте. САД>дальше, везде подхватилась новая реализаций, реализация нашего декоратора. приложение взлетело.
Круто, но все тоже самое можно было бы сделать без DI, заменив его на банальную фабрику.
Здравствуйте, VladD2, Вы писали:
VD>Иногда DI заставляет вводить лишние абстракции. Скажем вводить интерфейсы там где у них никогда не будет более одной реализации.
DI контейнеры такого совсем не требуют.
VD> Код завязанный на коркретный DI хрен перенесешь в другой проект.
Ну это если DI контейнер криво спроектирован (да, большая часть как раз такие, но, к счастью, не все). Если же он спроектирован нормально (например родной МСовский), то переносить надо только код регистрации компонентов, а он обычно сравнительно небольшой и тривиальный по структуре.
VD> Иногда DI приводит к тому, что хрен поймешь, что за тип к тебе в реальности приехал и где та магия, которая к этому привела.
Не иногда, а очень часто.
VD>Многие проблемы DI происходят от того, что DI-фрэймворки динамические, создают граф зависимостей в рантайме. Если бы зависимости разрешались бы статически
Здравствуйте, VladD2, Вы писали:
МП>>Они затрудняют распутывание кода, VD>Есть такое. Но это скорее проблема реализации DI.
Не, это принципиальная проблема, когда код инициализации никак статически не связан с кодом использования.
МП>>понижают гибкость автоматического рефакторинга (в частности ReSharper-ом) VD>А вот это точно полная чушь. Прекрасно рефакторю код напичканный DI с помощью Райдера.
Не так уж и прекрасно. Найти конкретную реализацию в конкретном месте использования не всегда просто, а иногда возможно только в рантайме.
Здравствуйте, Философ, Вы писали:
Ф>Нет не принимается: абстрактная фабрика точно так же уменьшает связность и развязывает зависимости. Ключ здесь — использование интерфейсов вместо конкретных классов.
Dependency Injection вовсе не обязует использовать интерфейсы.
Здравствуйте, Sharov, Вы писали:
S>·>Мде уж. Это у тебя полная путаница. Основная фича DI — это отделить конструирование компонентов от их использования. S>Без графа зависимостей этого не сделаешь? Но да, это не главная фича, а компонент этой фичи.
Не знаю что ты конкретно под этим подразумеваешь, но вот это
и есть граф зависимостей: dbContext зависит от dbOptions, mainService зависит от dbContext и т.п.
Притом, если использовать исключительно Constructor Injection, то у тебя гарантированно получится DAG — а это круто с т.з. красивости архитектуры.
Только он нарисован вручную, в момент написания кода, а не автоматически сгенерирован в runtime.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Ночной Смотрящий, Вы писали:
НС> Тё>DI это довольно старый паттерн. НС> Паттерн это Dependency Inversion. А Dependency Injection это несколько иное.
Ты по-моему тоже попутал Dependency Inversion это Principle, а не pattern.
S>Как-то продивинуто . Зачем тут полноту по Тьюрингу поминать? Вся суть в том, что DI\IoC не предполагает S>явно создания объектов программистам, но иногда это необходимо.
Создать объекты можно безо всяких там DI/IoС.
Как уже было замечено выше, "контейнер" (или composition root) — это способ назвать код "конфигурацией" и вынести его туда, где тестировать его становится сложно, а значит, (барабаны), не нужно.
Был тут уже выше пример про то, что хочется назвать определенную сборку "продакшном", и под этим соусом избежать тестирования.
Здравствуйте, SkyDance, Вы писали:
S>>Как-то продивинуто . Зачем тут полноту по Тьюрингу поминать? Вся суть в том, что DI\IoC не предполагает S>>явно создания объектов программистам, но иногда это необходимо.
SD>Создать объекты можно безо всяких там DI/IoС. SD>Как уже было замечено выше, "контейнер" (или composition root) — это способ назвать код "конфигурацией" и вынести его туда, где тестировать его становится сложно, а значит, (барабаны), не нужно.
SD>Был тут уже выше пример про то, что хочется назвать определенную сборку "продакшном", и под этим соусом избежать тестирования.
Это все хорошо, но только для небольших проектов, если проект сложный, то и способ сборки частей будет чуть хитрее чем простая передача экземпляра в конструктор.
Там могут быть существенны и скорость компиляции и возможность замены модулей...
AA>Там могут быть существенны и скорость компиляции и возможность замены модулей...
Вот над этим и работайте. Ускоряйте компиляцию, современные билд-системы очень даже хорошо с этим справляются. Даже безо всякой распределенной магии, просто путем сборки только тех зависимостей, которые изменились.
А если у вас есть такая банальщина как key-value storage, вы просто можете готовые build artifacts туда складывать, как mapping sha(SourceFile) -> BuildArtifact (примерно так работают bazel/buck/...).
Почему именно там?
M> где куча разнообразной логики которая имеет свойство часто меняться, это приводит к тому что меняются сигнатуры конструкторов, их зависимости и т.д.
И? Если сигнатуры поменялись, тебе их все равно где то придется поправить, хоть с DI, хоть без.