2008-08-11 5 views
35

Прежде всего, я знаю, как создать Java-приложение. Но я всегда был озадачен тем, где поставить свои занятия. Есть сторонники для организации пакетов строго ориентированным образом, другие - отдельными.Как я должен структурировать приложение Java, где я помещаю свои классы?

Я сам всегда имели проблемы с

  • наименованием,
  • размещения

Так,

  1. Где вы кладете домен конкретных константы (и каковы лучшее название для такого класса)?
  2. Где вы размещаете классы для материалов, которые являются как инфраструктурными, так и специфичными для домена (например, у меня есть класс FileStorageStrategy, который хранит файлы либо в базе данных, либо, альтернативно, в базе данных)?
  3. Куда поместить Исключения?
  4. Существуют ли какие-либо стандарты, на которые я могу ссылаться?
+0

Очевидно, нет окончательного ответа, но после использования maven2 некоторое время я приступил к определению данной структуры, и поэтому я объявляю ответ maven как один. (Это не значит, что другие ошибаются или что-то еще) Я просто понял, насколько проще не думать о начальных этапах вашей сборки, вы просто бросаете свои источники и источники в те данные каталоги и компилируете их без создания файлов муравьев и т. д. – Mauli 2009-05-15 12:51:20

ответ

21

Я действительно пришел, как Maven's Standard Directory Layout.

Одним из ключевых идей для меня, чтобы иметь два источника корни - один для производства кода и один для тестового кода, как так:

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

(здесь, как SRC/главная/Java и SRC/тест/java являются исходными корнями).

Преимущества:

  • Ваши тесты имеют пакет (или «по умолчанию») уровень доступа к классам при тестировании.
  • Вы можете легко упаковать только ваши источники в JAR, сбросив src/test/java в качестве исходного корня.

Одно правило о размещении классов и пакетов:

Вообще говоря, хорошо структурированные проекты будут свободны от circular dependencies. Узнайте, когда они плохие (и когда они not), и рассмотрите инструмент, например JDepend или SonarJ, который поможет вам устранить их.

3

Названия классов должны всегда быть описательными и пояснять. Если у вас есть несколько доменов ответственности за ваши классы, то их, вероятно, нужно будет реорганизовать.

Аналогично для вас пакеты. Они должны быть сгруппированы по областям ответственности. У каждого домена есть свои исключения.

Как правило, не потейте, пока не дойдете до точки, где она становится подавляющей и раздутой. Затем сядьте и не используйте код, просто переформатируйте классы, регулярно компилируя, чтобы убедиться, что все работает. Затем продолжайте, как и раньше.

2

Используйте пакеты для группировки связанных функций вместе.

Обычно верхняя часть вашего дерева пакетов - это ваше доменное имя, измененное (com.domain.subdomain), чтобы гарантировать уникальность, и тогда обычно будет пакет для вашего приложения. Затем разделите это на соответствующую область, поэтому ваш FileStorageStrategy может идти, скажем, com.domain.subdomain.myapp.storage, а затем могут быть конкретные реализации/подклассы/все в com.domain.subdomain.myapp.storage.file и com.domain.subdomain.myapp.storage.database. Эти имена могут быть довольно длинными, но import держит их всех в верхней части файлов, и IDE также могут помочь в этом.

Исключения обычно идут в том же пакете, что и классы, которые их бросают, поэтому, если бы у вас было, скажем, FileStorageException, оно было бы в том же пакете, что и FileStorageStrategy. Точно так же интерфейс, определяющий константы, будет в одном пакете.

Существует не какой-либо стандарт как таковой, просто используйте здравый смысл, и если все становится слишком грязным, рефакторинг!

0

Одна вещь, которую я делал в прошлом - если я расширяю класс, я попытаюсь следовать их соглашениям. Например, при работе с Spring Framework у меня будут классы MVC Controller в пакете com.mydomain.myapp.web.servlet.mvc Если я не продлеваю что-то, я просто перехожу к тому, что является самым простым. com.mydomain.domain для объектов домена (хотя, если у вас есть тонна объектов домена, этот пакет может стать немного громоздким). Для доменных констант я фактически ставил их как общедоступные константы в самом родном классе.Например, если у меня есть класс «Member» и максимальная константа длины имени члена, я помещаю его в класс Member. В некоторых магазинах есть отдельный класс Constants, но я не вижу значения для объединения несвязанных чисел и строк в один класс. Я видел, как некоторые другие магазины пытаются решить эту проблему, создав классы SEPARATE Constants, но это просто кажется пустой тратой времени, и результат слишком запутан. Используя эту настройку, большой проект с несколькими разработчиками будет дублировать константы повсюду.

0

Мне нравится разбивать классы в пакеты, связанные друг с другом.

Например: Модель Для баз данных, связанных с вызовами

Просмотр Классы, которые имеют дело с тем, что вы видите

управления Основные функциональные классы

Util Любое разное. классы, которые используются (как правило, статические функции)

т.д.

1

