Jak skonstruować aplikację Java, gdzie umieścić swoje zajęcia?

Po pierwsze, wiem jak zbudować aplikację Java. Ale zawsze zastanawiałam się, gdzie umieścić moje zajęcia. Istnieją zwolennicy organizacji pakietów w sposób ściśle domenowy, inni oddzieleni według poziomu.

Ja sam zawsze miałem problemy z

  • nazewnictwo,
  • umieszczenie

Więc,

  1. gdzie umieszczasz stałe specyficzne dla domeny (i jaka jest najlepsza nazwa dla takiej klasy)?
  2. Gdzie umieścić klasy dla rzeczy, które są zarówno infrastrukturalne, jak i specyficzne dla domeny (na przykład mam klasę FileStorageStrategy, która przechowuje pliki albo w bazie danych, albo alternatywnie w bazie danych)?
  3. Gdzie umieścić wyjątki?
  4. czy są jakieś standardy, do których mogę się odnieść?
Author: Joris Schellekens, 2008-08-11

10 answers

Naprawdę polubiłem standardowy układ katalogów Mavena .

Jednym z kluczowych pomysłów dla mnie jest posiadanie dwóch korzeni źródłowych - jednego dla kodu produkcyjnego i jednego dla kodu testowego:

MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.ava

(tutaj zarówno src / main / java, jak i src / test / java są źródłami źródłowymi).

Zalety:

  • twoje testy mają pakiet (lub" domyślny") dostęp do Twoich klas w trakcie testu.
  • możesz łatwo spakować tylko swoje źródła produkcji do słoika, upuszczając src / test / java jako źródło root.

Jedna zasada dotycząca umieszczania klas i pakietów:

Ogólnie rzecz biorąc, dobrze zorganizowane projekty będą wolne od zależności kołowych . Dowiedz się, kiedy są złe (a kiedy nie), i rozważ narzędzie takie jak JDepend lub SonarJ , które pomoże Ci je wyeliminować.

 23
Author: Brian Laframboise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-27 05:38:47

Jestem wielkim fanem zorganizowanych źródeł, więc zawsze tworzę następującą strukturę katalogów:

/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system

W /src używam domyślnych wzorców Javy: nazw pakietów zaczynających się od Twojej domeny (org.Twoja domena.yourprojectname) oraz nazwy klas odzwierciedlające aspekt OOP, który tworzysz wraz z klasą (zobacz pozostałe komentarze). Typowe nazwy pakietów jak util, model, widok, zdarzenia są również przydatne.

Zazwyczaj umieszczam stałe dla konkretnego temat we własnej klasie, jak SessionConstants lub ServiceConstants w tym samym pakiecie klas domeny.

 10
Author: cringe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-12 08:00:18

Gdzie pracuję, używamy Mavena 2 i mamy całkiem niezły archetyp dla naszych projektów. Celem było uzyskanie dobrego rozdzielenia problemów, dlatego zdefiniowaliśmy strukturę projektu za pomocą wielu modułów (po jednym dla każdej warstwy aplikacji): - common: wspólny kod używany przez inne warstwy (np. i18n) - entities: podmioty domeny - repozytoria: moduł ten zawiera interfejsy i implementacje daos - usługi-intf: interfejsy dla Usług (np. UserService, ...) - usługi-impl: wdrożenia usług (np. UserServiceImpl) - web: wszystko co dotyczy zawartości stron WWW (np. css, jsps, strony jsf,...) - ws: web services

Każdy moduł ma swoje własne zależności (np. repozytoria mogą mieć jpa), a niektóre są ogólnoświatowe (należą więc do wspólnego modułu). Zależności między różnymi modułami projektu wyraźnie oddzielają rzeczy (np. warstwa internetowa zależy od warstwy usług, ale nie wie o repozytorium warstwa).

Każdy moduł ma swój własny pakiet bazowy, na przykład jeśli pakietem aplikacji jest " com.foo.bar", wtedy mamy:

