Rozdzielanie projektów Java

12

Mam duży projekt Java i używamy maven do naszego cyklu budowania. Ten jeden projekt jest szeroko stosowany - w innych projektach, w różnych aplikacjach, z których niektóre są w nim zawarte, a niektóre gdzie indziej ... Szczerze mówiąc, jest to trochę bałagan (różne bity dodawane w różnych momentach dla określonych celów) i chciałbym to trochę posprzątać. Ponadto nie jest w pełni przetestowany (wiele bitów zostało dodanych bez odpowiednich testów jednostkowych i integracyjnych), a niektóre testy trwają długo lub wcale nie przechodzą ... (uh-oh) - więc testy są wyłączone w cyklu budowy maven (znowu, uh-oh).

Zastanawiam się nad podzieleniem tego dużego projektu na mniejsze konkretne projekty, tak aby „końcowy” podprojekt (lub kilka podprojektów) zbierał różne podprojekty, których potrzebowałby.

Moje myślenie jest następujące:

  • jeśli podzielę duży projekt na różne podprojekty, stanie się jasne, jaka jest odpowiedzialność za każdy projekt.
  • dzieląc na podprojekty, mogę następnie wyczyścić testowanie każdego podprojektu indywidualnie i włączyć testy dla tego podprojektu w cyklu budowania raju.

Jestem nieco zaniepokojony wpływem, jaki może to mieć na czas kompilacji.

  • Czy nałożenie struktury na duży projekt (tj. Na mniejsze podprojekty) spowolniłoby kompilator?

Ponadto mam niewielkie obawy dotyczące wpływu, jaki może to mieć czas edytowania w IDE (głównie używamy Intellij). Wydaje się, że Intellij buduje każdy projekt kolejno przez drzewo zależności - tzn. Jeśli C zależy od B zależy od A, a ja zmienię A, nie będzie próbował zbudować B, chyba że A się skompiluje i tak dalej. Prawdopodobnie jest to korzystne, ale odkryłem, że jeśli - na przykład zmieniam interfejs w A, który jest powszechnie używany w B i C, zajmuje trochę czasu, aby naprawić wszystkie błędy z tej zmiany ...

Kolejne pytanie dotyczy sposobu korzystania z klas fabrycznych. Niektóre aspekty projektu zależą od zewnętrznych słoików. Czasami (na szczęście nie często) są one aktualizowane i musimy przeprowadzić migrację. Mamy tendencję do radzenia sobie z tym za pomocą klasy Factory, która wskazuje na poprawne wersje kodu zewnętrznego (więc nie musimy zmieniać wszystkich implementacji w całej bazie kodu).

W tej chwili jest to wszystko w dużym projekcie, ale myślę, że przechodząc do podprojektów, mógłbym opracować nowy projekt do wdrożenia nowego kodu zewnętrznego, upewnić się, że podprojekt jest w pełni funkcjonalny i przetestowany oraz następnie przełącz zależności / klasę fabryczną w projekcie użytkownika. Jest to jednak bardziej skomplikowane ze względu na szerokie zastosowanie interfejsów w całym dużym projekcie. Na przykład

  • podprojekt A - zawiera interfejsy
  • podprojekt B - zależy od A dla interfejsów i starego zewnętrznego słoika
  • podprojekt C - zależy od B (a więc A i starego zewnętrznego słoika) i zawiera klasę Factory, która wykorzystuje implementacje interfejsów B

Jeśli muszę zmienić zewnętrzny słoik B, mogę:

  • utwórz podprojekt B_ii - znowu zależy od A, a teraz nowego zewnętrznego słoika
  • kiedy już będzie w pełni funkcjonalny, mogę dodać zależność C do B_ii i zmienić klasę Factory, aby korzystać z nowych implementacji interfejsów.
  • kiedy to wszystko działa, mogę następnie usunąć zależność C od pierwotnego B, a w razie potrzeby usunąć podprojekt B.

  • Czy to rozsądny sposób, aby to zrobić?

Ogólnie moje pytania są następujące:

  • Czy ktoś ma doświadczenie w rozkładaniu dużych projektów? Czy są jakieś wskazówki / triki, którymi chętnie się podzielisz?
  • Jaki to miało wpływ na twoje czasy rozwoju i kompilacji?
  • Jaką radę mógłbyś udzielić w sprawie zorganizowania takiego rozpadu takiego projektu?
wypłata
źródło
Pamiętaj, że możesz utworzyć projekt nadrzędny z A, B i C oddzielnie wyewidencjonowanymi obok siebie. Dzięki temu np. IntelliJ ma jednocześnie wszystkie trzy w pamięci i dokonuje refaktoryzacji ponad granicami modułów.
Thorbjørn Ravn Andersen

Odpowiedzi:

10

Mam zamiar zrobić szybkie pierwsze cięcie na tym (świetne Q BTW!):

Czy nałożenie struktury na duży projekt (tj. Na mniejsze podprojekty) spowolniłoby kompilator?

Nie dość, że ma to znaczenie, koszty ogólne są w rzeczywistości wywołane przez Maven.

