2010-05-29 19 views
7

Sono al lavoro per impacchettare un'API per il consumo pubblico. Come tale sto cercando di limitare i metodi che sono esposti solo a quelli che desidero essere pubblici e sostenibili. Sotto questo, naturalmente, ci sono una moltitudine di metodi ad accesso limitato.Le mie classi API interne dovrebbero essere tutte in un unico pacchetto?

Il problema è che ho un sacco di codice interno che deve accedere a questi metodi ristretti senza rendere pubblici quei metodi. Questo crea due problemi:

  • Non riesco a creare interfacce per comunicare tra le classi in quanto questo renderebbe questi miei metodi interni pubblici.
  • Non riesco ad accedere ai metodi protetti o predefiniti a meno che non inserisca la maggior parte delle classi interne nello stesso pacchetto .

Quindi, ho circa 70 o 80 classi interne in pacchetti separati ma MA con modificatori di accesso eccessivamente permissivi. Diresti che un singolo pacchetto è il minore di due mali o esiste un modo migliore per essere in grado di mascherare i miei metodi interni mantenendo pacchetti più granulari?

Sarei interessato a scoprire le migliori pratiche qui.

Sono già a conoscenza di This

+0

Penso che la domanda sia un po 'soggettiva: personalmente, non mi piacciono le decisioni di progettazione che portano a una cattiva organizzazione interna, come il caso di tutte le classi in un solo pacchetto. Ma il modo giusto di fare queste cose non viene in mente proprio ora. – incarnate

risposta

7

Ci sono due soluzioni alla tua domanda che non implicano il mantenimento di tutte le classi nello stesso pacchetto.

Il primo è utilizzare il modello Friend Accessor/Friend Package descritto in (Practical API Design, Tulach 2008).

Il secondo è utilizzare OSGi. C'è un articolo here che spiega come OSGi realizza questo.

Domande correlate: 1, 2, 3 e 4.

+0

Questa è una risposta eccellente e il link al pacchetto di amici era la soluzione che stavo cercando. – Chris

+0

Sono felice di poterti aiutare. Anch'io avevo bisogno di una soluzione a questa limitazione apparentemente seria di Java. Questo modello dovrebbe essere un candidato ideale per estendere Java utilizzando MPS Jetbrains o altri strumenti di sviluppo basati su modelli. –

+0

Bene, devi ancora rendere pubblico l'Accessor astratto interno (quindi una parte dell'API). Peggio ancora, un utente malvagio può fornire il proprio AccessorImpl, costringendo quindi il proprio pacchetto interno a utilizzare la propria API. Questo funzionerà fino a quando la classe Item non verrà inizializzata e spara a IllegalStateException. – charlie

2

Un esempio potrebbe essere la Servlet API come si vede sono separati comuni API servlet e http in due pacchetti.

Se si separa il codice in un api.jar e implementation.jar, è possibile utilizzare le interfacce per l'implementazione che non sono visibili agli utenti di api.jar. Se oggetti di classi indipendentemente dal loro pacchetto, devono collaborare in alcun modo, i metodi ovviamente devono essere visibili (almeno nell'implementazione).

+0

+1 Grazie per l'informazione. Sono consapevole di poter impacchettare il problema, ma in realtà desidero limitare gli utenti che hanno sia l'api che i jar di implementazione dall'essere in grado di accedere a metodi di implementazione non dell'interfaccia in un modo non previsto. – Chris

1

sì, non è possibile proteggere l'implementazione interna dall'accesso. Ci sono alcune tecnologie (come OSGi), che offrono una soluzione a questo durante l'avvio di applicazioni/runtime. Questo è un difetto di modularizzazione del linguaggio java (ma anche molto difficile da aggiungere in seguito a causa di problemi di compatibilità).

mi piace la convenzione di aggiungere artefatti visibili pubblicamente a /api pacchetto e interni a /interno. Alla fine finisci con.

 

# 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 
 

In questo modo si ha una separazione netta e si possono anche eseguire regole del codice di analisi del codice statico.

Come con la servlet-api menzionata sopra, è possibile dividere ulteriormente api vs impl in diversi vasi. Ma questo comporta un maggiore sforzo per costruire-il ciclo di vita e mantenere i moduli, quindi lo farei solo laddove una suddivisione di artefatto di runtime completa abbia senso (come in jsr-spec vs. impl).

Problemi correlati