2016-03-18 23 views
12

Ero piuttosto pigro e usavo quasi tutte le iniezioni sul campo. Stavo solo fornendo un costruttore vuoto, inserisco i miei campi @Inject, tutto sembrava bello e semplice. Comunque l'iniezione sul campo ha i suoi compromessi, quindi ho escogitato alcune semplici regole che mi aiutano a decidere quando usare il campo e quando usare le iniezioni del costruttore. Apprezzerò qualsiasi feedback se c'è un errore nella mia logica o se hai ulteriori considerazioni da aggiungere.Daga 2: quando utilizzare le iniezioni del costruttore e quando utilizzare le iniezioni sul campo?

Prima qualche chiarimento al fine di essere sulla stessa pagina:

iniezione Costruttore:

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

Lo stesso con il campo di iniezione:

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

    @Inject 
    AppPrefs appPrefs; 

Regola 1: deve utilizzare campo iniezione se non controllo la creazione dell'oggetto (pensa Attività o Frammento in Android). Se alcuni framework (non a prova di Dagger) creano il mio oggetto e me lo gestiscono non ho altra scelta che iniettarlo manualmente dopo aver ricevuto l'istanza.

Regola 2: DEVE utilizzare l'iniezione del costruttore se la classe è/può essere utilizzata in un altro progetto che non utilizza Dagger 2. Se gli altri progetti non usano Dagger, non possono usare DI, quindi l'utente deve creare l'oggetto "vecchio" utilizzando new.

Regola 3: Iniezione PREFER del costruttore quando si lavora con le gerarchie di classi perché è più semplice creare test di unità.

Chiarificazione:

Considerando la seguente struttura che utilizza l'iniezione campo:

package superclass; 

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

.

package differentpackage; 

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

Quando sto creando unit test per SubClass nella directory test/java/differentpackage non ho altra scelta, ma per far apparire l'intera infrastruttura DI al fine di essere in grado di iniettare il HttpClient. Al contrario, se stavo usando l'iniezione del costruttore in questo modo:

public class SuperClass { 
    private final HttpClient mHttpClient; 

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

nel mio test di unità che potevo semplicemente:

HttpClient mockHttp = mock(HttpClient.class); 

Subclass tested = new Subclass(mockHttp); 

// tests 

Quindi, in pratica ora sono in un altro estremo: tendo a fare affidamento soprattutto su Iniezioni del costruttore e utilizzare le iniezioni sul campo solo quando si applica la "Regola 1". L'unico 'problema' che ho con il costruttore inietta è che per le classi di 'fine' costruttori a volte diventano abbastanza sovraccaricati con i parametri e guardano prolisso e brutto come questo:

@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 
        ) { 

Ragazzi, quali sono le regole per scegliere tra costruttore e campo inietti? Mi manca qualcosa, ci sono errori nella mia logica?

+0

https://stackoverflow.com/questions/39207845/android-dagger-2-inject-versus-provides Guarda anche questo, offre una buona visione –

risposta

5

Utilizzare l'iniezione del costruttore. se non puoi, usa l'iniezione di proprietà.

La regola 1 sembra ok, come le decorazioni o gli attributi è possibile utilizzare l'iniezione di proprietà (campo).

La regola 2 sembra ok, perché chi usa la tua classe deve seguire il tuo costruttore. Forse non sanno che devono intessere anche la tua proprietà.

Regola 3 Non è solo un bene per il test unitario. È buono per applicare la responsabilità unica. È più facile vedere il tuo oggetto grafico. Altrimenti lo nasconderai con la proprietà.

Se veniamo nella tua domanda, sì, ci sono molti parametri nel tuo costruttore. Ma la soluzione non è un'iniezione di proprietà. Puoi refactoring il tuo codice e utilizzare aggregate services