Zalecenia dotyczące integracji kontenera DI / IoC z istniejącą aplikacją

10

Mam teraz do czynienia z integracją kontenera inwersji sterowania (IoC) z istniejącą aplikacją i szukam rekomendacji, w jaki sposób można to najłatwiej osiągnąć z ostatecznym celem zmniejszenia sprzężenia, a tym samym zwiększenia testowalności. Chociaż generalnie nie klasyfikowałbym większości klas jako obiektów boskich , każda z nich ma zbyt wiele obowiązków i ukrytych zależności poprzez statykę, singletony i brak interfejsów.

Oto kilka przykładów niektórych wyzwań, z którymi trzeba się zmierzyć:

  • Rzadko stosuje się wstrzyknięcie zależności
  • Istnieje wiele metod statycznych - zarówno metod fabrycznych, jak i pomocniczych
  • Singletony są dość powszechne
  • Interfejsy, gdy są używane, nie są zbyt szczegółowe
  • Obiekty często przyciągają niepotrzebne zależności poprzez klasy podstawowe

Naszym celem jest, aby następnym razem, gdy będziemy musieli dokonać zmian w konkretnym obszarze, staramy się wyeliminować zależności, które w rzeczywistości istnieją, ale są ukryte za globalsami, takimi jak singletony i statyka.

Przypuszczam, że czyni to kontener IoC drugorzędnym w stosunku do wprowadzenia wstrzykiwania zależności, ale oczekiwałbym, że istnieje zestaw praktyk i zaleceń, które można zastosować lub rozważyć, które pomogą nam przełamać te zależności.

Kaleb Pederson
źródło
3
Muszę teraz zapytać o powód, dla którego to zrobiłem ... co jest przyczyną tej zmiany? Konserwowalność? Skalowalność, ponieważ będzie rosła wykładniczo? Programiści się nudzą?
Aaron McIver
1
Niedawno dołączyłem do firmy i staram się wprowadzić „najlepsze praktyki”. Moim głównym celem jest zwiększenie testowalności i ograniczenie sprzężenia. Możemy łatwo użyć DI / IoC do nowego kodu i nie zamierzamy próbować zmieniać całego istniejącego kodu na raz, ale chciałbym uzyskać zalecenia dotyczące tego, jak najlepiej zmienić istniejący kod na lepsze, następnym razem, gdy robimy zmiany w tym obszarze. Jak dotąd jedyne, co znalazłem w Internecie, to: code.google.com/p/autofac/wiki/ExistingApplications
Kaleb Pederson
3
Chyba że istnieje duża liczba zautomatyzowanych testów jednostkowych / integracyjnych; modyfikowanie istniejącej infrastruktury, chyba że istnieje problem ze względu na najlepsze praktyki, wymaga problemów. Nawet jeśli twój pakiet testów jednostkowych / integracyjnych był solidny, wciąż się wahałem.
Aaron McIver
1
@Aaron Mam nadzieję, że nie zabrzmiało to tak, jakbyśmy robili to ze względu na najlepsze praktyki. Wprowadzamy zmiany, ponieważ praca z istniejącym kodem jest trudna i powolna, i robimy to fragmentarycznie, gdy pracujemy w tym konkretnym obszarze. Na szczęście mamy zestaw rozsądnych testów integracyjnych i kilka testów jednostkowych w celu wsparcia wprowadzania zmian.
Kaleb Pederson

Odpowiedzi:

8

