Jakiś czas temu zobaczyłem odpowiedź na pytanie dotyczące drobiazgowej organizacji pakietów Java. Na przykład my.project.util
, my.project.factory
, my.project.service
, itd.
Nie mogę go teraz znaleźć, więc równie dobrze mogę zadać pytanie.
Czy istnieją najlepsze praktyki dotyczące organizacji pakietów w Javie i co się w nich dzieje?
Jak organizujesz zajęcia w swoim projekcie Java?
Na przykład projekt, nad którym pracuję z kilkoma osobami, zawiera pakiet o nazwie fasola. Zaczęło się od projektu zawierającego prostą fasolę, ale ostatecznie (z powodu złego doświadczenia i braku czasu) zawierało wszystko (prawie). Wyczyściłem je trochę, umieszczając niektóre klasy fabryczne w pakiecie fabrycznym (klasy ze statycznymi metodami, które tworzą fasole), ale mamy inne klasy, które wykonują logikę biznesową i inne, które wykonują proste przetwarzanie (nie z logiką biznesową), takie jak pobieranie komunikat o kodzie z pliku właściwości.
Wasze przemyślenia i komentarze są mile widziane.
źródło
Odpowiedzi:
Organizacja pakietu lub jego struktura to zwykle gorąca dyskusja. Poniżej znajduje się kilka prostych wskazówek dotyczących nazewnictwa i strukturyzacji pakietów:
com.company.product.modulea
com.company.product.module.web
lubcom.company.product.module.util
itp.com.company.product.model
icom.company.product.util
itp.Po kilku eksperymentach i próbach powinieneś być w stanie wymyślić strukturę, w której czujesz się komfortowo. Nie skupiaj się na jednej konwencji, bądź otwarty na zmiany.
źródło
Organizuję pakiety według funkcji , a nie według wzorców lub ról implementacyjnych. Myślę, że pakiety takie jak:
beans
factories
collections
jest źle.
Wolę na przykład:
orders
store
reports
więc mogę ukryć szczegóły implementacji poprzez widoczności pakietu . Fabryka zamówień powinna znajdować się w
orders
paczce, dlatego szczegóły dotyczące tworzenia zamówienia są ukryte.źródło
Krótka odpowiedź: jeden pakiet na moduł / funkcję, ewentualnie z sub-pakietami. Połącz ze sobą ściśle powiązane rzeczy w jednym pakiecie. Unikaj okrągłych zależności między pakietami.
Długa odpowiedź: zgadzam się z większością tego artykułu
źródło
Wolę funkcję przed warstwami, ale myślę, że to zależy od twojego projektu. Rozważ swoje siły:
Spróbuj zminimalizować zależności pakietów, szczególnie między funkcjami. W razie potrzeby wyodrębnij interfejsy API.
W niektórych organizacjach zespoły pracują nad funkcjami, aw innych na warstwach. Wpływa to na sposób organizacji kodu, służy do formalizowania interfejsów API lub zachęca do współpracy.
Umieszczenie wszystkiego w module upraszcza wdrażanie i wersjonowanie, ale trudniej naprawia błędy. Dzielenie rzeczy zapewnia lepszą kontrolę, skalowalność i dostępność.
Dobrze zorganizowany kod jest dużo łatwiejszy do zmiany niż duża kula błota.
Im większy, tym bardziej musi być sformalizowany / znormalizowany.
Niektóre kody są ważniejsze niż inne. Interfejsy API powinny być bardziej stabilne niż implementacja. Dlatego należy go wyraźnie oddzielić.
Osoba z zewnątrz powinna mieć możliwość dowiedzenia się, o co chodzi w kodzie i od czego zacząć czytanie od spojrzenia na drzewo pakietu.
Przykład:
To tylko przykład. To jest dość formalne. Na przykład definiuje 2 interfejsy dla cechy1 . Zwykle nie jest to wymagane, ale może być dobrym pomysłem, jeśli używane są inaczej przez różne osoby. Możesz pozwolić wewnętrznemu API rozszerzyć publiczność.
Nie podoba mi się nazwa „impl” lub „support”, ale pomagają one oddzielić mniej ważne rzeczy od ważnych (domena i API). Jeśli chodzi o nazywanie, lubię być jak najbardziej konkretny. Jeśli masz pakiet o nazwie „utils” z 20 klasami, przejdź
StringUtils
do support / string,HttpUtil
support / http i tak dalej.źródło
Nie, naprawdę nie. Istnieje wiele pomysłów i opinii, ale prawdziwą „najlepszą praktyką” jest kierowanie się zdrowym rozsądkiem!
(Proszę przeczytać Brak najlepszych praktyk, aby uzyskać informacje na temat „najlepszych praktyk” i osób, które je promują).
Jest jednak jedna zasada, która prawdopodobnie ma szeroką akceptację. Struktura pakietu powinna odzwierciedlać strukturę modułu (nieformalną) aplikacji, a użytkownik powinien dążyć do minimalizacji (lub idealnie całkowitego uniknięcia) cyklicznych zależności między modułami.
(Cykliczne zależności między klasami w pakiecie / module są w porządku, ale cykle między pakietami zwykle utrudniają zrozumienie architektury aplikacji i mogą stanowić barierę dla ponownego użycia kodu. W szczególności, jeśli użyjesz Maven, zauważysz, że jest to cykliczne Zależności między pakietami / modułami oznaczają, że cały połączony bałagan musi być jednym artefaktem Maven.)
Należy również dodać, że nie jest jeden powszechnie akceptowane najlepsze praktyki dla nazw pakietów. Oznacza to, że nazwy pakietów powinny zaczynać się od nazwy domeny organizacji w odwrotnej kolejności. Przestrzegając tej zasady, zmniejszasz prawdopodobieństwo problemów powodowanych przez konflikt twoich (pełnych) nazw klas z innymi ludźmi.
źródło
Widziałem, jak niektórzy ludzie promowali „pakiet po funkcji” zamiast „pakiet po warstwie”, ale przez wiele lat stosowałem kilka podejść i stwierdziłem, że „pakiet po warstwie” jest znacznie lepszy niż „pakiet po funkcji”.
Ponadto odkryłem, że strategia hybrydowa: „pakiet po module, warstwa, a następnie funkcja” działa wyjątkowo dobrze w praktyce, ponieważ ma wiele zalet „pakiet po funkcji”:
Dokładnie wyjaśniam tutaj: Struktura i organizacja nazw pakietów Java, ale moja standardowa struktura pakietów to:
revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...
Gdzie:
revdomain Odwrócona domena np. com.mycompany
moduleType [app * | framework | util]
moduleName np. myAppName, jeśli typem modułu jest aplikacja lub „finanse”, jeśli jest to struktura rachunkowości
warstwa [model | interfejs | trwałość | bezpieczeństwo itp.]
layerImpl np., furtka, jsp, jpa, jdo, hibernacja (Uwaga: nieużywane, jeśli warstwa jest modelem)
funkcja np. finanse
podfunkcjaN np. księgowość
podfunkcja N + 1 np. amortyzacja
* Czasami „aplikacja” jest pomijana, jeśli moduleType jest aplikacją, ale umieszczenie jej tam sprawia, że struktura pakietu jest spójna we wszystkich typach modułów.
źródło
Nie znam standardowych praktyk dotyczących organizacji pakietów. Generalnie tworzę pakiety, które obejmują dość szerokie spektrum, ale mogę różnicować w ramach projektu. Na przykład osobisty projekt, nad którym obecnie pracuję, zawiera pakiet poświęcony moim niestandardowym kontrolkom interfejsu użytkownika (pełnym klasom klas podklasowych). Mam pakiet poświęcony zarządzaniu bazą danych, mam pakiet dla zestawu detektorów / zdarzeń, które utworzyłem i tak dalej.
Z drugiej strony kazałem współpracownikowi stworzyć nową paczkę dla prawie wszystkiego, co zrobił. Każde inne MVC, którego chciał, miało swoją własną paczkę i wydawało się, że zestaw MVC był jedyną grupą klas, która mogła znajdować się w tym samym pakiecie. Pamiętam, że w pewnym momencie miał 5 różnych pakietów, z których każdy zawierał jedną klasę. Myślę, że jego metoda jest trochę ekstremalna (a zespół zmusił go do zmniejszenia liczby pakietów, gdy po prostu nie mogliśmy sobie z tym poradzić), ale w przypadku aplikacji niepraktycznych, więc umieszczenie wszystkiego w tym samym pakiecie. Jest to punkt równowagi, który ty i twoi koledzy z drużyny musicie znaleźć dla siebie.
Jedną rzeczą, którą możesz zrobić, to cofnąć się i pomyśleć: jeśli byłeś nowym członkiem przedstawionym do projektu lub twój projekt został wydany jako open source lub API, jak łatwo / trudno byłoby znaleźć to, czego chcesz? Bo dla mnie to jest to, czego naprawdę chcę od pakietów: organizacja. Podobnie jak w przypadku przechowywania plików w folderze na komputerze, spodziewam się, że będę mógł je znaleźć ponownie bez konieczności przeszukiwania całego dysku. Oczekuję, że będę w stanie znaleźć klasę, którą chcę, bez konieczności przeszukiwania listy wszystkich klas w pakiecie.
źródło