Mam dużą bazę kodową z wieloma singletonami „anty-wzorcowymi”, klasami użyteczności z metodami statycznymi i klasami tworzącymi własne zależności za pomocą new
słowa kluczowego. To bardzo utrudnia testowanie kodu.
Chcę stopniowo migrować kod do kontenera wstrzykiwania zależności (w moim przypadku jest to Guice
, ponieważ jest to GWT
projekt). Z mojego zrozumienia zastrzyku uzależnienia, to wszystko albo nic. Wszystkimi klasami zarządza Spring / Guice lub żadnymi. Ponieważ baza kodów jest duża, nie mogę przekształcić kodu w ciągu nocy. Potrzebuję więc sposobu, aby robić to stopniowo.
Problem polega na tym, że kiedy zaczynam od klasy, która wymaga wstrzyknięcia do innych klas, nie mogę użyć prostej @Inject
w tych klasach, ponieważ te klasy nie są jeszcze zarządzane przez kontener. To tworzy długi łańcuch aż do „najlepszych” klas, które nigdzie nie są wstrzykiwane.
Jedyny sposób, jaki widzę, to na razie udostępnienie Injector
globalnego kontekstu / aplikacji za pośrednictwem singletona, aby inne klasy mogły uzyskać z niego zarządzaną fasolę. Jest to jednak sprzeczne z ważną ideą nieujawniania composition root
aplikacji.
Innym podejściem byłoby podejście oddolne: aby rozpocząć od klas „wysokiego poziomu”, należy uwzględnić je w pojemniku wstrzykiwania zależności i powoli przechodzić do klas „mniejszych”. Ale potem muszę długo czekać, ponieważ mogę przetestować te mniejsze klasy, które wciąż zależą od globałów / statyki.
W jaki sposób można osiągnąć taką stopniową migrację?
PS Pytanie Stopniowe podejście do wstrzykiwania zależności jest podobne w tytule, ale nie odpowiada na moje pytanie.
źródło
Odpowiedzi:
Niestety
C#
to mój język wybór, mogę czytaćJava
ale prawdopodobnie rżnąć składnię próbuje napisać ... Te same koncepcje zastosowania pomiędzyC#
iJava
choć, więc mam nadzieję, że to pokaże kroki w jaki sposób można stopniowo przenieść swoją bazę kodu, aby być bardziej testowalny.Dany:
można łatwo refaktoryzować do korzystania z DI, bez użycia kontenera MKOl - i potencjalnie możesz nawet rozbić go na kilka etapów:
(potencjalnie) Krok pierwszy - weź zależności, ale bez zmiany kodu wywołującego (UI):
Refaktor 2 (lub pierwszy refaktor w przypadku natychmiastowego wdrożenia kontenera IOC i zmiany kodu wywoławczego):
Krok 2 mógłby technicznie być wykonany sam - ale (potencjalnie) byłby o wiele większy - zależny od tego, ile klas obecnie „odnawia” funkcjonalność, którą chcesz DI.
Zastanów się nad przejściem z kroku 1 -> kroku 2 -
Foo
niezależnie od tego możesz tworzyć testy jednostkoweBar
. Natomiast przed refaktorem kroku 1 nie było łatwo tego dokonać bez faktycznej implementacji obu klas. Wykonanie kroku 1 -> krok 2 (zamiast kroku 2 natychmiast) pozwoliłoby na mniejsze zmiany w miarę upływu czasu, a Ty już masz zestaw testowy, aby lepiej upewnić się, że Twój reaktor pracował bez konsekwencji.źródło
Koncepcja jest taka sama, niezależnie od tego, czy używasz Java, PHP, czy nawet C #. W tym filmie na YouTube Gemma Anible dość dobrze poradziła sobie z tym pytaniem:
https://www.youtube.com/watch?v=Jccq_Ti8Lck (PHP, przepraszam!)
Zamieniasz niestabilny kod na „fasada” (z powodu braku lepszego terminu), który wywołuje nowy, testowalny kod. Następnie stopniowo możesz zastąpić starsze połączenia wprowadzonymi usługami. Zrobiłem to w przeszłości i działa całkiem dobrze.
źródło