com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...

Każdy moduł respektuje standardową strukturę projektu maven:

   src\
   ..main\java
     ...\resources
   ..test\java
     ...\resources

Testy jednostkowe dla danej warstwy łatwo znajdują swoje miejsce w \src \ test... Wszystko, co jest specyficzne dla domeny, ma swoje miejsce w module entities. Teraz coś w rodzaju FileStorageStrategy powinno wejść do modułu repozytoria, ponieważ nie musimy dokładnie wiedzieć, co realizacja jest. W warstwie usług znamy tylko interfejs repozytorium, nie obchodzi nas jaka jest konkretna implementacja (rozdzielenie obaw).

Istnieje wiele zalet tego podejścia:

  • wyraźny rozdział obaw
  • każdy moduł jest pakowalny jako jar (lub war w przypadku modułu web), a tym samym pozwala na łatwiejsze ponowne użycie kodu (np. możemy zainstalować moduł w repozytorium maven i użyć go ponownie w innym projekt)
  • maksymalna niezależność każdej części projektu

Wiem, że to nie odpowiada na wszystkie Twoje pytania, ale myślę, że to może wprowadzić Cię na właściwą ścieżkę i może okazać się przydatne dla innych.

 8
Author: Sébastien D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 15:55:13

Nazwy klas powinny być zawsze opisowe i oczywiste. Jeśli masz wiele domen odpowiedzialności za swoje klasy, to prawdopodobnie powinny być refakturowane.

Podobnie dla Ciebie Pakiety. Powinny one być pogrupowane według zakresu odpowiedzialności. Każda domena ma swoje własne wyjątki.

Generalnie nie przejmuj się nim, dopóki nie osiągniesz punktu, w którym staje się przytłaczające i nadęte. To siadaj i nie koduj, tylko refaktoruj klasy, Kompiluj regularnie do upewnij się, że wszystko działa. Więc kontynuuj jak wcześniej.

 3
Author: graham.reeds,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-11 08:00:58

Używaj pakietów do grupowania powiązanych funkcji razem.

Zwykle wierzchołkiem drzewa pakietów jest odwrócona nazwa domeny (com.domain.subdomain), aby zagwarantować wyjątkowość, a wtedy zwykle będzie pakiet dla Twojej aplikacji. Następnie podziel to według powiązanego obszaru, więc twoje FileStorageStrategy może wejść, powiedzmy, com.domain.subdomain.myapp.storage, a następnie mogą istnieć konkretne implementacje/podklasy / cokolwiek w com.domain.subdomain.myapp.storage.file i com.domain.subdomain.myapp.storage.database. Nazwy te mogą być dość długie, ale import utrzymuje je wszystkie na górze plików, a IDE mogą pomóc Zarządzaj tym.

Wyjątki zwykle idą w tym samym pakiecie, co klasy, które je rzucają, więc jeśli masz, powiedzmy, FileStorageException to trafiłyby do tego samego pakietu, co FileStorageStrategy. Podobnie interfejs definiujący stałe byłby w tym samym pakiecie.

Nie ma tak naprawdę żadnego standardu jako takiego, po prostu użyj zdrowego rozsądku, a jeśli wszystko zrobi się zbyt bałagan, refactor!

 2
Author: Kieron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-11 08:24:02

Jedną z rzeczy, która okazała się bardzo pomocna w testach jednostkowych, było posiadanie katalogów myApp / src / oraz MyApp / test_src/. W ten sposób mogę umieszczać testy jednostkowe w tych samych pakietach co klasy, które testują, a mimo to mogę łatwo wykluczyć przypadki testowe podczas przygotowywania mojej instalacji produkcyjnej.

 2
Author: Arkadiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 12:21:37

