Как обойти отсутствие спецификаторов доступа к пакетам? - PullRequest
1 голос
/ 08 марта 2012

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

Это делает довольно сложным организацию внутренних деталей реализации моей публичной библиотеки в логические единицы связанной функциональности при сохранении хорошей инкапсуляции. JSR 294 объясняет это лучше всего:

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

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

Итак, мой вопрос: какие обходные пути существуют для этого ограничения и каковы плюсы и минусы? Два упомянутых в JSR - использовать пакеты для логической группировки (нарушая инкапсуляцию); поместите все в одну упаковку (громоздко). Есть ли другие плюсы / минусы этих обходных путей? Есть ли другие решения? (Я смутно осознавал комплекты OSGi, но мне было трудно понять, как они работают и каковы могут быть плюсы / минусы (возможно, это мошенничество). Это кажется очень навязчиво по сравнению с пакетами vanilla, для разработки и развертывания.

Примечание: я буду одобрять любые хорошие ответы, но ответ best будет таким, который всесторонне сворачивает плюсы и минусы других (плагиат!).

Смежные (но не дублирующие!) Вопросы

Предвосхищая крики «Возможный дубликат», вот похожих вопросов, которые я нашел на SO; Я представляю их здесь для справки, а также для объяснения, почему они не отвечают на мой вопрос.

Ответы [ 3 ]

0 голосов
/ 08 марта 2012

Я получу мяч катится.Украдите этот ответ и добавьте к нему / исправьте его / уточните пожалуйста!

Используйте несколько пакетов для нескольких логических групп

Плюсы : эффективная логическая группировка связанного кода.

Минусы : когда внутренние классы деталей реализации в разных пакетах должны использовать друг друга, они должны быть обнародованы - даже для конечного пользователя - нарушая инкапсуляцию.(Чтобы обойти это, используйте стандартное соглашение об именах для пакетов, содержащих внутренние детали реализации, такие как .internal или .impl).

Поместите все в один пакет

Плюсы : эффективная инкапсуляция

Минусы : неудобно для разработки / обслуживания библиотеки, если она содержит много классов

Использование пакетов OSGi

Плюсы :?(они решают проблему?)

Минусы : кажется очень навязчивым при разработке (для пользователя и автора библиотеки) и развертывании, по сравнению с простым развертыванием файлов .jar.

Ожидание Jigsaw в Java 8

http://openjdk.java.net/projects/jigsaw/

Плюсы : исправляет проблему навсегда?

Минусы : пока не существует, точная дата выпуска неизвестна.

0 голосов
/ 08 марта 2012

Я никогда не находил это проблемой. Обходной путь (если вы хотите так его назвать) называется хороший дизайн API .

Если вы хорошо спроектируете свою библиотеку, то вы почти всегда можете сделать следующее:

  • Поместите основной публичный API в один пакет, например. «my.package.core» или просто «my.package»
  • Поместите вспомогательные модули в другие пакеты (в соответствии с логическими группировками), но предоставьте каждому свой собственный общедоступный набор API (например, фабричный класс, такой как "my.package.foobarimpl.FoobarFactory")
  • Основной открытый пакет API использует только открытый API вспомогательных модулей
  • Ваши тесты также должны выполняться в первую очередь на общедоступных API-интерфейсах (поскольку это то, что вас волнует с точки зрения регрессий или функциональности)

Для меня «правильный уровень инкапсуляции» для пакета заключается в том, чтобы предоставить достаточно публичного API, чтобы ваш пакет мог эффективно использоваться в качестве зависимости. Не больше и не меньше. Не должно иметь значения, используется ли он другим пакетом в той же библиотеке или внешним пользователем. Если вы разрабатываете свои пакеты в соответствии с этим принципом, вы увеличиваете вероятность эффективного повторного использования.

Создание частей пакета «глобально доступным» на самом деле не приносит никакого вреда, если ваш API достаточно хорошо разработан. Помните, что пакеты не являются объектными экземплярами, и в результате инкапсуляция не имеет большого значения: сделать элементы пакета общедоступными обычно намного менее вредно, чем раскрытие внутренних деталей реализации класса (что я согласен почти всегда должен быть приватным / защищенным).

Рассмотрим, например, java.lang.String. У него большой публичный API, но что бы вы ни делали с публичным API, оно не может мешать другим пользователям java.lang.String. Совершенно безопасно использовать в качестве зависимости от нескольких мест одновременно. С другой стороны, весь ад развалился бы, если бы вы позволили пользователям java.lang.String иметь прямой доступ к внутреннему массиву символов (что позволило бы на месте изменять неизменяемые строки .... неприятно !!).

P.S. Похвальное упоминание идет в OSGi, потому что это довольно удивительная технология и очень полезная во многих обстоятельствах. Тем не менее, его приятное место действительно связано с развертыванием и управлением жизненным циклом модулей (остановка / запуск / загрузка и т. Д.). Вам не нужно это для организации кода ИМХО.

0 голосов
/ 08 марта 2012

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

...