2016-03-18 4 views
12

Я был вроде ленив и использовал почти полностью полевые инъекции. Я просто предоставлял пустой конструктор, поместил поля @Inject, все выглядело красиво и просто. Однако у полевых инъекций есть свои компромиссы, поэтому я разработал несколько простых правил, которые помогают мне решить, когда использовать поле и когда использовать инъекции конструктора. Я буду признателен за любые отзывы, если в моей логике есть ошибка или у вас есть дополнительные соображения для добавления.Кинжал 2: Когда использовать инъекции конструктора и когда использовать полевые инъекции?

Сначала некоторые разъяснения для того, чтобы быть на той же странице:

инъекции Constructor:

@Inject 
public SomeClass(@Named("app version") String appVersion, 
        AppPrefs appPrefs) {... 

То же самое с инъекцией поля:

public class SomeClass { 
    @Inject 
    @Named("app version") String mAppVersion; 

    @Inject 
    AppPrefs appPrefs; 

Правило 1: ДОЛЖЕН использовать поле если я не контролирую создание объекта (подумайте об активности или фрагменте в Android). Если какая-то (не-кинжалная) структура создает мой объект и обрабатывает его для меня, у меня нет выбора, кроме как ввести его вручную после получения экземпляра.

Правило 2: ДОЛЖНО использовать инъекцию конструктора, если класс используется/может использоваться в другом проекте, который не использует кинжал 2. Если другие проекты не используют кинжал, они не могут использовать DI, поэтому пользователю необходимо создать объект «старый» способ, используя new.

Правило 3: Встраивание конструктора PREFER при работе с иерархиями классов, поскольку легче создавать модульные тесты.

Пояснение:

Учитывая следующую структуру, которая использует инъекции поля:

package superclass; 

public class SuperClass { 
    @Inject 
    HttpClient mHttpClient; 
    ... 
} 

.

package differentpackage; 

public class SubClass extends SuperClass { 
    public SubClass() { 
    } 
} 

Когда я создаю модульное тестирование для SubClass в каталоге test/java/differentpackage У меня нет выбора, кроме как поднять всю инфраструктуру DI для того, чтобы иметь возможность впрыскивать HttpClient. В отличие от этого, если бы я использовал инъекции конструктора, как это:

public class SuperClass { 
    private final HttpClient mHttpClient; 

    @Inject 
    public SuperClass(HttpClient httpClient) { 
     mHttpClient = httpClient; 
    } 
} 

в моей модульного теста я мог бы просто:

HttpClient mockHttp = mock(HttpClient.class); 

Subclass tested = new Subclass(mockHttp); 

// tests 

Так в основном сейчас я нахожусь в другой крайности: я, как правило, полагаются в основном на инъекции конструктора и использовать полевые инъекции только тогда, когда применяется «Правило 1». Единственная «проблема», что у меня есть с конструктором впрыскивает является то, что для классов «конец» Конструкторы иногда становятся весьма перегружены с параметрами, и они выглядят многословным и уродливые, как это:

@Inject 
public ModelMainImpl(@Named("app version") String appVersion, 
        AppPrefs appPrefs, 
        LoginPrefs loginPrefs, 
        @ForApplication Context appContext, 
        NetworkInfoProvider networkInfoProvider, 
        AndroidEventPoster androidEventPoster, 
        Session session, 
        ForgeExchangeManager exchangeManager, 
        HttpFunctionality httpFunctionality, 
        @Named("base url") String baseUrl, 
        @Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer 
        ) { 

Ребята, каковы ваши правила в выбирать между конструктором и полевыми инъекциями? Я что-то упускаю, есть ошибки в моей логике?

+0

https://stackoverflow.com/questions/39207845/android-dagger-2-inject-versus-provides Посмотрите на это, также хорошо понимая –

ответ

5

Использование инъектора конструктора. если вы не можете, используйте инъекцию свойств.

Правило 1 выглядит нормально, например, украшения или атрибуты, которые вы можете использовать для инъекции Property (field).

Правило 2 выглядит нормально, потому что кто использует ваш класс, он должен следовать за вашим конструктором. Возможно, они не знают, что они тоже должны замаскировать вашу собственность.

Правило 3 Это не только хорошо для модульного испытания. Это полезно для применения Single Responsibilty. Легче увидеть ваш граф объекта. В противном случае вы скроете его с помощью свойства.

Если мы примем ваш вопрос, да, у вас есть много параметров в вашем конструкторе. Но решение не относится к оборудованию. Вы можете реорганизовать свой код и использовать aggregate services

Смежные вопросы