Krótka odpowiedź: Narysuj swoją architekturę systemu w kategoriach modułów, rysowanych obok siebie, z każdym modułem pokrojonym pionowo w warstwy (np. widok, model, trwałość). Następnie użyj struktury typu com.mycompany.myapp.somemodule.somelayer , np. com.mycompany.myapp.klient.zobacz lub kom.mycompany.myapp.serwer.model .

Używanie najwyższego poziomu pakietów dla aplikacji modułów , w staromodnym informatycznym sensie modułowych programowanie , powinno być oczywiste. Jednak w większości projektów, nad którymi pracowałem, zapominamy o tym i kończymy z bałaganem pakietów bez tej najwyższej struktury. Ten anty-wzorzec zwykle pokazuje się jako pakiet dla czegoś takiego jak "słuchacze" lub "akcje", które grupują inne niepowiązane klasy po prostu dlatego, że implementują ten sam interfejs.

W module lub w małej aplikacji stosuj pakiety dla warstw aplikacji. Prawdopodobnie pakiety zawierają następujące rzeczy, w zależności od architektury:

  • com.mycompany.myapp.widok
  • com.mycompany.myapp.model
  • com.mycompany.myapp.usługi
  • com.mycompany.myapp.Zasady
  • com.mycompany.myapp.persistence (lub " dao " dla warstwy dostępu do danych)
  • com.mycompany.myapp.util (uważaj, aby było to używane tak, jakby było "różne")

W każdym z te warstwy, naturalne jest grupowanie klas według typu, jeśli jest ich dużo. Powszechnym antypakietem jest niepotrzebne wprowadzanie zbyt wielu pakietów i poziomów podpakietów, tak aby w każdym pakiecie było tylko kilka klas.

 2
Author: Peter Hilton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 13:40:54

Myślę, że to proste i nie przesadzaj. Nie przesadzaj z abstrakcją i nakładaj zbyt wiele warstw. Po prostu zadbaj o to, a gdy rośnie, refaktoryzacja jest trywialna. Jedną z najlepszych cech IDE jest refaktoryzacja, więc dlaczego nie skorzystać z niej i zaoszczędzić energii mózgu do rozwiązywania problemów, które są związane z aplikacją, a nie meta problemy, takie jak organizacja kodu.

 1
Author: Michael Neale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-12 03:36:32

Jedna rzecz, którą zrobiłem w przeszłości - jeśli przedłużam zajęcia, spróbuję podążać za ich konwencjami. Na przykład, podczas pracy z frameworkiem Spring, będę miał moje klasy kontrolerów MVC w pakiecie o nazwie com.mydomain.myapp.www.servlet.mvc Jeśli czegoś nie przedłużam, po prostu wybieram to, co najprostsze. com.mydomain.domena dla obiektów Domain (chociaż jeśli masz mnóstwo obiektów domain, ten pakiet może być nieco nieporęczny). Dla stałych specyficznych dla domeny, w rzeczywistości umieszczam je jako publiczne stałe w najbardziej pokrewnej klasie. Na przykład, jeśli mam klasę "Member" i mam maksymalną stałą długości nazwy użytkownika, umieszczam ją w klasie Member. Niektóre sklepy tworzą osobną klasę stałych, ale nie widzę wartości w grupowaniu niepowiązanych liczb i ciągów w jedną klasę. Widziałem kilka innych sklepów próbujących rozwiązać ten problem poprzez tworzenie oddzielnych klas stałych, ale to po prostu wydaje się stratą czasu, a wynik jest zbyt mylący. Korzystając z tej konfiguracji, duży projekt z wielu programistów będzie powielać stałe w każdym miejscu.

 0
Author: bpapa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-11 23:25:44

Lubię dzielić moje klasy na pakiety, które są ze sobą powiązane.

Na przykład: Model dla wywołań związanych z bazą danych

Zobacz klasy, które zajmują się tym, co widzisz

Control podstawowe klasy funkcjonalności

Util any misc. klasy, które są używane (zazwyczaj funkcje Statyczne)

Itd.

 0
Author: Bryan Denny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-12 01:28:23