Domanda

Prima di tutto, so come costruire un'applicazione Java.Ma sono sempre stato perplesso su dove collocare le mie lezioni.Ci sono sostenitori dell'organizzazione dei pacchetti in modo strettamente orientato al dominio, altri separati per livelli.

Io stesso ho sempre avuto problemi con

  • nominare,
  • collocazione

COSÌ,

  1. Dove inserisci le costanti specifiche del tuo dominio (e qual è il nome migliore per una classe del genere)?
  2. Dove inserisci le classi per elementi sia infrastrutturali che specifici del dominio (ad esempio ho una classe FileStorageStrategy, che memorizza i file nel database o in alternativa nel database)?
  3. Dove inserire le eccezioni?
  4. Ci sono norme a cui posso fare riferimento?
È stato utile?

Soluzione

Mi è davvero piaciuto quello di Maven Layout della directory standard.

Una delle idee chiave per me è avere due radici sorgente: una per il codice di produzione e una per il codice di test in questo modo:

MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.java

(qui, sia src/main/java che src/test/java sono root di origine).

Vantaggi:

  • I tuoi test hanno accesso a livello di pacchetto (o "predefinito") alle classi in fase di test.
  • Puoi facilmente impacchettare solo le tue fonti di produzione in un JAR rilasciando src/test/java come root della fonte.

Una regola pratica sul posizionamento in classe e sui pacchetti:

In generale, i progetti ben strutturati saranno esenti da dipendenze circolari.Impara quando sono cattivi (e quando lo sono non) e considera uno strumento come JDipende O SonarJ questo ti aiuterà ad eliminarli.

Altri suggerimenti

Sono un grande fan dei sorgenti organizzati, quindi creo sempre la seguente struttura di directory:

/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system

In /src sto utilizzando i modelli Java predefiniti:Nomi dei pacchetti che iniziano con il tuo dominio (org.tuodominio.tuonomeprogetto) e nomi delle classi che riflettono l'aspetto OOP che stai creando con la classe (vedi gli altri commentatori).Nomi di pacchetti comuni come util, modello, visualizzazione, eventi sono anche utili.

Tendo a inserire costanti per un argomento specifico in una classe, ad esempio Costanti di sessione O Costanti di servizio nello stesso pacchetto delle classi del dominio.

Dove lavoro, utilizziamo Maven 2 e abbiamo un archetipo piuttosto carino per i nostri progetti.L'obiettivo era ottenere una buona separazione delle preoccupazioni, quindi abbiamo definito una struttura di progetto utilizzando più moduli (uno per ogni "livello" dell'applicazione):- comune:Codice comune usato dagli altri livelli (ad es. I18n) - Entità:Le entità del dominio - repository:Questo modulo contiene le interfacce e le implementazioni DAOS - Services -Intf:Interfacce per i servizi (ad es. Userservice, ...) - Services -Impl:Implementazioni dei Servizi (ad es. UtentiServiceImpl) - Web:Tutto per quanto riguarda il contenuto web (ad es. CSS, JSPS, JSF Pages, ...) - WS:servizi web

Ogni modulo ha le proprie dipendenze (ad esempio, i repository potrebbero avere jpa) e alcuni riguardano l'intero progetto (quindi appartengono al modulo comune).Le dipendenze tra i diversi moduli del progetto separano chiaramente le cose (ad esempio, il livello web dipende dal livello di servizio ma non conosce il livello di repository).

Ogni modulo ha il proprio pacchetto base, ad esempio se il pacchetto dell'applicazione è "com.foo.bar", allora avremo:

com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...

Ogni modulo rispetta la struttura standard del progetto Maven:

   src\
   ..main\java
     ...\resources
   ..test\java
     ...\resources

I test unitari per un dato livello trovano facilmente il loro posto in \src est...Tutto ciò che è specifico del dominio ha il suo posto nel modulo entità.Ora qualcosa come FileStorageStrategy dovrebbe entrare nel modulo repository, poiché non abbiamo bisogno di sapere esattamente quale sia l'implementazione.Nel livello dei servizi conosciamo solo l'interfaccia del repository, non ci interessa quale sia l'implementazione specifica (separazione delle preoccupazioni).

I vantaggi di questo approccio sono molteplici:

  • chiara separazione delle preoccupazioni
  • ogni modulo è impacchettabile come jar (o war nel caso del modulo web) e quindi consente un riutilizzo più semplice del codice (ad esempio, potremmo installare il modulo nel repository Maven e riutilizzarlo in un altro progetto)
  • massima indipendenza di ogni parte del progetto

So che questo non risponde a tutte le tue domande, ma penso che potrebbe metterti sulla strada giusta e potrebbe rivelarsi utile ad altri.

I nomi delle classi dovrebbero sempre essere descrittivi e autoesplicativi.Se hai più domini di responsabilità per le tue classi, probabilmente dovrebbero essere sottoposte a refactoring.

Lo stesso vale per i tuoi pacchetti.Dovrebbero essere raggruppati per ambito di responsabilità.Ogni dominio ha le sue eccezioni.

Generalmente non preoccuparti finché non arrivi al punto in cui diventa opprimente e gonfio.Quindi siediti e non scrivere codice, rifattorizza semplicemente le classi, compilando regolarmente per assicurarti che tutto funzioni.Poi continua come hai fatto prima.

