Существуют ли передовые практики для организации пакетов (Java)?
Некоторое время назад я увидел ответ на вопрос, касающийся тонкой организации пакетов Java. Например, my.project.util
, my.project.factory
, my.project.service
и т.д.
Я не могу найти его сейчас, поэтому я могу также задать вопрос.
Существуют ли передовые практики в отношении организации пакетов в Java и что с ними происходит?
Как вы организуете свои классы в своем проекте Java?
Например, проект, над которым я работаю с несколькими людьми, имеет пакет, называемый beans. Сначала это был проект, содержащий простые компоненты, но в итоге (из-за плохого опыта и нехватки времени) он содержал все (почти). Я немного их очистил, поместив некоторые фабричные классы в фабричный пакет (классы со статическими методами, которые создают бины), но у нас есть другие классы, которые выполняют бизнес-логику, и другие, которые выполняют простую обработку (не с бизнес-логикой), например, получение сообщение для кода из файла свойств.
Ваши мысли и комментарии приветствуются.
Ответы
Ответ 1
Организация пакетов или структурирование пакетов обычно - это горячая дискуссия. Ниже приведены некоторые простые рекомендации по наименованию и структурированию пакетов:
- Следуйте java соглашения об именах пакетов
- Структура ваших пакетов в соответствии с их функциональной ролью, а также их бизнес-ролью
- Разбивайте свои пакеты в соответствии с их функциональностью или модулями. например
com.company.product.modulea
- Дальнейший отрыв может быть основан на уровнях вашего программного обеспечения. Но не переходите за борт, если у вас всего несколько классов в пакете, тогда имеет смысл иметь все в пакете. например
com.company.product.module.web
или com.company.product.module.util
и т.д.
- Избегайте выхода из строя со структурированием, IMO избегает отдельной упаковки для исключений, заводов и т.д., если нет насущной необходимости.
- Если ваш проект мал, держите его простым в нескольких пакетах. например
com.company.product.model
и com.company.product.util
и т.д.
- Взгляните на некоторые из популярных проектов с открытым исходным кодом на Apache projects. Посмотрите, как они используют структурирование для проектов различного размера.
- Также рассмотрите сборку и распространение при именовании (позволяя вам распространять ваш api или SDK в другом пакете, см. сервлет api)
После нескольких экспериментов и испытаний вы сможете придумать структурирование, с которым вам удобно. Не зацикливайтесь на одном соглашении, открывайте для изменений.
Ответ 2
Я организую пакеты по функциям, а не по шаблонам или ролям реализации. Я думаю, что пакеты, как:
-
beans
-
factories
-
collections
не правы.
Я предпочитаю, например:
поэтому я могу скрыть детали реализации через видимость пакета. Фабрика заказов должна быть в пакете orders
, поэтому детали о том, как создать заказ, скрыты.
Ответ 3
Краткий ответ: один пакет на модуль/функцию, возможно, с подпакетами. Поместите тесно связанные вещи вместе в один и тот же пакет. Избегайте круговых зависимостей между пакетами.
Длинный ответ: Я согласен с большей частью этой статьи
Ответ 4
Я предпочитаю функцию перед слоями, но я думаю, это зависит от вашего проекта. Рассмотрим свои силы:
- зависимости
Попробуйте минимизировать зависимости пакетов, особенно между функциями. Извлечение API, если это необходимо. - Организация команды
В некоторых организациях команды работают над функциями, а в других - над слоями. Это влияет на то, как организован код, использовать его для формализации API или поощрения сотрудничества. - Развертывание и управление версиями
Помещение всего в модуль упрощает развертывание и управление версиями, но затрудняет исправление ошибок. Разделение вещей обеспечивает лучший контроль, масштабируемость и доступность. - Ответить на изменение
Хорошо организованный код гораздо проще изменить, чем большой шарик грязи. - Размер (люди и строки кода)
Чем больше, тем более формализованным/стандартизированным оно должно быть. - Важность/качество
Некоторые коды важнее других. API должны быть более стабильными, чем реализация. Поэтому оно должно быть четко отделено. - Уровень абстракции и точка входа
Для постороннего должно быть возможно узнать, о чем код, и с чего начать чтение, посмотрев на дерево пакетов.
Пример:
com/company/module
+ feature1/
- MainClass // The entry point for exploring
+ api/ // Public interface, used by other features
+ domain/
- AggregateRoot
+ api/ // Internal API, complements the public, used by web
+ impl/
+ persistence/
+ web/ // presentation layer
+ services/ // Rest or other remote API
+ support/
+ feature2/
+ support/ // Any support or utils used by more than on feature
+ io
+ config
+ persistence
+ web
Это всего лишь пример. Это довольно формально. Например, он определяет 2 интерфейса для feature1. Обычно это не требуется, но может быть хорошей идеей, если разные люди используют их по-разному. Вы можете позволить внутреннему API расширять общедоступность.
Мне не нравятся имена 'impl' или 'support', но они помогают отделить менее важные вещи от важных (домен и API). Когда дело доходит до именования, мне нравится быть максимально конкретным. Если у вас есть пакет с именем 'utils' с 20 классами, переместите StringUtils
в support/string, HttpUtil
в support/http и так далее.
Ответ 5
Есть ли лучшие практики в отношении организации пакетов на Java и что происходит в них?
На самом деле нет. Есть много идей и много мнений, но "наилучшей практикой" является использование вашего здравого смысла!
Однако есть один принцип, который, вероятно, имеет широкое признание. Ваша структура пакета должна отражать структуру вашего приложения (неформального), и вы должны стремиться минимизировать (или идеально полностью избегать) любые циклические зависимости между модулями.
(Циклические зависимости между классами в пакете/модуле просто прекрасны, но межпакетные циклы обычно затрудняют понимание архитектуры приложения и могут быть препятствием для повторного использования кода. В частности, если вы используете Maven, вы будете найти, что циклические отношения между пакетами/межмодулями означают, что весь взаимосвязанный беспорядок должен быть одним артефактом Maven.)
Я также должен добавить, что существует одна широко распространенная практика для имен пакетов. И это то, что имена ваших пакетов должны начинаться с имени вашей организации в обратном порядке. Если вы будете следовать этому правилу, вы уменьшите вероятность проблем, вызванных вашими (полными) именами классов, сталкивающимися с другими народами.
Ответ 6
Я видел, как некоторые люди продвигали "пакет за функцией" поверх "пакет за слоем", но я использовал довольно много подходов в течение многих лет и нашел "пакет за слоем" намного лучше, чем "пакет за функцией".
В дополнение к этому я обнаружил, что гибридная стратегия "пакет за модулем, слой, затем функция" работает очень хорошо на практике, поскольку она имеет много преимуществ "пакет за функцией":
- Способствует созданию фреймворков многократного использования (библиотеки с аспектами как модели, так и пользовательского интерфейса)
- Позволяет реализации уровня "включай и работай" - практически невозможно с "пакетом по элементу", потому что он размещает реализации уровня в том же пакете/каталоге, что и код модели.
- Многое другое...
Я подробно объясняю здесь: Структура и организация имени пакета Java, но моя стандартная структура пакета:
revdomain.moduleType.moduleName.layer. [layerImpl].feature.subfeatureN.subfeatureN + 1...
Куда:
revdomain обратный домен, например com.mycompany
moduleType [app * | framework | util]
moduleName, например, myAppName, если тип модуля - приложение, или "финансы", если это учетная структура
слой [модель | пользовательский интерфейс | постоянство | безопасность и т.д.,]
layerImpl, напр., wicket, jsp, jpa, jdo, hibernate (Примечание: не используется, если слой является моделью)
например, финансы
subfeatureN напр., бухгалтерский учет
subfeatureN + 1, например, амортизация
* Иногда "приложение" пропускается, если moduleType является приложением, но его размещение делает структуру пакета согласованной для всех типов модулей.
Ответ 7
Мне не известны стандартные методы организации пакетов. Обычно я создаю пакеты, которые охватывают довольно широкий спектр, но я могу различать в рамках проекта. Например, в личном проекте, над которым я сейчас работаю, есть пакет, посвященный моим настраиваемым элементам управления пользовательским интерфейсом (полный классов, подклассифицирующих классы swing). У меня есть пакет, посвященный моей работе с базой данных, у меня есть пакет для набора слушателей/событий, которые я создал, и т.д.
С другой стороны, у меня был сотрудник, создавший новый пакет практически для всего, что он делал. Каждый другой MVC, который он хотел получить, получил свой собственный пакет, и казалось, что MVC-набор был единственной группой классов, которые разрешены в одном пакете. Я помню, в какой-то момент у него было 5 разных пакетов, в каждом из которых был один класс. Я думаю, что его метод немного экстремален (и команда заставила его сократить количество своих пакетов, когда мы просто не могли справиться с этим), но для нетривиального приложения, так что все было бы в одном пакете. Это баланс, который вы и ваши товарищи по команде должны найти для себя.
Одна вещь, которую вы можете сделать, это попытаться отступить и подумать: если бы вы были новым участником, представленным в проекте, или ваш проект был выпущен как открытый исходный код или API, то насколько легко/сложно было бы найти то, что вы хотеть? Потому что для меня это то, что я действительно хочу из пакетов: организация. Подобно тому, как я храню файлы в папке на своем компьютере, я ожидаю, что смогу найти их снова, не выполняя поиск всего моего диска. Я предполагаю, что могу найти класс, который я хочу, без поиска списка всех классов в пакете.
Ответ 8
Я обычно организовываю слои, потому что я пишу много веб-приложений. Поэтому у меня будет постоянство, сервис, модель, просмотр, использование и т.д.