Ponadto mam niewielkie obawy dotyczące wpływu, jaki może to mieć czas edytowania w IDE (głównie używamy Intellij). Wydaje się, że Intellij buduje każdy projekt kolejno przez drzewo zależności - tzn. Jeśli C zależy od B zależy od A, a ja zmienię A, nie będzie próbował zbudować B, chyba że A się skompiluje i tak dalej. Prawdopodobnie jest to korzystne, ale odkryłem, że jeśli - na przykład zmieniam interfejs w A, który jest powszechnie używany w B i C, zajmuje trochę czasu, aby naprawić wszystkie błędy z tej zmiany ...

Różne środowiska IDE mają różne mocne strony w odniesieniu do powiązań Maven i zarządzania zależnościami. Wydaje się, że obecna sytuacja polega na tym, że działa ona głównie na najnowszych Eclipse, Netbeans i IntelliJ - ale będziesz musiał nauczyć swoich programistów awaryjnego podwójnego działania „Odśwież pliki źródłowe z dysku i odbuduj wszystkie powiązane projekty maven”.

Uważam jednak, że w dzisiejszych czasach muszę to robić coraz mniej. Posiadanie dysku SSD robi tutaj ogromną różnicę BTW.

paragrafy klas fabryki wycinków

Zarządzanie zależnościami jest niezwykle ważne, niezależnie od tego, jakiej technologii (Maven / Ivy / cokolwiek) używasz, aby pomóc Ci je wdrożyć.

Zacznę od wyciągnięcia obszernych raportów z wtyczki zależności Maven i podsumowania tego, co masz. Ogólnie mówiąc, ustawiasz zależność w zarządzaniu zależnościami POM tak wysoko, jak to możliwe, ale nie wyżej. Więc jeśli dwa z twoich submodułów używają zależności zewnętrznej, przeciągnij to do ich macierzystej POM i tak dalej.

Uaktualnianie zewnętrznych plików JAR powinno zawsze odbywać się jako właściwy mini-projekt. Oceń, dlaczego przeprowadzasz aktualizację, zmień kod źródłowy, aby skorzystać z nowych funkcji / poprawek błędów itp. Po prostu zderzenie wersji bez tej analizy i pracy spowoduje kłopoty.

Ogólnie moje pytania są następujące:

Czy ktoś ma doświadczenie w rozkładaniu dużych projektów? Czy są jakieś wskazówki / porady, którymi chętnie się podzielisz?

  • Interfejsy i wstrzykiwanie zależności są Twoim przyjacielem.
  • Należy przeczytać książkę Michaela Feathera na temat skutecznego radzenia sobie ze starszym kodem .
  • Testy integracyjne są twoim przyjacielem
  • Podział podprojektów na foo-api (tylko interfejsy!) I foo-core oraz posiadanie modułów zależnych tylko od foo-api pomaga bardzo dużo i wymusza separację
  • Moduły Jboss i / lub OSGi mogą pomóc wymusić czystą separację

Jaki to miało wpływ na twoje czasy rozwoju i kompilacji?

Bardzo niewielki wpływ na czasy projektowania i budowy - ogromny wzrost czasu dla naszej ogólnej ciągłej dostawy.

Jaką radę mógłbyś udzielić w sprawie zorganizowania takiego rozpadu takiego projektu?

Rób małe rzeczy we właściwy sposób, a potem wielkie rzeczy wypadają czysto. Więc rozdzielaj rzeczy po trochu - nie rób masowej restrukturyzacji całej partii, chyba że masz wysoki odsetek pokrycia w testach integracyjnych.

Napisz testy integracyjne przed podziałem - powinieneś mniej więcej uzyskać ten sam wynik (y) po podziale.

Narysuj schematy modułowości, którą masz teraz i gdzie chcesz się dostać. Zaprojektuj kroki pośrednie.

Nie poddawaj się - niektóre golenie Jaków stanowi teraz podstawę do „szybkiego budowania i refaktoryzacji bez strachu” Bezwstydna wtyczka -> od The Ben and I's The Well-Grounded Java Developer .

Powodzenia!

Martijn Verburg
źródło
0

Moje zdanie na ten temat jest odrębne tylko w razie potrzeby. Pojawia się jednak kolejne pytanie: jak ustalić, czy jest to konieczne?

  • Gdy artefakt jest inny (tzn. Nie buduj słoika EAR, WAR, JAR, testowania integracji w tym samym projekcie).
  • Kiedy podczas separacji zauważysz, że jakiś kod musi istnieć w więcej niż jednym artefakcie, zamień je w nowy.
  • Gdy jakiś inny projekt poza twoim zespołem chce użyć czegoś, co masz w swoim projekcie.

Jednym z powodów jest to, że programiści muszą poradzić sobie z wieloma projektami i spróbować dowiedzieć się poza tym, jaki pakiet Java jest do jakiego projektu powinien należeć. Byłem przy projektach, w których stało się to naprawdę anemiczne i miałem projekt, w którym cztery klasy implementowały jedną funkcjonalność tylko dlatego, że jest to kierunek architektoniczny. Było to również zanim Maven stał się popularny, więc ścieżki klas i to, czego nie trzeba konfigurować zarówno w skryptach IDE, jak i Ant.

Innym powodem jest to, że będziesz mieć więcej ruchomych części, z którymi musisz sobie poradzić w zakresie hydrauliki plików i prawdopodobnie będziesz mieć spaghetti zależności, zanim się zorientujesz.

Refaktoryzacja jest również łatwiejsza w ramach projektu niż w przypadku różnych projektów.

Jeśli problemem jest czas kompilacji, po prostu zapewnij lepszy sprzęt.

Archimedes Trajano
źródło