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

Элемент, который вы пытались найти, не был в DOM , когда ваш скрипт работал.

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

Рассмотрим следующую разметку; сценарий # 1 не находит

, а сценарий # 2 преуспевает:


test div

Итак, что вы должны делать? У вас есть несколько вариантов:


Вариант 1: Переместите свой скрипт

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


  
  

Примечание: размещение скриптов внизу как правило, считается лучшей практикой .


Вариант 2: jQuery's ready()

Отмените свой сценарий до тех пор, пока DOM не будет полностью проанализирован, используя ready() :



Примечание. Вы можете просто привязать к DOMContentLoaded или window.onload, но у каждого есть свои оговорки. jQuery ready() предоставляет гибридное решение.


Вариант 3: Делегирование событий

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

blockquote>

Когда элемент вызывает событие (при условии, что это bubbling g6], и ничто не останавливает его распространение), каждый родитель в родословной этого элемента также получает событие. Это позволяет нам привязать обработчик к существующему элементу и примерным событиям, когда они пузырятся от его потомков ... даже те, которые добавлены после присоединения обработчика. Все, что нам нужно сделать, это проверить событие, чтобы узнать, был ли он поднят нужным элементом и, если да, запустите наш код.

jQuery on() выполняет эту логику для нас. Мы просто предоставляем имя события, селектор для желаемого потомка и обработчик событий:



Примечание: Обычно этот шаблон зарезервированы для элементов, которые не существовали во время загрузки или , чтобы избежать прикрепления большого количества обработчиков. Также стоит отметить, что, пока я прикреплял обработчик к document (для демонстрационных целей), вы должны выбрать ближайшего надежного предка.


Вариант 4: Атрибут defer

Используйте атрибут defer в

Для справки, вот код из этого внешнего скрипта :

document.getElementById("test").addEventListener("click", function(e){
   console.log("clicked: %o", this); 
});

Примечание: атрибут defer, безусловно, кажется , как волшебная пуля , но важно знать об оговорках ... 1. defer может использоваться только для внешних скриптов, т. е. для тех, у кого есть атрибут src. 2. знать о поддержке браузера , то есть: ошибка реализации в IE & lt; 10

40
задан 9 revs, 5 users 39% 2 November 2017 в 22:11
поделиться

10 ответов

Я действительно приехал для симпатии Знатока Стандартное Расположение Каталога .

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

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

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

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

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

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

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

27
ответ дан rzo 27 November 2019 в 01:42
поделиться

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

/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) и имен классов, отражающих аспект ООП, который Вы создаете с классом (см. других комментаторов). Общие имена пакета как util, представление модели , , события полезны, также.

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

12
ответ дан cringe 27 November 2019 в 01:42
поделиться

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

Каждый модуль уважает стандартную структуру проекта знатока:

   src\
   ..main\java
     ...\resources
   ..test\java
     ...\resources

Модульные тесты на данный слой легко находят свое место под \src\test... Все, что является зависящим от домена, имеет, это - место в модуле объектов. Теперь что-то как FileStorageStrategy должно войти в модуль репозиториев, так как мы не должны знать точно, какова реализация. В сервисном слое мы только знаем интерфейс репозитория, мы не заботимся о том, что определенная реализация (разделение проблем).

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

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

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

11
ответ дан Sébastien D. 27 November 2019 в 01:42
поделиться

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

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

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

4
ответ дан graham.reeds 27 November 2019 в 01:42
поделиться

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

Обычно вершина Вашего дерева пакета является Вашим доменным именем, инвертированным (com.domain.subdomain) для гарантии уникальности, и затем обычно будет пакет для приложения. Тогда подразделите это связанной областью, таким образом, Ваш FileStorageStrategy мог бы войти, скажем, com.domain.subdomain.myapp.storage, и затем мог бы быть определенный implementations/subclasses/whatever в com.domain.subdomain.myapp.storage.file и com.domain.subdomain.myapp.storage.database. Эти имена могут стать довольно длинными, но import сохраняет их всех наверху файлов, и IDE могут помочь управлять этим также.

Исключения обычно входят в тот же пакет как классы, которые бросают их, поэтому если бы Вы имели, скажем, FileStorageException, то он вошел бы в тот же пакет как FileStorageStrategy. Аналогично интерфейс, определяющий константы, был бы в том же пакете.

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

3
ответ дан Kieron 27 November 2019 в 01:42
поделиться

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

3
ответ дан 27 November 2019 в 01:42
поделиться

Короткий ответ: потяните свою архитектуру системы с точки зрения модулей, оттянутых бок о бок, с каждым модулем, нарезанным вертикально на слои (например, представление, модель, персистентность). Тогда используйте структуру как 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.ser vices
  • com.mycompany.myapp.rules
  • com.mycompany.myapp.persistence (или 'дао' для уровня доступа к данным)
  • com.mycompany.myapp.util (остерегаются этого используемого, как будто это был 'misc')

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

3
ответ дан Peter Hilton 27 November 2019 в 01:42
поделиться

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

2
ответ дан Michael Neale 27 November 2019 в 01:42
поделиться

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

0
ответ дан bpapa 27 November 2019 в 01:42
поделиться

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

, Например: Model For связанные с базой данных вызовы

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

Управление классы Базовой функциональности

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

и т.д.

0
ответ дан Bryan Denny 27 November 2019 в 01:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: