2016-03-18 18 views
12

Byłem trochę leniwy i używałem prawie całkowicie zastrzyków polowych. Właśnie dostarczałem pustego konstruktora, umieszczałem pola @Inject, w których wszystko wyglądało ładnie i prosto. Jednak wtrysk polowy ma swoje kompromisy, więc wymyśliłem kilka prostych zasad, które pomagają mi zdecydować kiedy użyć pola i kiedy użyć zastrzyków konstruktora. Będę wdzięczny za każdą informację zwrotną, jeśli w mojej logice jest błąd lub masz dodatkowe uwagi do dodania.Sztylet 2: Kiedy używać zastrzyków konstruktorskich i kiedy używać zastrzyków polowych?

Pierwsze pewne wyjaśnienia, aby być na tej samej stronie:

wtrysk Konstruktor:

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

samo z wtryskiem polu:

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

    @Inject 
    AppPrefs appPrefs; 

Zasada 1: musi użyć pola wtrysku, jeśli nie kontroluję tworzenia obiektu (pomyśl Aktywność lub Fragment w Androidzie). Jeśli jakaś struktura (nie znająca sztyletu) tworzy mój obiekt i obsługuje go, nie mam innego wyboru, jak wstrzyknąć go ręcznie po otrzymaniu instancji.

Reguła 2: MUSI używać zastrzyku konstruktora, jeśli klasa jest/może być używana w innym projekcie, który nie używa Dagger 2. Jeśli inne projekty nie używają Daggera, nie mogą używać DI, więc użytkownik musi utworzyć obiekt "w starym" stylu przy użyciu new.

Reguła 3: PREFERUJ zastrzyk konstruktora podczas pracy z hierarchiami klas, ponieważ łatwiej jest tworzyć testy jednostkowe.

Wyjaśnienie:

Biorąc pod uwagę następujące struktury, która wykorzystuje iniekcji pola:

package superclass; 

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

.

package differentpackage; 

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

Kiedy tworzę testów jednostkowych dla SubClass w katalogu test/java/differentpackage mam innego wyboru, aby przywołać całą infrastrukturę DI aby móc wstrzyknąć HttpClient. W przeciwieństwie do tego, gdybym był przy użyciu konstruktora wtrysku tak:

public class SuperClass { 
    private final HttpClient mHttpClient; 

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

w moim badanej jednostki mogłem po prostu:

HttpClient mockHttp = mock(HttpClient.class); 

Subclass tested = new Subclass(mockHttp); 

// tests 

Więc w zasadzie teraz jestem w drugiej skrajności: staram się polegać głównie na iniekcje konstruktorów i używać zastrzyków polowych tylko wtedy, gdy ma zastosowanie "Zasada 1". Jedyny „problem”, że mam z konstruktora wstrzykuje jest to, że na zajęcia „end” konstruktorzy czasem stać się bardzo przeciążony z parametrami i wyglądają rozwlekły i brzydkie tak:

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

Guys, jakie są zasady do wybierać między konstruktorem a zastrzykami polowymi? Brakuje mi czegoś, czy są jakieś błędy w mojej logice?

+0

https://stackoverflow.com/questions/39207845/android-dagger-2-inject-versus-provides Spójrz na to również, zapewnia dobry wgląd –

Odpowiedz

5

Użyj wtrysku konstruktora. jeśli nie możesz, użyj wtrysku własności.

Zasada 1 wydaje się być w porządku, podobnie jak dekoracje lub atrybuty, których można użyć Wstrzyknięcia właściwości (pola).

Zasada 2 wydaje się być w porządku, ponieważ kto korzysta z klasy, musi podążać za swoim konstruktorem. Mogą nie wiedzieć, że muszą również intilizować swoją własność.

Reguła 3 To nie jest po prostu dobre dla testu jednostkowego. To jest dobre dla stosowania pojedynczej odpowiedzialności. Łatwiej jest zobaczyć wykres obiektu. W przeciwnym razie ukryjesz go za pomocą właściwości.

Jeśli przyjdziemy na twoje pytanie, tak, istnieje wiele parametrów w twoim konstruktorze. Ale rozwiązanie nie jest wtryskiem nieruchomości. Możesz zmienić kod i użyć aggregate services