Utilizza i pacchetti per raggruppare insieme funzionalità correlate.

Di solito la parte superiore dell'albero dei pacchetti è il nome di dominio invertito (com.domain.subdomain) per garantire l'unicità e quindi solitamente ci sarà un pacchetto per la tua applicazione.Quindi suddividilo per area correlata, quindi tuo FileStorageStrategy potrebbe entrare, dire, com.domain.subdomain.myapp.storage, e quindi potrebbero esserci implementazioni/sottoclassi/qualsiasi cosa in com.domain.subdomain.myapp.storage.file E com.domain.subdomain.myapp.storage.database.Questi nomi possono diventare piuttosto lunghi, ma import li mantiene tutti in cima ai file e anche gli IDE possono aiutare a gestirli.

Le eccezioni di solito vanno nello stesso pacchetto delle classi che le lanciano, quindi se tu avessi, diciamo, FileStorageException andrebbe nello stesso pacchetto di FileStorageStrategy.Allo stesso modo un'interfaccia che definisce le costanti si troverebbe nello stesso pacchetto.

Non esiste davvero alcuno standard in quanto tale, basta usare il buon senso e, se tutto diventa troppo confuso, eseguire il refactoring!

Una cosa che ho trovato molto utile per i test unitari è stata avere una directory myApp/src/ e anche myApp/test_src/.In questo modo, posso inserire test unitari negli stessi pacchetti delle classi che testano, e tuttavia posso facilmente escludere i casi di test quando preparo la mia installazione di produzione.

Risposta breve:disegna l'architettura del tuo sistema in termini di moduli, disegnati fianco a fianco, con ciascun modulo suddiviso verticalmente in strati (ad es.vista, modello, persistenza).Quindi usa una struttura come com.mycompany.myapp.somemodule.somelayer, per esempio. com.miaazienda.miaapp.client.view O com.miaazienda.miaapp.server.model.

Utilizzo del livello più alto di pacchetti per l'applicazione moduli, nel vecchio senso informatico di programmazione modulare, dovrebbe essere ovvio.Tuttavia, nella maggior parte dei progetti su cui ho lavorato finiamo per dimenticarci di farlo e ci ritroviamo con un caos di pacchetti senza quella struttura di primo livello.Questo anti-modello di solito si presenta come un pacchetto per qualcosa come "ascoltatori" o "azioni" che raggruppa classi altrimenti non correlate semplicemente perché implementano la stessa interfaccia.

All'interno di un modulo o in una piccola applicazione, utilizzare i pacchetti per i livelli dell'applicazione.I pacchetti probabili includono cose come le seguenti, a seconda dell'architettura:

  • com.miaazienda.miaapp.view
  • com.miaazienda.miaapp.modello
  • com.mycompany.myapp.services
  • com.mycompany.myapp.rules
  • com.miaazienda.miaapp.persistenza (o 'dao' per il livello di accesso ai dati)
  • com.miaazienda.miaapp.util (attenzione a non usarlo come se fosse 'misc')

All'interno di ciascuno di questi livelli, è naturale raggruppare le classi per tipo se ce ne sono molte.Un anti-modello comune qui è quello di introdurre inutilmente troppi pacchetti e livelli di sottopacchetti in modo che ci siano solo poche classi in ciascun pacchetto.

Penso che sia semplice e non pensarci troppo.Non astrarre troppo e non sovrapporre troppo.Mantienilo pulito e, man mano che cresce, rifattorizzarlo è banale.Una delle migliori caratteristiche degli IDE è il refactoring, quindi perché non utilizzarlo e risparmiare energia cerebrale per risolvere problemi relativi alla tua app, piuttosto che meta problemi come l'organizzazione del codice.

Una cosa che ho fatto in passato è che se sto prolungando una lezione cercherò di seguire le loro convenzioni.Ad esempio, quando lavoro con il framework Spring, avrò le mie classi di controller MVC in un pacchetto chiamato com.mydomain.myapp.web.servlet.mvc Se non estengo qualcosa che vado con ciò che è più semplice.com.mydomain.domain per gli oggetti di dominio (anche se se hai molti oggetti di dominio questo pacchetto potrebbe diventare un po' ingombrante).Per le costanti specifiche del dominio, in realtà le inserisco come costanti pubbliche nella classe più correlata.Ad esempio, se ho una classe "Membro" e ho una costante di lunghezza massima del nome membro, la inserisco nella classe Membro.Alcuni negozi creano una classe Constants separata, ma non vedo il valore nel raggruppare numeri e stringhe non correlati in un'unica classe.Ho visto altri negozi tentare di risolvere questo problema creando classi di costanti SEPARATE, ma sembra semplicemente una perdita di tempo e il risultato è troppo confuso.Utilizzando questa configurazione, un progetto di grandi dimensioni con più sviluppatori duplicherà le costanti ovunque.

Mi piace suddividere le mie lezioni in pacchetti correlati tra loro.

Per esempio:Modello Per le chiamate relative al database

Visualizzazione Classi che trattano ciò che vedi

Controllo Classi di funzionalità principali

Utile Qualsiasi mis.classi utilizzate (tipicamente funzioni statiche)

eccetera.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top