Unity

Bardzo długo moim ulubionym kontenerem był Unity, mimo faktu, że dużo mądrych ludzi ze społeczności wieszało na nim psy. Dlaczego tak polubiłem Unity? Ponieważ powstawał na moich oczach. Znam go począwszy od wczesnych “zajawek” wypuszczanych przez grupę Patterns & Practices. Wcześniej nieco interesowałem się ich biblioteką ObjectBuilder, więc naturalnie moja uwaga przeszła na Unity. Byłem w stanie przeczytać i zrozumieć kod pierwszej wersji tego kontenera bez specjalnego wysiłku. Efekt tego był taki, że znam Unity jak własną kieszeń i wiem czego się po nim spodziewać.

To prawda, że pod względem ilości ficzerów Unity jest daleko w tyle za “wiodącymi” kontenerami, ale przez bardzo długi czas zupełnie mi to nie przeszkadzało.  W końcu jednak zaczęło…

Dlaczego nie Unity?

W projekcie, który aktualnie realizuję w końcu (co było do przewidzenia) pojawiła się potrzeba zastosowania kontenera DI. Było to w momencie tworzenia pierwszych testów integracyjnych. Struktura projektu oparta jest na kilku kluczowych interfejsach reprezentujących najważniejsze koncepcje, takie jak: czynność, proces (sekwencja czynności), reguła walidacji, czy reguła przepisywania. Tu pojawił się problem: chciałbym, aby rejestracja implementacji była w jakiś sposób zautomatyzowana — abym nie musiał rejestrować w kontenerze każdej kolejnej klasy. Niestety Unity (sam w sobie) nie pozwala na takie rzeczy. Czyżby czas na zmianę przyzyczajeń?

Jeśli nie Unity, to co?

Potrzebowałem czegoś, co jest w stanie zarejestrować automatycznie implementacje moich interfejsów na podstawie podanych reguł — konwencji. Wiele kontenerów obsługuje dziś takie scenariusze. W szczególności rozważałem dwa: Autofac oraz Castle Windsor. Spring.NET dyskwalifikuje niedojrzałość płynnego interfejsu konfiguracji. Wybrałem ostatecznie Autofaca. Dlaczego? Powodów jest kilka.

Po pierwsze i najważniejsze, Autofac pozwala mi zrealizować moje wymaganie. Kod konfigurujący kontener wygląda mniej-więcej tak:

private void RegisterActivities()
{
   RegisterAllTypes().Where(IsActivityType).AsSelf().SingleInstance();
}

private static bool IsActivityType(Type type)
{
   return type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IActivity<>));
}

private void RegisterRequestValidationRules()
{
   RegisterAllTypes().AssignableTo<IRequestValidationRule>().AsImplementedInterfaces();
}

Pierwsza metoda rejestruje wszystkie klasy implementujące generyczny interfejs IActivity<T> jako konkretne klasy w trybie singletonowym. Druga jest oczywiście pomocnicza. Trzecia zaś rejestruje wszystkie typy implementujace interfejs IRequestValidationRule jako imlementowane interfejsy. Prawda, że proste i eleganckie?

Po drugie, Autofac to tylko kontener. Nie posiada rozbudowanego systemu rozszerzeń (jak Castle Facilities), który, o ile aplikacja tego wymaga, może okazać się nieoceniony, jednak w moim przypadku (dosyć prosta aplikacja) tylko by zawadzał.

Po trzecie, Autofac nie posiadająca żadnych zależności. Dlaczego to takie ważne? Ponieważ mój projekt, z takich czy innych powodów, ma już podłączone (o wiele za) dużo różnych bibliotek. Nie chciałem narażać się na możliwość konfliktu wersji Castle.DynamicProxy (z którego korzystają zarówno moje biblioteki, jak i Windsor) lub log4net.

Po ostatnie (i najmniej ważne), Autofac to tylko jedna dll-ka.

Co dalej?

Zrewidowałem właśnie swoje przyzwyczajenia odnośnie kontenera. Zmieniłem Unity na Autofac. To oczywiste, ale to nie wszystko. Zmieniłem także swoje nastawienie kwestii DI w ogólności. Ta zmiana zmusiła mnie do lepszego przyjrzenia się dostępnym możliwościom, poszerzyła moje horyzonty. Wreszcie, zmiana ta uczyniła każdą następną zmianę łatwiejszą. Nowe wymaganie dla mojej aplikacji będzie można zrealizować prościej używając Castle Windsor? Proszę bardzo! Już się “przepinam”.

Nieodłączną cechą “wyzywania na pojedynek” swoich przyzwyczajeń jest uświadomienie sobie istnienia założeń, które podświadomie czynimy. W moim wypadku założeniem było korzystanie z Unity i przez kilka projektów nawet nie rozważałem innej opcji. Po “przygodzie” z Autofac, następnym razem na pewno się zastanowię. Innym przykładem nieświadomego założenia jest wykorzystanie bazy SQLowej w (entej) postaci normalnej. Czy ktoś się nad tym zastanawia? A może warto? W dzisiejszych czasach jest tyle ciekawych alternatyw…

VN:F [1.9.13_1145]
Rating: 3.0/5 (1 vote cast)
Ewolucja przyzwyczajeń DI/IoC, 3.0 out of 5 based on 1 rating