Comments 15
Поэтому я решил написать свой DI фреймфорк (http://jeta.brooth.org/guide/inject.html) с покером и без рефлекции. И таки написал. Все работает, расширяется и удобно. Теперь чешу затылок, или я чего не понимаю или они.
@Inject
используя Java Reflection API, не Class.forName()
. Потом, ClassForNameMetasitory
не основной класс библиотеки, скорее на всякий случай, в документации его нет. Тем не менее, основной класс-metasitory — MapMetasitory
, но он тоже использует c Class.forName()
. Но, если вопрос принципиальный, то можно и это обойти просто создав сгенерированный MapMetasitoryContainer
как в статье создается DaggerAppComponent
.Хотя, при всей моей не любви в рефлекции, я не вижу ничего плохого в вызове
Class.forName()
, тем более один раз при старте. Class.forName() печален тем, что надо исключать классы из обфускации, в остальном мне тоже не особо принципиально.
Про Dagger 2: мне нравится то, как он ложится в концепцию языка и делает DI не меташтукой, а полноценными и понятными сущностями, которые легко подменять при тестировании и интегрировать в разные места приложения.
@Module public class RestModule { protected final RestModuleProviders providers; public RestModule(RestModuleProviders providers) { this.providers = providers; } @Provides RestManager provideRestManager() { return providers.provideRestManager(); } }
Как это делается в Jeta:
@MetaEntity(ext = RestManager.class) class TestRestManager extends RestManager { //... }
И вы меня простите конечно, но о каком удобвстве можно говорить, когда вам предлагают писать
inject(MyThousandthClass c)
для каждого класса где вы используете инжекцию?В остальном в Jeta DI все соблюдено, никакой мета-магии, все классы сгенерированны, читаемы и легко дебажатся. По возможности все ошибки проверяются в compile-time, и все зависимости, провайдеры и скопы определяются там же.
Так в том то и дело, что я могу отнаследовать или замокать модуль и переопределить метод @Provides
, это просто класс, который провайдит что-то, и он никуда от меня не спрятан.
И вы меня простите конечно, но о каком удобвстве можно говорить, когда вам предлагают писать inject(MyThousandthClass c) для каждого класса где вы используете инжекцию?
1) Так сразу видно что куда инжектится, понятен скоуп зависимостей и вот это всё.
2) Интерфейс @Component
легко подменяется в тестах на тестовую реализацию/мок.
Ваш пример:
@MetaEntity(ext = RestManager.class)
class TestRestManager extends RestManager {
//...
}
Не понятно для какой области проекта будет использован TestRestManager
, что если у TestRestManager
есть параметры, про которые DI не знает? С даггером можно написать этот код руками (а можно и не писать) и сделать всё что нужно.
С Dagger1 я воевал, читал исходники, искал пути внедрения нужного мне поведения (в основном для тестов) и тд и тп. В исходники Dagger 2 не залазил ни разу тк всё что нужно можно делать из "юзерспейса" и даггер просто будет использовать тот код, который я ему подсуну, для меня это библиотека для DI, наиболее натурально встраивающаяся в язык .
замокать модуль
Если у Вас только тестовый модуль то вы конечно можете замокать. У меня проект где провайдеры могут быть заменены не только в тестах но и в расширениях (вся логика приложения находится в библиотеки (aar), а уже на ее основе создаются приложения(apk))
Так сразу видно что куда инжектится, понятен скоуп зависимостей и вот это всё.
что если вам нужно проинжектить класс с разными скопами?
Не понятно для какой области проекта будет использован
Тут все описано. Скоп можно указать как аргумент аннотации
@MetaEntity(ext = RestManager.class, scope=AppScope.class)
, а можно указать дефолтный в настройках.что если у TestRestManager есть параметры, про которые DI не знает?
Простите, о каких параметрах речь?
для меня это библиотека для DI, наиболее натурально встраивающаяся в язык
На самом деле рад что Вас все устраивает. Как в анекдоте, «Если все работает — #%& трогать»
Если у Вас только тестовый модуль то вы конечно можете замокать. У меня проект где провайдеры могут быть заменены не только в тестах но и в расширениях (вся логика приложения находится в библиотеки (aar), а уже на ее основе создаются приложения(apk))
Тут Dagger 2 вроде палок в колёса не вставит, можно акцептить модули снаружи — из конкретных приложений.
Простите, о каких параметрах речь?
Если для работы TestRestManager
нужны будут объекты, о которых DI не знает, как он создаст инстанс TestRestManager
?
// P.S. я ни в коем случае не наезжаю и не осуждаю ваш DI, со стороны вроде ок, эдакий микс Dagger 1 и Dagger 2, разве что слишком часто встречается Meta
в названиях классов, что смущает и сразу думаешь про XML :D
что если вам нужно проинжектить класс с разными скопами?
Это как?
Скопы (по крайней мере в Android), могут быть только вложенными, т.е. вы не можете проинжектить класс с двумя скопами. Вы можете вынести его в вышестоящий скоп.
Dagger 2. Лечим зависимости по методике Google