Saturday, October 8, 2011

[ RUS | Manual | Project ] Project's directory/package structure

Структура пакетов и папок в проекте.
В первый раз, когда сталкиваешься с задачей создания структуры папок/пакетов внутри своего проекта - долго не можешь понять - зачем создавать такие сложные бессмысленные вложенности, как например 'src/main/java', а потом делать еще не менее непонятные вложенности вроде 'com.makeappinc.calculator.context'. Неужели не проще сразу располагать все свои пакеты и классы/файлы/ресурсы в корневой папке 'src'? Зачем делать параллельную ветку каталогов 'src/main/resources'?

Отвечаю:
Не проще, подобные мелочи сразу избавляют тебя от огромных проблем в будущем. Делай так и будешь счастлив!
А сейчас я объясню почему :)


Для начала давайте взглянем на такую структуру папок:
calculator/src/main/java/com/makeappinc/calculator/context/

Не правда ли ужасно? Но не паникуй! Сейчас все станет на свои места :)
Здесь можно выделить четыре основных логических части:

  • calculator/ - корневой каталог проекта
  • src/main/java/ - структура папок соответствующая соглашению Maven Directories Layout (именно как контейнер java исходников)
  • com/makeappinc/calculator/ - путь к корневому каталогу приложения (в данном случае к приложению calculator)
  • context/ - вложенный пакет самого приложения


Давайте разберемся что же они означают.

Корневой каталог проекта. [ calculator/ ]
Это каталог, являющийся корневым каталогом всего проекта. На самом деле, в общем случае он содержит только следующие три элемента:
  • src/
  • target/ (данная папка может появится как результат выполнения сборки проекта Maven'ом)
  • pom.xml

Мавен ожидает, что каталог 'src' - это папка, которая содержит абсолютно все данные, относящиеся к исходникам проекта. Поэтому именно внутри нее следует размещать следующие виды данных: исходные коды, ресурсы, настройки, картинки, мета-информацию о проекте или различные дескрипторы.
Но в случае с папкой 'target' все иначе. Эта папка изначально не существует и является грубо говоря - рабочей папкой Maven'а. Внутри этой папки Maven сохраняет все результаты сборки проекта - как скомпилированные классы (если такие есть), так и различные jar/war/ear/pom файлы (если это требуется).


Maven Directory Layout. [ src/main/java/ ]
Эта часть соответствует соглашениям по структуре папок для Maven'a. Подробней можно ознакомится здесь [ http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html ]

Итак, если необходимо разместить исходные коды проекта, то для этого нужно выбрать папку:
src/main/java

Различные файлы настроек, картинки, xml следует сохранять в этой папке:
src/main/resources

А если, к примеру, необходимо создать тесты на java, то их лучше расположить здесь:
src/test/java

Замечу:
Это неимоверно удобно, логично и правильно хранить разные виды данных отдельно - в разных частях проекта. Ты всегда знаешь где стоит искать настройки, где лежат только исходные коды на java и тебе абсолютно не важно - знаешь ли ты всю структуру проекта целиком или нет. Так же нет необходимости описывать Maven'у где находятся данные папки с тестами/исходными кодами/ресурсами - он и без тебя уже все это знает! :)


Корневой каталог приложения. [ com/makeappinc/calculator/ ]
Лучше всего представить себе, что данная вложенность папок - является неким ID вашего приложения :) Его паспортными данными или серийным номером. Это одна из вещей, которая позволяет вам всегда и везде распознать любые ресурсы вашего приложения. Но самое главное, это дает определенные гарантии, что вы не столкнетесь с разного рода коллизиями имен пакетов, классов или файлов при вгрузке в JVM, потому что данный подход в значительной мере исключает ситуацию существования пакетов в других jar идентичных по названию с вашими пакетами. К примеру, если у вас есть корневой пакет приложения 'src' внутри которого вы создали класс 'Main.class', то в случае, если в JVM будет загружен другой класс 'Main.class', относящийся к такому же пакету 'src', то произойдет ошибка обращения к классу, т.к. Classloader не поймет, какую из двух одноименных реализаций от него требуют. Все осложняется тем, что java программы практически всегда используют огромное количество сторонних библиотек, влиять на структуру которых нет возможности. Поэтому следует делать все от вас зависящее, чтобы избегать совпадения наименования ваших пакетов с чужими. Именно поэтому, проще всего решить такую проблему путем введения зависимости названия ваших пакетов от лично ваших ID/названия фирмы/имени/nickname'а, а так же от названия самого приложения (т.к. это обеспечит различие названия пакетов уже между вашими проектами).

Корневой каталог состоит из двух частей:
  • com.makeappinc - перевернутое доменное имя вашей компании, брэнда, команды или вас лично, которое явно указывает на вашу организацию или на вашу личность. К примеру, если ваша компания называется 'appla' и у нее имеется доменное имя 'appla.org', то эта часть будет выглядеть так: 'org.appla'. В другом случае, если у вас есть ник 'gadget' и даже если у вас нет какого-либо собственного web-ресурса, вы можете создать такой пакет: 'org.gadget'.
  • calculator - просто название вашего приложения

Вложенный пакет самого приложения. [ context/ ]
Конечно же, в случае если вы пишите простенькое java-приложение вроде "Hello World!", то нет нужды создавать какие-то дополнительные пакеты. Но это становится абсолютно необходимым при разработке больших приложений. Т.к. зачастую не знаешь во что вырастет твое приложение - крайне рекомендую начинать использовать пакетную структуру приложения сразу же, как только начнете писать свое приложение. Я не стану в этой статье детально объяснять философию создания пакетов в приложении, скажу лишь, что можно создавать любые пакеты взамен или рядом с пакетом из примера 'context', а также вложенные в них, если это вам необходимо.

No comments: