Должны ли мои внутренние классы API быть в одном пакете?

Я с трудом собираю API для общественного потребления. Как таковой я пытаюсь ограничить методы, которые подвергаются только тем, которые я хочу быть общедоступными и поддерживаемыми. Под этим, конечно, существует множество методов ограниченного доступа.

Проблема в том, что у меня есть много внутреннего кода, который должен получить доступ к этим ограниченным методам, не открывая эти методы. Это создает две проблемы:

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

Итак, у меня есть около 70 или 80 внутренних классов в чисто разделенных пакетах, но с чрезмерно разрешительными модификаторами доступа. Скажете ли вы, что один пакет является меньшим из двух зол или есть лучший способ укрыть мои внутренние методы, сохраняя при этом более гранулированные пакеты?

Мне было бы интересно узнать о лучшей практике здесь.

Я уже знаю Это

Ответ 1

Есть два решения вашего вопроса, которые не включают в себя сохранение всех классов в одном пакете.

Во-первых, используйте шаблон Friend Accessor/Пакет друзей, описанный в (Практический дизайн API, Tulach 2008).

Вторым является использование OSGi. Здесь приведена статья объясняющая, как это делает OSGi.

Вопросы, относящиеся: 1, 2, 3 и 4.

Ответ 2

Одним из примеров может быть Servlet API, поскольку вы видите, что они разделили общий API сервлета и http на два пакета.

Если вы отделите свой код в api.jar и implementation.jar, вы можете использовать интерфейсы для своей реализации, которые не видны пользователям api.jar. Если объекты классов, независимо от их пакета, должны каким-либо образом сотрудничать, то методы, конечно, должны быть видимыми (по крайней мере, в реализации).

Ответ 3

Да, вы просто не можете защитить данные внутренней реализации от доступа. Существуют некоторые технологии (например, OSGi), которые предлагают решение для этого во время запуска/запуска приложений. Это недостаток модульной модуляции языка java (но также очень сложно добавить впоследствии из-за пониженной совместимости).

Мне нравится соглашение добавлять публично видимые артефакты к /api пакетам и внутренним элементам в /internal. В конце концов вы закончите с.


# this package is allowed to be accessed by api-users
com.foo.users.api
# this is completely internal logic (api implementation)
# should only be touched by the api-module itself.
com.foo.users.internal

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

Как и вышеприведенный сервлет-api, вы можете еще больше разделить api против impl на разные банки. Но это требует больше усилий для создания жизненного цикла и поддержания модулей, поэтому я бы сделал это только там, где имеет смысл полный раскол артефакта времени исполнения (например, в jsr-spec vs. impl).