|
Lo scopo del lavoro è quello di guadagnarsi il tempo libero
|
|
|
|
|
Architettura di sistemi distribuiti: un approccio a 5 livelli
By
Armando Capogrossi
20 luglio 2005
|
 |
|
Il disegno dell’architettura di un’applicazione distribuita si basa sullo studio di tutti i casi d’uso possibili. Bisogna quindi capire le necessità degli utenti dell’applicazione e analizzare i casi d’uso che dovranno essere soddisfatti dal sistema. L’attenzione dovrà anche essere concentrata sulla definizione di oggetti di dominio e strutture fisiche di utilità per il sistema. E’ necessaria una precisazione: questo articolo non si prefigge lo scopo di spiegare le metodologie utilizzate nella stesura di use cases, tantomeno quello di porre l’accento sui criteri di base dell’analisi Object Oriented. L’attenzione verrà focalizzata unicamente sul disegno architetturale. Proprio per questo motivo, quando si accennerà a casi d’uso o a criteri provenienti dall’analisi OO dei problemi relativi al sistema studiato, si supporrà di avere già a disposizione tutte le basi per la definizione delle competenze dei vari livelli nell’architettura del sistema stesso.
|
|
|
Architettura a livelli
|
top
|
|
In generale, un qualsiasi sistema distribuito può essere classificato tramite un insieme di livelli: | Livello | Responsabilità | Tecnologia | | Presentazione | User Interface | JSP/HTML/Javascript/awt/jfc | | Applicazione | sintassi, interazione con lo strato dei servizi, workflow degli use case | Servlet/JavaBean | | Servizi | transazioni, logica di business e di workflow | Session bean | | Dominio | semantica, modello di dominio, logica business di dominio | Entity bean e classi Java | | Persistenza | gestione dati | OODBMS/RDBMS/Entity beans/ORM< | Analizziamo nel dettaglio le caratteristiche dei 5 livelli: - Presentazione: in questo livello si elaborano le parti grafiche dell’applicazione. Ne fanno parte anche le tag libraries dedicate alla formattazione
- Applicazione: questo livello si occupa di compattare il livello dei componenti con quello di presentazione tramite un flusso di lavoro. Più dettagliatamente:
- gestisce lo stato dei client tramite sessioni HTTP
- opera validazioni sulla sintassi delle richieste provenienti dai client
- delega alla logica di business nello strato dei servizi la soddisfazione delle richieste provenienti dai client (il flusso di lavoro di cui si accennava)
- utilizza taglibs dedicate alla comunicazione con gli EJB
- Servizi: rappresenta lo strato dedicato a soddisfare le richeste provenienti dallo strato di application. Lo strato dei servizi è generalmente implementato come Session Façade, cioè uno strato di session bean stateless che si occupano di invocare la business logic (relativa a soddisfare un caso d’uso) su oggetti di dominio (entity bean in genere). Questo livello
- controlla che la transazione sotto cui gira la logica sia unica
- gestisce il flusso tra gli oggetti di dominio in modo da soddisfare il particolare use case (anche questo livello utilizza un workflow come collante con il livello superiore)
- Dominio: in questo strato risiedono quegli oggetti che provengono dall’analisi Object Oriented dei problemi. Il livello dei servizi delega molte richieste, tra quelle che riceve, allo strato di dominio. Questo livello deve essere implementato in modo da risultare indipendente dall’ intera applicazione essendo così riutilizzabile in altre parti del progetto o addirittura in altri progetti. Le tecnologie di implementazione del modello di dominio si dividono in due tipi:
- quelle che generano il codice di persistenza (entity bean di tipo CMP, JDO, Object Relational Mappers)
- quelle che impongono la scrittura del codice di persistenza direttamente nell’oggetto di dominio (entity bean di tipo BMP)
- Persistenza: lo sviluppatore utilizzerà degli strumenti specifici per mappare gli oggetti di dominio al magazzino dei dati
La soluzione proposta rappresenta un approccio classico al problema relativo al disegno dell’architettura di un sistema. Si può però optare per non utilizzare un livello di dominio, modificando notevolmente l’architettura, e di conseguenza la scelta nell’uso dei pattern. Disegnare un sistema senza un livello di dominio ritorna dei vantaggi solo in caso di applicazioni “semplici”: - si creano modelli di dominio molto semplici
- si migliorano le prestazioni in caso di operazioni di sola lettura dei dati: gli use case vengono soddisfatti tramite classi con codice di accesso diretto al DB, evitando di utilizzare classi dedicate alla gestione delle operazioni CRUD relative alla base di dati. In questi casi si utilizza un session bean che acceda direttamente al DB tramite le peculiarità dell’API JDBC
- si costruiscono velocemente i prototipi: l’accesso diretto al DB permette di creare applicazioni prototipo (di vita breve) senza troppi sforzi
|
|
Le Fasi Di Sviluppo
|
top
|
|
A questo punto, supponiamo di avere ben chiari tutti gli elementi relativi al sistema che verrà sviluppato: - use cases da soddisfare e relativa implementazione via codice
- modello concettuale di dominio
- tipo di persistenza che gestirà il modello di dominio
Dobbiamo stabilire delle linee guida sul processo di sviluppo del progetto: - implementazione
- amministrazione dell’ambiente tramite il server j2ee che utilizziamo (in genere, i server di buon livello forniscono dei tool per monitorare il lavoro, testare, ecc.) o tramite strumenti opensource (ad esempio quelli del progetto jakarta)
- definizione di ambienti di test diversi, che permettano di esaminare:
- integrazione dei moduli nell’architettura (quindi le relazioni con gli altri moduli)
- stress: la risposta del sistema a carichi pesanti (ad esempio un numero di connessioni simultanee molto maggiore di quello pronosticato)
- definizione di ambiente di sviluppo
- definizione di ambiente di produzione
In questo articolo ci occuperemo dell’implementazione degli strati dell’architettura. L’integrazione dei moduli nel sistema e i problemi legati a packaging e deployment sono già stati discussi negli articoli che il javaportal ha pubblicato riguardo Ant. La fase di test sarà oggetto di un articolo che verrà pubblicato di qui a breve.
|
|
Gerarchia
|
top
|
|
Nell’architettura a 5 livelli, gli strati superiori sono direttamente dipendenti da quelli inferiori fornendo un ordine naturale di sviluppo. Questo significa che le classi e le interfacce che vengono prodotte risulteranno, sia a tempo di compilazione che a tempo di esecuzione, dipendenti dalle classi apparteneti allo strato direttamente inferiore: si ricordi che i compilatori Java operano in funzione delle dipendenze, per cui, compilando una classe, vengono compilate tutte le classi da essa referenziate.
|
|
Struttura e dipendenze
|
top
|
|
Ancor prima delle classi del livello più basso, dobbiamo definire delle classi di utilità che esulano dalla gerarchia degli strati perché vengono utilizzate a tutti i livelli. Si tratta di eccezioni e classi comuni. Per entrambe è valido il discorso che non si può predire tutte le necessità del sistema in fase di progettazione, così, le necessità più lampanti verranno soddisfatte dalla codifica delle classi stesse, mentre altre emergeranno in seguito. A monte, bisogna avere un’idea di come strutturare l’applicazione raggruppando tutte le classi in packages che abbiano nomi significativi e contengano classi che svolgono compiti logici simili: com.nomeCompagnia.nomeApplicazione.common.util com.nomeCompagnia.nomeApplicazione.common.exceptions Negli identificativi dei packages, common implica che il pacchetto in considerazione conterrà classi di uso comune tra gli strati dello stesso container o di containers differenti. Una struttura di packages potrebbe essere: com.nomeCompagnia.nomeApplicazione.common.util com.nomeCompagnia.nomeApplicazione.common.exceptions com.nomeCompagnia.nomeApplicazione.common.dto com.nomeCompagnia.nomeApplicazione.ejb.domain com.nomeCompagnia.nomeApplicazione.ejb.persistence com.nomeCompagnia.nomeApplicazione.ejb.services com.nomeCompagnia.nomeApplicazione.web Ovviamente, si potrebbe creare una struttura relativa agli strati dell’architettura del dominio verticale; queste scelte dipendono dal grado di libertà lasciato al progettista o allo sviluppatore e dai gusti.
|
|
Implementazione dei livelli
|
top
|
|
Discutiamo nel dettaglio l’ordine di implementazione del codice nei 5 strati. Una volta decisa la struttura dei pacchetti, la gestione delle eccezioni e la codifica delle classi di uso comune, siamo pronti per la codifica dello strato di dominio in concomitanza con la definizione dello strato di persistenza.
|
|
Dominio
|
top
|
|
Lo strato dei servizi dipende direttamente da quello di dominio: in una web application ad esempio, il client accede ai dati tramite richiesta alla Session Façade (formata dai session bean di servizio), che funziona da proxy verso gli oggetti di dominio (entity beans o classi semplici). I session bean di servizo non potranno essere compilati se non vengono compilate le classi di dominio. Per ovviare ad una non-compilazione delle classi di dominio dovuta a problemi nelle classi di servizio, in principio, i metodi load/store/remove/find delle stesse possono essere lasciati vuoti. In questo modo le classi possono essere compilate e si può passare all’implementazione degli strati successivi, fermo restando che l’implementazione dovrà essere raffinata al procedere del lavoro.
|
|
Persistenza
|
top
|
|
Implementare gli schemi dello strato di persistenza (comunque la gestione del tipo di persistenza scelto in generale) porta via molto tempo e riduce la produttività del team di sviluppo della User Interface che non può realmente testare le operazioni cardine (operazioni Create/Read/Update/Delete) senza un vero e proprio strato di persistenza funzionante. Utilizziamo allora delle operazioni di lettura e modifica fittizie relative a dati inseriti nel DB con lo scopo di testare le funzionalità delle UI.
|
|
Servizi
|
top
|
|
Questo rappresenta lo strato più importante del sistema: fornisce le basi per gli strati di dominio e persistenza, e definisce le interfacce che verranno utilizzate dai client. Allora, per completare lo strato dei servizi, sarà necessario che i livelli di dominio e persistenza siano funzionanti, in modo da poter testare l’intero strato dei servizi stessi. Un punto cruciale nella nostra discussione riguarda servizi relativi ad operazioni CRUD su oggetti di dominio: leggere o modificare oggetti di dominio rappresenta un compito imprescindibile dall’architettura di un sistema J2EE.
|
|
Application
|
top
|
Gli oggetti utilizzati in questo strato costituiscono il punto di snodo delle richieste provenienti dai client. Una web application utilizzerà Servlets e JavaBeans per ridirigere le richieste allo strato di competenza, quello dei servizi, in cui ogni use case dovrà essere soddisfatto.
|
|
Presentazione
|
top
|
|
Finalmente, con i livelli servizi/dominio/persistenza funzionanti, possiamo terminare lo sviluppo dello strato client. Si è già sottolineato come lo strato dei servizi sia quello che da carattere al sistema e di come, proprio per questa peculiarità, fornisca le basi di implementazione per le interfacce usate dai clienti. La caratteristica principale di un client risiede nelle interfacce grafiche che questo utilizza per presentare e far manipolare alcuni dati agli utenti. Risulta chiaro che le dipendenze gerarchiche nell’implementazione dei livelli non influiscono sulle UI, che devono essere tenute in considerazione durante tutta la fase di sviluppo e soprattutto nel momento dello sviluppo dei servizi che dovranno soddisfarle.
|
|
Ultimi raffinamenti
|
top
|
|
Come ultimo passo, si implementeranno quelle parti degli strati necessarie a soddisfare gli use case presi in considerazione in momenti successivi. In questo modo non si dovrà forzatamente completare la codifica di uno strato (fermo restando che la parte già codificata sia funzionante), ma si procederà aggiungendo nuove classi secondo necessità.
|
|
Conclusioni
|
top
|
|
La progettazione dell’architettura di un sistema distribuito trova la sua migliore espressione nell’uso di pattern dai comportamenti eterogenei (creazione, trasferimento dati infrastrutturale, facciata di servizi, accesso, ecc…). Allo scopo di migliorare le proprie capacità da progettista, si rimanda il lettore agli articoli relativi ai pattern J2EE pubblicati sul javaportal e al sito della Sun.
|
|
|
| |
| JavaPortal è ideato da: |
 |

Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons
|
|
|