Aby wykonać coś takiego, będziesz musiał pracować etapami, każdy z nich nie jest trywialny, ale można to osiągnąć. Zanim zaczniesz, musisz zrozumieć, że nie możesz przyspieszyć tego procesu.

  1. Zdefiniuj główne podsystemy aplikacji i interfacedla każdego z nich. Ten interfejs powinien określać tylko metody, z których inne części systemu będą korzystać, aby z nim rozmawiać. UWAGA: w tym przypadku może być konieczne wykonanie więcej niż jednego przejścia.
  2. Podaj implementację opakowania tego interfejsu, która deleguje do istniejącego kodu. Celem tego ćwiczenia jest uniknięcie przepisywania masowego , ale przeredagowanie kodu w celu użycia nowych interfejsów - tj. Zmniejszenia sprzężenia w systemie.
  3. Skonfiguruj kontener IoC, aby zbudować system przy użyciu utworzonych interfejsów i implementacji. Na tym etapie chcesz zadbać o utworzenie instancji kontenera IoC, aby mógł on uruchomić aplikację. To znaczy, jeśli jesteś w środowisku serwletu, upewnij się, że możesz pobrać / utworzyć kontener w init()metodzie serwletu .
  4. Zrób to samo w obrębie każdego podsystemu, tym razem, gdy dokonujesz refaktoryzacji, zmieniasz implementację kodu pośredniczącego w rzeczywistą, która z kolei używa interfejsów do komunikowania się z jego komponentami.
  5. Powtarzaj w razie potrzeby, aż uzyskasz równowagę między wielkością elementu a funkcjonalnością.

Kiedy skończysz, jedynymi metodami statycznymi, które powinieneś mieć w systemie, są te, które są naprawdę funkcjami - na przykład spójrz na Collectionsklasę lub Mathklasę. Żadna metoda statyczna nie powinna próbować uzyskać bezpośredniego dostępu do innych komponentów.

To zajmie dużo czasu, odpowiednio zaplanuj. Upewnij się, że podczas przeprowadzania refaktoryzacji stajesz się bardziej SOLIDNY ​​w swoim podejściu projektowym. Na początku będzie to bolesne. Drastycznie zmieniasz iteracyjnie wygląd swojej aplikacji.

Berin Loritsch
źródło
Dobre sugestie. Podczas dokonywania takich zmian odsyłam też do innych sugestii: code.google.com/p/autofac/wiki/ExistingApplications
Kaleb Pederson
7

Wybierz Efektywną pracę ze Starszym Kodem i postępuj zgodnie z jego radami. Zacznij od zbudowania wysp objętych kodem i stopniowo przejdź do bardziej uporządkowanej aplikacji. Próba masowej zmiany jest receptą na katastrofę.

Michael Brown
źródło
Uwielbiam tę książkę !!
Martijn Verburg,
Dobra rekomendacja. Chociaż przeczytałem połowę tego lata temu, wyobrażam sobie, że wyciągnę z tego znacznie więcej, gdy jestem głęboko w sytuacji.
Kaleb Pederson
To zabawne, wybrana odpowiedź w zasadzie podsumowuje książkę;) Oczywiście Feathers jest o wiele bardziej szczegółowy.
Michael Brown
5

Głównym powodem wprowadzenia IoC jest oddzielenie modułów. Problemem, szczególnie w Javie, jest nadzwyczaj silne powiązanie, które newdaje operator, w połączeniu z tym, że kod wywołujący wie dokładnie, jakiego modułu użyje.

Wprowadzono fabryki, aby przenieść tę wiedzę do centralnego miejsca, ale ostatecznie albo nadal okablujesz moduły za pomocą new/ singleton, który utrzymuje twarde wiązanie, albo czytasz w pliku konfiguracyjnym i używasz pliku refleks / Class.forName, który jest kruchy podczas refaktoryzacji .

Jeśli nie masz celu zmodularyzowanego, to IoC nic ci nie da.

Wprowadzenie testów jednostkowych najprawdopodobniej to zmieni, ponieważ będziesz musiał wyśmiewać moduły, które nie są testowane, a najłatwiejszym sposobem radzenia sobie z tym, a także rzeczywistymi modułami produkcyjnymi z tym samym kodem, jest użycie frameworka IoC w celu wstrzyknięcia odpowiedniego moduły.


źródło