Существуют ли лучшие практики для организации пакетов (Java)? [закрыто]


201

Некоторое время назад я увидел ответ на вопрос, касающийся тонкой организации пакетов Java. Так , например, my.project.util, my.project.factory, my.project.serviceи т.д.

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

Существуют ли передовые практики в отношении организации пакетов на Java и что с ними происходит?

Как вы организуете свои классы в своем проекте Java?

Например, проект, над которым я работаю с несколькими людьми, имеет пакет, называемый beans. Сначала он был проектом, содержащим простые бины, но в итоге (из-за плохого опыта и нехватки времени) содержал все (почти). Я немного очистил их, поместив некоторые фабричные классы в фабричный пакет (классы со статическими методами, которые создают бины), но у нас есть другие классы, которые выполняют бизнес-логику, и другие, которые выполняют простую обработку (не с бизнес-логикой), например, получение сообщение для кода из файла свойств.

Ваши мысли и комментарии приветствуются.


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

Я предлагаю вам прочитать это: assignice.com/blog/archives/5164 . TL; DR ... вся идея "лучших практик" сломана. В лучшем случае это вопиющий неправильный термин, а в худшем - совершенно вредный.
Стивен С.

Ответы:


174

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

  • Следуйте соглашениям об именах пакетов 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 . Посмотрите, как они используют структурирование для проектов разных размеров.
  • Также при сборке имен учитывайте сборку и распространение (позволяя распространять ваш api или SDK в другом пакете, см. Api servlet)

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


Спасибо за ваш ответ. Это в значительной степени то, что мы пытались охватить, но много несвязанного кода попало в наш пакет компонентов, откуда и возник мой вопрос.
Cyntech

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

Согласитесь с вашими точками. Только один момент, чтобы подчеркнуть название компании в упаковке, иногда компания получает проданный продукт. Руководство хочет удалить название компании. Это может быть наверху.
Tushar D

183

Я организую пакеты по функциям , а не по шаблонам или ролям реализации. Я думаю, что пакеты, как:

  • beans
  • factories
  • collections

не правы.

Я предпочитаю, например:

  • orders
  • store
  • reports

поэтому я могу скрыть детали реализации через видимость пакета . Фабрика заказов должна быть в ordersупаковке, поэтому детали о том, как создать заказ, скрыты.


10
Этот пост дает хорошее представление о видимости пакета. Я никогда не видел возможности использования пакета Java, но правильная структура пакета могла бы позволить разработчикам лучше использовать его.
2013 года

23
Это совершенно верно, но немногие разработчики делают это. Пакеты должны быть связными коллекциями классов, некоторые из которых видны только внутри пакета. Это минимизирует связь между классами, которые не должны быть связаны, потому что они относятся к различным функциям. Подход «пакет за слоем» не использует преимущества модификаторов видимости пакетов, и пакеты в таком проекте имеют низкую когезию и высокую степень связи между пакетами.
Нейт Рид

У вас есть пример этого? Я использую Spring-MVC, мне трудно организовать его по функциям / модулям, потому что Spring использует config xml.
Эрик Хуан,

2
@onof Я также систематизирую свой код по функциям, но каковы рекомендации для базовых классов, общих для всех функций?
Марк

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

40

Краткий ответ: один пакет на модуль / функцию, возможно, с подпакетами. Положите тесно связанные вещи в одном пакете. Избегайте циклических зависимостей между пакетами.

Длинный ответ: я согласен с большей частью этой статьи


2
суб-пакеты нарушают инкапсуляцию. «
Рикардо Гамба

21

Я предпочитаю функцию перед слоями, но я думаю, это зависит от вашего проекта. Рассмотрим свои силы:

  • Зависимости
    Попробуйте минимизировать зависимости пакетов, особенно между функциями. Извлечение 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, HttpUtilsupport / http и так далее.


13

Существуют ли передовые практики в отношении организации пакетов на Java и что с ними происходит?

Не на самом деле нет. Есть много идей и много мнений, но настоящая «лучшая практика» - это использовать ваш здравый смысл!

(Пожалуйста, прочтите « Нет лучших практик», чтобы узнать о «лучших практиках» и людях, которые их продвигают.)

Тем не менее, есть один принцип, который, вероятно, имеет широкое признание. Структура вашего пакета должна отражать (неформальную) структуру модуля вашего приложения, и вы должны стремиться минимизировать (или в идеале полностью избежать) любые циклические зависимости между модулями.

(Циклические зависимости между классами в пакете / модуле просто хороши, но циклы между пакетами, как правило, затрудняют понимание архитектуры вашего приложения и могут стать препятствием для повторного использования кода. В частности, если вы используете Maven, вы обнаружите, что циклический межпакетные / межмодульные зависимости означают, что весь взаимосвязанный беспорядок должен быть одним артефактом Maven.)

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


9

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

В дополнение к этому я обнаружил, что гибридная стратегия «пакет за модулем, слой, затем функция» работает очень хорошо на практике, поскольку она имеет много преимуществ «пакет за функцией»:

  • Способствует созданию фреймворков многократного использования (библиотеки с аспектами как модели, так и пользовательского интерфейса)
  • Позволяет реализации уровней plug and play - практически невозможно с помощью «пакет за особенностью», потому что он размещает реализации уровней в том же пакете / каталоге, что и код модели.
  • Многое другое...

Я подробно объясняю здесь: структура и структура имени пакета 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 является приложением, но его размещение делает структуру пакета согласованной для всех типов модулей.


5

Я не знаю стандартных методов организации пакетов. Я обычно создаю пакеты, которые охватывают довольно широкий спектр, но я могу выделиться в рамках проекта. Например, в личном проекте, над которым я сейчас работаю, есть пакет, посвященный моим настраиваемым элементам управления пользовательским интерфейсом (полный классов, подклассов классов свинга). У меня есть пакет, посвященный моему управлению базой данных, у меня есть пакет для набора слушателей / событий, которые я создал, и так далее.

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.