Як інкапсулювати внутрішні класи в API, написаному на Java?


9

Треба написати бібліотеку. Природно, він повинен мати лише дуже невеликий API (якомога ширший, наскільки можливий). Внутрішня бібліотека дещо складна. Тому вони потребують структурування.

Для структуризації я зараз бачу два способи:

1. використовувати пакети.

плюси: бібліотека може бути акуратно структурована. Все на свої місця.

Мінуси: використання класів через межі пакетів потребує загальнодоступних класів і, отже, розширює API всієї бібліотеки.

2. використовуйте статичні внутрішні класи, все в одному пакеті.

плюси: потрібно лише дуже мало публічних речей (заняття, методи тощо).

Мінуси: Класи приховані лише для їх структури. Це був би один з небагатьох випадків використання, коли використовується стільки статичних внутрішніх класів. Розробники до цього не звикли і можуть їх не помітити.


Чи є кращий спосіб досягти невеликого API в добре структурованій бібліотеці?

Редагувати: я забув згадати: це для бібліотеки Android. Тому ніякої ja9.


Чому ваші внутрішні класи повинні бути статичними?
Девід Арно

Чи внутрішні класи не збільшують кодові одиниці? Я маю на увазі, клас з кількома внутрішніми класами може стати дуже довгим.
Tulains Córdova

2
@ TulainsCórdova, добре, я читаю термін "внутрішній" як "внутрішній", який я думаю, що Java називає "пакет-приватний". Нормальний спосіб створити lib - це, безумовно, мати один пакет, який містить кілька публічних класів, при цьому все інше є внутрішнім / пакетним-приватним.
Девід Арно

Привіт @frmarkus. Я намагався переписати назву вашого питання, щоб бути більш конкретним і уникати закритих голосів "незрозуміло, що ви запитуєте". Не соромтесь відредагувати його, якщо ви вважаєте, що це неправильно представляє ваше фактичне запитання.
Андрес Ф.

1
@ TulainsCórdova: Так, кодові одиниці отримують шлях до великого (3k рядків коду на файл). Це ще одна важлива проблема такого способу структурування.
Маркус Фрауенфелдер

Відповіді:


1

Я бачу, що ви робите з 2. Ви використовуєте класи як пакети, а пакети - як модулі, щоб ви могли ізолювати себе в пакеті, але все-таки впорядковувати його в межах пакета за допомогою класів.

Це дуже розумно. Остерігайтеся розумних.

Це змусить вас заклинювати кілька класів у одному вихідному файлі (який ви могли б віддати перевагу), і на шляху з'явиться додаткове слово з великої літери.

Це також змусить вас написати будь-який тестовий код у пакеті, якщо ви не використовуєте роздуми, щоб зламати свій шлях ззовні.

Якщо це не так, це спрацює. Це просто здасться дивним.

Люди більше звикли до внутрішніх класів, які використовуються як EntrySet в Hashtable . Це приватне, тому я не можу його створити, але він реалізує загальнодоступний інтерфейс, тому я просто розмовляю з ним через інтерфейс і щось захоплюю для мене.

Але ви описуєте заняття, з якими не хочете, щоб я спілкувався навіть через інтерфейс. Так що для мене немає інтерфейсу. Це означає, що я не маю на що дивитись і збивати з пантелику (якщо ви не надасте мені джерело).

Найбільша проблема, яку я передбачу, - це заплутана новичка, що підтримує API. Ви можете кидати на них документацію та коментарі, але не завищуйте їх, коли вони не читають і не довіряють ні одному.

Ви створили ще одну модель, яка компенсує дефіцит мови. У Java немає модифікатора доступу, який надає доступ до групи пакетів. Я чув, що був запропонований модифікатор доступу "модуль", але не бачу ознак цього.

Модифікатор доступу за замовчуванням (без модифікатора), швидше за все, ви будете використовувати тут, якщо ви не заперечуєте, щоб я прокрався через спадщину, в цьому випадку захищений.

Modifier        Class     Package   Subclass  World
public          Y         Y         Y         Y
protected       Y         Y         Y         N
no modifier     Y         Y         N         N
private         Y         N         N         N 

Те, що вам справді хочеться, це модульний доступ. Таким чином ви могли б тримати свої тести в одному пакеті, а в іншому - код. На жаль, у нас його немає на Java.

Більшість людей просто роблять 1 і розширюють API. Правильне використання інтерфейсів утримує тиск від впровадження.

Зламати те, що ви хочете в 1, ще жахливіше. Зазирніть у стек викликів і киньте виняток, коли те, що вам дзвонило, із пакету, який вам не подобається. Очі.


3

У кожному разі розділіть свій код на пакети. Це пройде довгий шлях до покращення ремонту.

Щоб уникнути доступу кінцевих користувачів до речей, які вони не повинні, потрібно розділити свій API на інтерфейс та реалізацію.

Це можна зробити дуже буквально, визначивши весь API в інтерфейсі Java та надавши деяку кількість заводських класів для створення об’єктів реалізації. Це те, що робить JDBC.

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


1
На жаль, це повне не йде. Це залишає багато громадських класів. Вони можуть мати підказки (бути фабриками або "внутрішніми"). Але я повинен застосувати додаткові інструменти до них (до всього публічного класу), це просто не добре.
Маркус Фрауенфелдер

@frmarkus - Я думаю, що (1) ви очікуєте занадто багато поза контролем доступу, або (2) вам потрібно переосмислити структуру вашого пакета, щоб класи з одного пакету не потребували залежності від класів з іншого пакет (якщо ви можете зберегти все як статичні вкладені класи, це не повинно бути складним).
kdgregory
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.