Pull to refresh

Comments 15

Пожалуйста, не растягивайте картинки с текстом, а еще лучше примеры кода тоже текстом выкладывать.
Около года ждал Dagger2. Когда вышел релиз, с радостью начал выпиливать Roboguice и переводить проекты на даггер. Чем дальше шло дело, тем сильнее я чесал затылок. Для лучшей библиотеки по инжекции все настраивается крайне топорно. Писать inject(Xyz) для каждого(!) класса. Из коробки нельзя подменить провайдера (в тестах например), только через костыли. Обращение к сгенерированному коду. Все уже не вспомню.

Поэтому я решил написать свой DI фреймфорк (http://jeta.brooth.org/guide/inject.html) с покером и без рефлекции. И таки написал. Все работает, расширяется и удобно. Теперь чешу затылок, или я чего не понимаю или они.
Вообще, когда мы говорим о рефлекшене в DI, я думаю мы подразумеваем нахождение элементов с аннотаций @Inject используя Java Reflection API, не Class.forName(). Потом, ClassForNameMetasitory не основной класс библиотеки, скорее на всякий случай, в документации его нет. Тем не менее, основной класс-metasitory — MapMetasitory, но он тоже использует c Class.forName(). Но, если вопрос принципиальный, то можно и это обойти просто создав сгенерированный MapMetasitoryContainer как в статье создается DaggerAppComponent.
Хотя, при всей моей не любви в рефлекции, я не вижу ничего плохого в вызове Class.forName(), тем более один раз при старте.

Class.forName() печален тем, что надо исключать классы из обфускации, в остальном мне тоже не особо принципиально.


Про Dagger 2: мне нравится то, как он ложится в концепцию языка и делает DI не меташтукой, а полноценными и понятными сущностями, которые легко подменять при тестировании и интегрировать в разные места приложения.

Я не согласен с тем что зависимости легко подменять, по крайней мере в версии 1.0. Мне приходилось оборачивать все провайдеры в отдельный класс и передовать его (или подменять тестовым) в модуль:

@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

Спасибо за диалог) я думаю хватит. Если будут вопросы по библиотеке, ответы должны быть на сайте. Удачи с любой DI!
что если вам нужно проинжектить класс с разными скопами?


Это как?
Скопы (по крайней мере в Android), могут быть только вложенными, т.е. вы не можете проинжектить класс с двумя скопами. Вы можете вынести его в вышестоящий скоп.
А почему не использовали dagger от Square? В нем можно «оверайдить» модули, т.е. легко подменять зависимости (кроме, как в тестах этого и не нужно). Правда, с использованием того же рефлекшен, который для Вас не является критическим аргументом.
Честно, я особо не знаком с dagger1. Отказался от него на фазе research. Как минимум, тут тоже нужно перечислять все классы которые я собираюсь инжектить. И для меня критично использование рефлекшена, обратного я не говорил. Ну и кончено, мысль от том что гугл собрался переписать этот фреймфорк намекала что с ним не все хорошо)
Sign up to leave a comment.