Я понимаю идею объема пакета, и иногда даже думал, что я хотел это. Однако каждый раз, когда я с серьезным намерением пытался использовать его, я обнаруживал, что он не соответствует потребностям, которые, как я думал, он будет обслуживать.
Моя главная проблема всегда заключается в том, что вещи, которые я хочу ограничить, никогда не находятся в одном пакете. Концептуально все они могут быть связаны, но логическое разделение данных в приложении делает их отдельными дочерними пакетами большего пакета.
Например, у меня может быть модель Миссии, и я хочу, чтобы только другие инструменты Миссии, такие как мои сервисы миссии, использовали некоторые методы. Тем не менее, я получаю в качестве своих пакетов Missions.models и Missions.services, так что MissionModel и MissionService - это не одна и та же область действия пакета. Никогда не кажется, что существует ситуация, когда пакеты надлежащим образом содержат вещи, для которых я хотел бы иметь повышенные разрешения, и не включали в себя множество вещей, которые я не хотел бы иметь этих разрешений; и редко я чувствую преимущество определения объема пакета, когда метод оправдывает изменение архитектуры моего проекта, чтобы поместить все в один пакет. Часто либо Аспекты, либо какая-то инверсия управления оказываются лучшим подходом к любой проблеме, которую я кратко рассматривал для определения объема пакета.
Мне любопытно, что это, как правило, считается верным для всех разработчиков Java, или просто случайность моей работы. Много ли используется объем пакета в реальном мире? Много ли случаев, когда это считается хорошей формой для использования, или это рассматривается в основном как устаревшее поведение, которое редко используется в современной разработке?
Я ничего не спрашиваю о том, почему закрытая область пакета является стандартной, я спрашиваю, когда ее следует использовать независимо от настроек по умолчанию. Большинство дискуссий о том, почему это значение по умолчанию, на самом деле не затрагиваются, когда область действия пакета действительно полезна, вместо этого просто спорят о том, почему две другие часто используемые области не должны быть по умолчанию, поэтому пакет выигрывает в процессе исключения. Кроме того, мой вопрос касается текущего состояния развития. В частности, развили ли мы до такой степени, что другие инструменты и парадигмы делают область применения пакета менее полезной, чем это было тогда, когда решение сделать ее по умолчанию имело смысл.
java.util.String
иjava.util.Integer
.Ответы:
Во всем
java.util.*
пакете есть случаи, когда код написан с защитой на уровне пакета. Например, этот битjava.util.String
- конструктор в Java 6 :или этот метод getChars :
Причина этого заключается в том, что разработчики кода (и их
java.util.*
можно считать довольно большой библиотекой) хотели иметь более высокую производительность за счет потери различной безопасности (проверки диапазона в массивах, прямой доступ к другим полям). это подразумевает реализацию, а не интерфейс, «небезопасный» доступ к частям класса, которые в противном случае считаются неизменяемыми с помощью открытых методов).Ограничивая доступ к этим методам и полям только для других классов в
java.util
пакете, это обеспечивает более тесную связь между ними, но также избегает раскрытия этих деталей реализации миру.Если вы работаете с приложением и вам не нужно беспокоиться о других пользователях, вам не стоит беспокоиться о защите на уровне пакетов. Помимо различных аспектов чистоты дизайна, вы можете сделать все
public
и быть в порядке с этим.Однако, если вы работаете над библиотекой, которая будет использоваться другими (или вы хотите избежать слишком запутывания ваших классов для последующего рефакторинга), вам следует использовать самый строгий уровень защиты, предоставленный вам для ваших нужд. Часто это значит
private
. Иногда, однако, вам нужно немного раскрыть детали реализации другим классам в том же пакете, чтобы избежать повторения или чтобы немного облегчить фактическую реализацию за счет соединения двух классов и их реализаций. Таким образом, уровень защиты пакета.источник
Integer.toString()
иString.valueOf(int)
можете делиться кодом, не раскрывая его миру. Этиjava.util
классы должны работать сообща , чтобы обеспечить больше всей функциональности а не отдельные классы, которые полностью острова к себе - они вместе в пакет и доля функциональных возможностей реализации через уровень пакета обзорного.Иногда я увеличиваю видимость приватных или защищенных методов для упаковки, чтобы позволить junit-тесту получить доступ к некоторым деталям реализации, к которым нельзя обращаться извне.
поскольку тест junit имеет тот же пакет, что и тестируемый элемент, он может получить доступ к этим деталям реализации
пример
Это спорно, если это «хорошее» использование или нет, но это прагматичное
источник
protected
в пакетную сферу?protected
уже предоставляет доступ к пакету. Это немного странно, но я думаю, что они не хотят требовать составных объявлений области видимости, таких какprotected packagescope void doSomething()
(для которых также требуется новое ключевое слово).Это не так уж и полезно, особенно по умолчанию, в мире, где люди склонны использовать точечные имена пакетов, как если бы они были подпакетами. Поскольку в Java нет такого понятия, как подпакет, поэтому xyinternals не имеет больше доступа к xy, чем к ab. Имена пакетов одинаковы или различны, частичное совпадение ничем не отличается от отсутствия общего.
Я предполагаю, что первоначальные разработчики никогда не ожидали, что соглашение будет использоваться, и хотели упростить ситуацию, не добавляя сложность иерархических пакетов в стиле Ada.
Java 9 является своего рода решением этой проблемы, поскольку вы можете поместить несколько пакетов в модуль и экспортировать только некоторые из них. Но это сделает область пакета еще более избыточной.
В идеальном мире они изменили бы область действия по умолчанию на «область видимости модуля, если содержащий модуль существует, в противном случае область видимости пакета». Затем вы можете использовать его для совместного использования реализации внутри модуля, что позволяет проводить рефакторинг без нарушения экспортируемых интерфейсов. Но, может быть, есть какая-то тонкость, почему это нарушит обратную совместимость, или иначе будет плохо.
источник
Тип сцепления ваших описывающее это на самом деле не лучший пример того , где вы будете использовать для доступа к пакету. Пакет удобен для создания компонентов, модулей, которые взаимозаменяемы на интерфейсе.
Вот грубый пример сценария. Предположим, ваш код был реорганизован, чтобы больше соответствовать функциональной сплоченности и компонентизации. Возможно, 3 банки, как:
Используя уровень пакета в Mission5000.java, вы можете быть уверены, что ни один другой пакет или компонент, такой как MissionManager, не может быть тесно связан с реализацией миссии. То есть, только компонент, предоставленный «третьей стороной» от «M co», фактически создает там собственную специальную фирменную реализацию Миссии. Менеджер миссий должен вызвать MissionBuiler.createMission (...) и использовать определенный интерфейс.
Таким образом, если компонент реализации Mission будет заменен, мы знаем, что разработчики MissionManager.jar не обошли API и напрямую использовали реализацию MCo.
Следовательно, мы можем обменять MCo-missionizer5000.jar на конкурирующий продукт. (Или, возможно, макет для юнит-тестирования менеджера миссии)
И наоборот, MCo может скрыть свои секреты коммерческой миссии.
(Это также связано с обеспечением идей нестабильности и абстрактности в компонентах.)
источник
Поскольку область действия пакета в java не разработана иерархически, это вряд ли полезно. Мы вообще не используем область действия пакета и определяем все классы как публичные.
Вместо этого мы используем наши собственные правила доступа, основанные на иерархии пакетов и предварительно определенных именах пакетов.
Если вы заинтересованы в деталях, Google для "CODERU-Правила".
источник