Подтвердить что ты не робот

Как я должен структурировать приложение Java, где я помещаю свои классы?

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

У меня всегда были проблемы с

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

Итак,

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

Ответ 1

Мне действительно понравилось Maven Стандартный макет каталога.

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

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

(здесь оба src/main/java и src/test/java являются корнями источника).

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

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

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

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

Ответ 2

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

/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

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

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

Ответ 3

Где я работаю, мы используем Maven 2, и у нас есть довольно хороший архетип для наших проектов. Цель заключалась в том, чтобы получить хорошее разделение проблем, поэтому мы определили структуру проекта с использованием нескольких модулей (по одному для каждого слоя приложения): - общий: общий код, используемый другими уровнями (например, i18n) - объекты: объекты домена - репозитории: этот модуль содержит интерфейсы daos и реализации - services-intf: интерфейсы для служб (например, UserService,...) - services-impl: реализация служб (например, UserServiceImpl) - web: все, что касается веб-контента (например, css, jsps, jsf pages,...) - 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 должно войти в модуль репозиториев, так как нам не нужно точно знать, что такое реализация. На уровне сервисов мы знаем только интерфейс репозитория, нам все равно, что такое конкретная реализация (разделение проблем).

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Обычно вершина вашего дерева пакетов - это ваше доменное имя, отменяемое (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. Точно так же интерфейс, определяющий константы, будет в одном пакете.

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

Ответ 6

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

Ответ 7

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

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

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

  • com.mycompany.myapp.view
  • com.mycompany.myapp.model
  • com.mycompany.myapp.services
  • com.mycompany.myapp.rules
  • com.mycompany.myapp.persistence(или "dao" для уровня доступа к данным)
  • com.mycompany.myapp.util(остерегайтесь, чтобы это использовалось так, как если бы оно было "разным" ).

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

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

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

Управление Классы функциональных возможностей ядра

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

и др.