Чи є найкращі практики для організації пакетів (Java)? [зачинено]


201

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

Зараз я не можу його знайти, тому я можу також задати питання.

Чи є найкращі практики щодо організації пакетів на Java і що стосується них?

Як ви організовуєте свої заняття в проекті Java?

Наприклад, проект, над яким я працюю з кількома людьми, має пакет під назвою квасоля. Він почав бути проектом, що містить просту квасолю, але закінчився (через поганий досвід та брак часу), що містить усе (майже). Я їх трохи очистив, помістивши кілька заводських класів у заводський пакет (класи зі статичними методами, що створюють квасоля), але у нас є інші класи, які працюють з бізнес-логікою, та інші, які виконують просту обробку (не з діловою логікою), наприклад, отримання. повідомлення про код з файлу властивостей.

Ваші думки та коментарі цінуються.


74
Я не згоден із закриттям цього питання. Я не погоджуюся з тим, що питання найкращої практики майже завжди ґрунтуються на досвіді та думці, однак я не погоджуюся з тим, що ці питання слід закрити в режимі переповнення стека. У цьому полягає суть хорошого програмування, використання кращих практик та пошуку найкращого рішення, використовуючи ці думки та досвід. Повторіть це запитання.
Синтех

Пропоную прочитати це: satisfice.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 сервлетів)

Після декількох експериментів і випробувань ви зможете придумати структуру, яку вам зручно. Не зациклюйтесь на одній конвенції, будьте відкриті до змін.


Дякую за Вашу відповідь. Це значною мірою те, що ми намагалися охопити, але багато непов'язаного коду потрапило до нашого пакету бобів, саме звідки і з’явилося моє запитання.
Синтех

2
Я погоджуюся, що пакет за функцією має найбільше значення. Я чув чудову аналогію, колись пов’язану зі структурою офісу компанії. У шаруватому підході кожен з людей на рівні в компанії буде сидіти один з одним, тобто керівники, менеджери, адміністратор, працівники / працівники сидять в окремих секціях будівлі. Ця структура, ймовірно, не настільки ефективна, як організований підхід "особливості". Тобто, якщо керівник відділу продажів сидить із менеджером з продажу, який сидить із співробітниками відділу продажів, які всі сидять із адміністратором з продажу. Це забезпечує кращу згуртованість між відділом, якщо організовано таким чином.
alex

Погодьтеся з вашими балами. Всього лише один момент, щоб підкреслити назву компанії в пакеті, коли компанія отримує проданий продукт. Керівництво хочуть видалити назву компанії. Це може бути накладними.
Тушар Д

183

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

  • beans
  • factories
  • collections

помиляються.

Я віддаю перевагу, наприклад:

  • orders
  • store
  • reports

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


10
Ця публікація дає хорошу думку про видимість пакету. Я ніколи не бачив сфери пакетів Java у використанні, але правильна структура пакету могла б дати змогу розробникам скористатися ними.
Jpnh

23
Це абсолютно правильно, але мало хто з розробників робить це. Пакети повинні бути згуртованими колекціями класів, деякі з яких є видимими лише в упаковці. Це дозволило б мінімізувати зв’язок між класами, які не повинні бути пов'язані, оскільки вони стосуються різних особливостей. Пакетно-шаровий підхід не використовує переваг модифікаторів видимості пакунків, і пакети в такому проекті мають низьку згуртованість і високий ступінь зв'язку між пакетами.
Нейт Рид

У вас є приклад цього? Я використовую Spring-MVC, мені важко впорядкувати його за функцією / модулем, оскільки весна використовує 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 інтерфейси для element1 . Зазвичай це не потрібно, але це може бути хорошою ідеєю, якщо його використовувати різні люди. Ви можете дозволити внутрішньому API розширити загальний доступ.

Мені не подобаються імена 'impl' або 'support', але вони допомагають відокремити менш важливі речі від важливих (домен та API). Що стосується найменування, то я люблю бути максимально конкретним. Якщо у вас є пакет під назвою 'utils' з 20 класами, перейдіть StringUtilsдо support / string, HttpUtilto support / http тощо.


13

Чи є найкращі практики щодо організації пакетів на Java і що стосується них?

Не дуже. Ідей та думок багато, але справжня "найкраща практика" - це використовувати здоровий глузд!

(Будь ласка, прочитайте " Не найкращі практики", щоб побачити "найкращі практики" та людей, які їх просувають.)

Однак є одна головна, яка, ймовірно, має широке визнання. Структура пакета повинна відображати (неформальну) структуру модуля вашої програми, і ви повинні прагнути мінімізувати (або в ідеалі цілком уникати) будь-яких циклічних залежностей між модулями.

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

Я хотів би також додати , що це один широко визнані найкраща практика для назв пакунків. Це означає, що назви ваших пакетів повинні починатися з доменного імені вашої організації у зворотному порядку. Якщо ви дотримуєтесь цього правила, ви знижуєте ймовірність виникнення проблем, спричинених зіткненням ваших (повних) класів із іншими народами.


9

Я бачив, як деякі люди рекламують "пакунок за функцією" над "пакунок за шаром", але я використовував досить багато підходів протягом багатьох років і виявив, що "пакет за шаром" набагато краще, ніж "пакет за функцією".

На додаток до цього я виявив, що гібридна стратегія "пакунок за модулем, шаром та функцією" працює на практиці надзвичайно добре, оскільки має багато переваг "пакет за функцією":

  • Сприяє створенню багаторазових фреймворків (бібліотеки з аспектами моделі та інтерфейсу)
  • Дозволяє реалізація шарів підключення та відтворення - практично неможливо з "пакунком за функцією", оскільки він розміщує реалізацію шару в тому ж пакеті / каталозі, що і код моделі.
  • Набагато більше...

Я пояснюю тут глибоко: Структура і організація імені пакета Java, але моя стандартна структура пакунків:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

Де:

revdomain Зворотний домен, наприклад, com.mycompany

moduleType [додаток * | фреймворк | util]

moduleName, наприклад, myAppName, якщо тип модуля - це додаток, або "фінанси", якщо його структура обліку

шар [модель | ui | стійкість | безпека тощо),]

layerImpl, наприклад, wicket, jsp, jpa, jdo, hibernate (Примітка: не використовується, якщо шар є моделлю)

особливість, наприклад, фінанси

subfeatureN наприклад., бухгалтерський облік

підрядністьN + 1 напр., амортизація

* Іноді "додаток" залишається, якщо moduleType є додатком, але введення його в систему робить структуру пакету послідовною для всіх типів модулів.


5

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

З іншого боку, у мене був співробітник, який створив новий пакет майже для всього, що він робив. Кожен різний MVC, якого він хотів, отримав свій власний пакет, і здавалося, що набір MVC - це єдине угруповання класів, дозволених бути в одному пакеті. Пригадую, в один момент у нього було 5 різних пакетів, кожен з яких мав в них один клас. Я думаю, що його метод трохи на крайньому рівні (і команда змусила його зменшити кількість пакунків, коли ми просто не змогли впоратися з цим), але для нетривіального додатку, тому було б помістити все в один і той же пакет. Це точка балансу, яку ви та ваші товариші по команді повинні знайти для себе.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.