Я думаю, что держать его простым и не более чем подумать. Не переусердствуйте и не сложите слишком много. Просто держите его аккуратным, и, поскольку он растет, рефакторинг является тривиальным. Одной из лучших возможностей IDE является рефакторинг, поэтому почему бы не использовать его и не избавить вас от способности мозга решать проблемы, связанные с вашим приложением, а не мета-проблемы, такие как организация кода.

10

Я огромный поклонник организованных источников, поэтому я всегда создаю следующую структуру каталогов:

/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 

В/ЦСИ я использую шаблоны Java по умолчанию: имена пакетов, начиная с вашим доменом (орг .yourdomain.yourprojectname) и имена классов, отражающие аспект OOP, который вы создаете с помощью класса (см. другие комментаторы). Обычные имена пакетов, такие как util, модель, вид, события также полезны.

Я склонен ставить константы для конкретной темы в собственном классе, как SessionConstants или ServiceConstants в том же пакете классов домена.

2

Одна вещь, которая мне очень полезна для модульных тестов, заключалась в том, чтобы иметь файлы myApp/src /, а также myApp/test_src /. Таким образом, я могу размещать модульные тесты в тех же пакетах, что и те классы, которые они тестируют, и тем не менее я могу легко исключить тестовые примеры при подготовке моей производственной установки.

2

Краткий ответ: нарисуйте свою архитектуру системы с точки зрения модулей, нарисованных бок о бок, каждый модуль нарезается вертикально на слои (например, вид, модель, настойчивость). Затем используйте структуру, такую ​​как com.mycompany.myapp.somemodule.somelayer, например. com.mycompany.myapp.client.view или com.mycompany.myapp.server.model.

Использование верхнего уровня пакетов для применения модулей, в старомодном знании компьютерной науки modular programming, должно быть очевидно. Тем не менее, в большинстве проектов, над которыми я работал, мы в конечном итоге забываем это сделать, и в конечном итоге с беспорядком пакетов без этой структуры верхнего уровня. Этот анти-шаблон обычно проявляет себя как пакет для чего-то вроде «слушателей» или «действий», которые группируют в противном случае несвязанные классы просто потому, что они реализуют один и тот же интерфейс.

Внутри модуля или в небольшом приложении используйте пакеты для слоев приложения. Вероятные пакеты включают в себя такие вещи, как ниже, в зависимости от архитектуры:

  • com.mycompany.myapp.view
  • com.mycompany.myapp.model
  • com.mycompany.myapp. услуги
  • com.mycompany.myapp.rules
  • com.mycompany.myapp.persi stence (или «дао» для данных уровня доступа)
  • com.mycompany.myapp.util (остерегайтесь этого используется как если бы он был «разное»)

В каждом из этих слоев, естественно, группировать классы по типу, если их много. Общий анти-шаблон здесь заключается в том, чтобы излишне вводить слишком много пакетов и уровней подпакета, чтобы в каждом пакете было всего несколько классов.

7

Где я работаю, мы используем Maven 2, и у нас есть довольно хороший архетип для наших проектов. Цель заключалась в том, чтобы получить хорошее разделение проблем, поэтому мы определили структуру проекта с использованием нескольких модулей (по одному для каждого слоя приложения): - общий: общий код, используемый другими слоями (например, i18n) - объекты: объекты домена - репозитории: этот модуль содержит интерфейсы daos и реализации - services-intf: интерфейсы для сервисов (например, UserService, ...) - услуги-осущ: реализации услуг (например, UserServiceImpl) - веб: все, в отношении веб-контента (например, CSS, JSP, JSF страницы, ...) - WS: веб-сервисы

Каждый модуль имеет свои собственные зависимости (например, репозитории могут иметь jpa), а некоторые из них являются проектами (при этом они принадлежат к общему модулю). Зависимости между различными проектными модулями четко разделяют вещи (например, веб-уровень зависит от уровня сервиса, но не знает о слое репозитория).

Каждый модуль имеет свой собственный базовый пакет, например, если пакет прикладных программ является «com.foo.bar», то мы имеем:

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

Каждый модуль уважает стандартную структуру Maven проекта:

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

Модульные тесты для данного слоя легко найти свое место в \ src \ test ... Все, что является специфичным для домена, имеет свое место в модуле сущностей. Теперь что-то вроде FileStorageStrategy должно войти в модуль репозиториев, так как нам не нужно точно знать, что такое реализация. На уровне сервисов мы знаем только интерфейс репозитория, нам все равно, какова конкретная реализация (разделение проблем).

Есть несколько преимуществ такого подхода:

  • четкое разделение проблем
  • каждый модуль packageable в банке (или войны в случае веб-модуля) и, таким образом, позволяет легче кода повторное использование (например, мы могли бы установить модуль в репозитории Maven и использовать его в другом проекте)
  • максимальную независимость каждой части проекта

Я знаю, что это делает не отвечайте на все ваши вопросы, но я думаю, что это может привести вас к правильному пути и может оказаться полезным для других.