Come incapsulare le classi interne in un'API scritta in Java?


9

Dobbiamo scrivere una biblioteca. Naturalmente, dovrebbe avere solo un'API molto piccola (quanto più ampia possibile quanto più piccola possibile). Gli interni della biblioteca sono piuttosto complessi. Pertanto, hanno bisogno di strutturazione.

Per la strutturazione attualmente vedo due modi:

1. usa i pacchetti.

pro: la biblioteca può essere ben strutturata. Tutto al suo posto.

contro: l' uso delle classi attraverso i bordi dei pacchetti necessita di classi pubbliche e quindi ampliare l'API dell'intera libreria.

2. usa classi interne statiche, tutto in un unico pacchetto.

pro: solo poche cose pubbliche (classi, metodi ecc.) necessarie.

contro: le classi sono nascoste solo per strutturarle. Questo sarebbe uno dei pochissimi casi in cui vengono utilizzate così tante classi interne statiche. Gli sviluppatori non ci sono abituati e potrebbero trascurarli.


Esiste un modo migliore per ottenere una piccola API in una libreria ben strutturata?

Modifica: ho dimenticato di menzionare: è per una libreria Android. Pertanto, no java9.


Perché le tue classi interne devono essere statiche?
David Arno,

Le classi interne non ingrandiscono le unità di codice? Voglio dire che una classe con diverse classi interne può diventare molto lunga.
Tulains Córdova,

2
@ TulainsCórdova, buon punto, ho letto il termine "interno" come "interno", che secondo me Java chiama "pacchetto-privato". Il modo normale di creare una libreria è sicuramente avere un pacchetto, contenente alcune classi pubbliche, con tutto il resto come interno / pacchetto-privato.
David Arno,

Ciao @frmarkus. Ho provato a riscrivere il titolo della tua domanda per essere più specifico ed evitare voti stretti "poco chiari su ciò che stai chiedendo". Sentiti libero di modificarlo nuovamente se ritieni che rappresenti in modo errato la tua vera domanda.
Andres F.

1
@ TulainsCórdova: Sì, le unità di codice diventano grandi (3k righe di codice per file). Questo è un altro importante problema di questo modo di strutturare.
Markus Frauenfelder,

Risposte:


1

Vedo cosa stai facendo con 2. Stai usando le classi come pacchetti e pacchetti come moduli in modo da poterti isolare all'interno del pacchetto ma comunque organizzare all'interno del pacchetto usando le classi.

È molto intelligente. Attenzione ai furbi.

Questo ti costringerà a bloccare più classi nello stesso file sorgente (che potresti preferire) e il percorso avrà una parola maiuscola in più.

Questo ti costringerà anche a scrivere qualsiasi codice di prova all'interno del pacchetto a meno che tu non usi la reflection per entrare dall'esterno.

A parte questo, funzionerà. Sembrerà strano.

Le persone sono più abituate alle classi interne utilizzate come EntrySet in Hashtable. È privato, quindi non posso crearlo, ma implementa un'interfaccia pubblica, quindi parlo semplicemente attraverso l'interfaccia e ne ho una per me.

Ma stai descrivendo classi con le quali non vuoi che io parli nemmeno attraverso un'interfaccia. Quindi nessuna interfaccia per me. Questo significa che non ho nulla da guardare ed essere confuso (a meno che tu non mi fornisca la fonte).

Il problema più grande che prevedo è che questi principianti confusi mantengono l'API. Puoi inviare loro documentazione e commenti, ma non essere sovvertito quando non leggono o si fidano di nessuno dei due.

Hai creato ancora un altro modello che compensa una mancanza nella lingua. Java non ha modificatore di accesso che garantisce l'accesso a un gruppo di pacchetti. Ho sentito che era stato proposto un modificatore di accesso al "modulo" ma non vedo alcun segno che ciò accada.

Il modificatore di accesso predefinito (nessun modificatore) è probabilmente quello che utilizzerai qui a meno che non ti dispiaccia che io entri di nascosto attraverso l'eredità, nel qual caso protetta.

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 

Quello che vuoi veramente è l'accesso al modulo. In questo modo è possibile conservare i test in un pacchetto e il codice in un altro. Purtroppo non ce l'abbiamo in Java.

Molte persone fanno solo 1 ed espandono l'API. L'uso corretto delle interfacce mantiene la pressione sull'implementazione.

L'hacking di ciò che vuoi in 1 è ancora più brutto. Dai un'occhiata allo stack di chiamate e genera un'eccezione ogni volta che ciò che ti ha chiamato proviene da un pacchetto che non ti piace. Eeew.


3

Certamente, separa il tuo codice in pacchetti. Farà molto per migliorare la manutenibilità.

Per impedire agli utenti finali di accedere a cose che non dovrebbero, è necessario separare l'API in interfaccia e implementazione.

Puoi farlo letteralmente, definendo l'intera API in termini di interfacce Java e fornendo un numero di classi di fabbrica per produrre oggetti di implementazione. Questo è ciò che fa JDBC.

Oppure puoi farlo tramite convenzione, creando internalpacchetti e documentando tali pacchetti come dipendenti dall'implementazione e soggetti a modifiche senza preavviso o compatibilità con le versioni precedenti.


1
Sfortunatamente, questo è un no go completo. Questo lascia a molte classi pubbliche. Potrebbero avere dei suggerimenti (essendo fabbriche o "interne"). Ma a devo applicare strumenti aggiuntivi a loro (a tutte le classi pubbliche), non va bene.
Markus Frauenfelder il

@frmarkus - Penso che (1) ti aspetti troppo dai controlli di accesso o (2) devi ripensare la struttura del pacchetto in modo che le classi di un pacchetto non debbano dipendere dalle classi di un altro pacchetto (se riesci a mantenere tutto come classi nidificate statiche, questo non dovrebbe essere difficile).
kdgregory,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.