Introduzione
Quando ci si trova a dover affrontare lo sviluppo
di applicazioni J2EE di grandi dimensioni, si
è portati a pensare che un approccio classico
basato su una metodologia di tipo top-down possa
risultare efficace. Si cerca quindi di suddividere
una realtà complessa in tante sottoparti,
per ciascuna delle quali applicare nuovamente
il medesimo procedimento di suddivisione. Tutto
questo basta a garantirci l'efficacia del tipo
di approccio? Forse no, giacchè è
di estrema importanza anche la scelta dei criteri
secondo cui viene effettuata la suddivisione in
sottoproblemi, così come la questione di
caratterizzarne le singole parti e i loro componenti,
e di definire e gestire le reciproche interrelazioni.
Questo è appunto l'obiettivo del presente
articolo, e cioè proporre e descrivere
un approccio affidabile, produttivo ed efficace
al problema dello sviluppo di grandi applicazioni
J2EE, discutendo i concetti di base in una prima
parte e presentando un esempio concreto nella
sezione conclusiva.
Applicazioni
J2EE di grandi dimensioni
Lo sviluppo di applicazioni J2EE di grandi dimensioni
è un processo che oltre alla complessità
intrinseca degli obiettivi di business da raggiungere,
deve confrontarsi con una ulteriore variabile,
appunto le dimensioni dell'intero progetto. Questo
fatto, come illustrato in rif.[1], implica la
necessità di affrontare le attività
di progettazione e sviluppo suddividendo l'intero
progetto in progetti più piccoli, quindi
più facilmente gestibili. Sempre leggendo
rif.[1], viene evidenziato come un approccio vincente
consista nell'impiegare la modellazione secondo
quanto suggerito da Object Management Group (la
Model Driven Architecture, MDA nel seguito, vedi
anche rif.[2] e rif.[3]), allo scopo di controllare
al meglio la complessità che applicazioni
di grandi dimensioni hanno in sè.
Secondo l'approccio MDA, si costruisce un modello
di business (Platform Independent Model o PIM),
si deriva da esso un insieme di modelli applicativi
(Platform Specific Model o PSM) e da essi il codice
che costituisce l'applicazione globale (Code Model).
Figura 1 - Model Driven Architecture
In
un simile scenario, piuttosto complesse saranno
anche le problematiche al contorno, tra cui ad
esempio:
- Dimensioni
del team di sviluppo, sarà numeroso e
conterrà un gran numero di differenti
skill
- Progettazione,
costruzione e gestione di un modello MDA di
business di grandi dimensioni
- Complessità
delle attività di integrazione
- Elevato
numero di iterazioni nello sviluppo per raffinamenti
successivi
- Necessità
di riuscire a coprire per intero il ciclo di
vita della applicazione
- Necessità
e complessità delle attività di
personalizzazione richieste
Figura 2 - Impiego di MDA nei progetti
Sfruttando
la metodologia MDA si riduce sensibilmente la
complessità di quanto si sviluppa, proprio
in virtù dello sviluppo per modelli così
come previsto da MDA medesima. In aggiunta, suddividendo
il modello base costituente il progetto in diversi
sotto-modelli (sottoprogetti) si riesce meglio
e più efficacemente ad affrontare e parallelizzare
differenti task di sviluppo.
Resta però da risolvere un problema di
base: individuare in modo opportuno i singoli
sottoprogetti e identificarne e gestirne al meglio
l'intercomunicabilità. E non si tratta
di qualcosa di banale.
Package
e Subsystems in UML
Dato che parliamo di MDA, metodologia che viene
impiegata servendosi del formalismo UML, esaminiamo
due importanti concetti del mondo UML, e precisamente
i concetti di Package e Subsystem.
Un Package è definito (vedere rif.[4])
come un particolare tipo di costrutto che permette
di organizzare gli elementi costitutivi dei modelli
(ad esempio classi o use-case) in gruppi, detti
appunto Package.
Il problema è che l'utilizzo dei soli Package
nello sviluppo di architetture di una certa complessità
può non essere sufficiente. Esiste qualcosa
di più adatto? La risposta è sì,
ed è il Subsystem.
Un Subsystem (rif.[5]) è un particolare
tipo di Package, in cui il meccanismo di aggregazione
è spinto ad un livello di granularità
più elevato rispetto a quello tipico dei
Package. In sostanza, un Subsystem può
essere pensato come una sorta di Package specializzato,
in cui i singoli elementi componenti sono stati
selezionati (e quindi aggregati) in base a considerazioni
di tipo specifico, quali ad esempio:
- l'esigenza
di dividere il software complessivo in moduli
"pluggable"
- l'opportunità
di parallelizzare un progetto complesso attivando
simultaneamente lo sviluppo di subtask
-
la necessità di poter disporre di separazioni
dovute e motivi di sicurezza (ad esempio in
un sistema di pagamenti le informazioni inerenti
i diversi livelli salariali devono essere gestite
con diversi livelli di sicurezza e legate a
diversi data pool).
Considerazioni
sull'uso dei Subsystems
Non esiste un numero magico in grado di dirci
quale deve essere la cardinalità ideale
di ciascun Subsystem in termini di elementi componenti.
Esiste però una serie di considerazioni
pratiche, dettate dal buon senso e dall'esperienza,
ciò che normalmente viene definito "best
practices". Vediamone alcune.
- E'
potenzialmente pericoloso pensare di legare
il numero dei Subsystem al numero di use-case
individuati, sia perchè questo può
complicare eccessivamente il modello di business
di partenza, sia perchè si corre il rischio
di perdere di vista la visione completa del
proprio business. E' più indicato costruire
il modello di partenza basato sul proprio core-business,
individuandone le varie classi e le mutue interrelazioni;
solo in uno step successivo si provvederà
ad aggiungere quanto derivante dagli use-case
- Cercare
di ridurre la dipendenza tra Subsystem minimizzando
il numero delle associazioni esistenti tra essi.
L'obiettivo è quello di ottenere un livello
di accoppiamento quanto più basso possibile.
- Tenere
presente che un Subsystem dovrebbe costituire
sempre e comunque un'unità estremamente
maneggevole. Un architect cercherà sempre
il compromesso ideale tra maneggevolezza - riduzione
della dimensione dei Subsystem - e agilità
- riduzione del numero di interdipendenze tra
un Subsystem e gli altri.
Progettare
per Subsystems
Normalmente, un architect dovrebbe produrre il
diagramma dei Subsystem con le relative interdipendenze
durante le prime fasi dello sviluppo, di solito
al termine della fase di disegno dello Use Case
Diagram.
- Lo
scopo principale di un diagramma delle interdipendenze
tra Subsystem è:
identificare con chiarezza gli elementi (classi)
di interfaccia tra Subsystem, tenendo a mente
quelli che potranno essere futuri cambiamenti
e relative analisi di impatto
-
stabilire i livelli di dipendenza tra Subsystems,
al fine di poter poi agevolmente determinare
quale possa essere la sequenza di sviluppo di
essi stessi
Non
esiste, ad oggi, una notazione dedicata per disegnare
tali diagrammi, neppure in UML 2.0. D'altra parte,
è possibile servirsi della notazione disponibile
per i Class Diagram, in cui ciascun Subsystem
viene identificato dallo stereotipo <<subsystem>>,
così come esemplificato nella figura 3.
Figura 3 - Dipendenze tra Subsystems
(clicca sull'immagine per ingrandire)
Un esempio
Un esempio concreto potrà forse chiarire
meglio i concetti presentati. Il nostro obiettivo
è quello di mostrare come una applicazione
di partenza - con tutti i suoi elementi - possa
essere "vista" e utilizzata da altre
applicazioni proprio grazie al concetto dei Subsystem.
Essi quindi permettono, come conseguenza, di assemblare
applicazioni relativamente semplici al fine di
pervenire a strutture via via più complesse,
fino a costituire l'applicazione finale, quantunque
essa possieda dimensioni ragguardevoli.
Per la realizzazione del nostro esempio utilizziamo
lo strumento Compuware OptimalJ (rif.[6]), tool
di sviluppo J2EE completamente aderente alla metodologia
MDA e ai concetti di Package e Subsystem.
Partiamo quindi da un semplice modulo applicativo
che descrive la gestione di una biblioteca e dei
libri che essa possiede. Il Class Diagram del
nostro modulo applicativo è rappresentato
in figura 4. Si noti in particolare l'elemento
di tipo "subsystem", che costituisce
un "punto di raccolta" per tutti gli
elementi del modulo applicativo che appartengono
a quel determinato Subsystem. Nel nostro caso
appartengono al Subsystem "book" le
classi Book e Library e anche i loro attributi
e relativi tipi complessi Address e BookType.
Figura 4 - Class Diagram applicazione Book
(clicca sull'immagine per ingrandire)
Durante
questa prima fase può essere richiesto
arricchire il modulo applicativo di ulteriori
funzionalità. Ad esempio, definire e codificare
un metodo di business in un session bean creato
a fronte del modello di business contenuto nel
class diagram.
Rivolgendo la nostra attenzione al Session Component
LibraryDetails, aggiungiamo ad esso un business
method numberOfBooks,destinato a restituire il
numero di libri presenti nella biblioteca (figura
5).
Figura 5 - Modellazione di un Business
Method
(clicca sull'immagine per ingrandire)
Effettuiamo
una veloce fase di collaudo del nostro modulo
Book destinata a inserire alcuni dati significativi,
ad esempio le informazioni relative ad una biblioteca
e ai libri che le appartengono, (figure 6 e 7).
Figura 6 - Creazione di una biblioteca
Figura 7 - Definizione dei libri della
biblioteca
A
questo punto siamo pronti per rendere "pubblico"
il nostro modulo Book e farlo diventare a tutti
gli effetti un Subsystem condivisibile e utilizzabile
da altri moduli applicativi (altri Subsystem).
A tal fine effettuiamo come prima cosa la pubblicazione
del modulo Book, cosa che come risultato provocherà
la costruzione di un componente book.jar contenente
tutti gli "ingredienti" necessari alla
pubblicazione (figura 8)
Figura 8 - Pubblicazione del Subsystem
Book
Successivamente
predisponiamo la nostra applicazione in formato
pronto per il deployment, e quindi costruiamo
l'archivio EAR (enterprise archive repository).
Gli oggetti che dovranno essere "visibili"
a tutti i moduli applicativi che devono utilizzare
il Subsystem Book saranno quindi book.jar, risultante
dalla pubblicazione, e book.ear, contenente gli
artifatti applicativi.
Adesso
immaginiamo che un differente team di sviluppo
stia lavorando ad un altro semplice modulo applicativo,
destinato a implementare e gestire le credenziali
di una persona che utilizza i libri della biblioteca.
Il nostro Class Diagram conterrà una sola
classe, Reader (figura 9).
Figura 9 - Class Diagram applicazione Reader
Come
passo successivo, effettuiamo il "mount"
via Filesystem degli archivi book.ear e book.jar,
cosa che, in un caso reale, richiederà
che essi siano resi disponibili in una qualche
locazione, anche remota .
Figura 10 - Mount del Subsystem Book
(clicca sull'immagine per ingrandire)
Il
risultato di tale operazione è che, passando
a esaminare il Domain Model del modulo Reader
che stiamo sviluppando, ci accorgiamo che adesso
"vediamo" anche l'intero Subsystem Book,
(si noti la presenza del piccolo lucchetto nero,
a indicare che Book può essere referenziato,
ma non modificato).
Figura 11 - Class Diagram contenente il
Subsystem Book
Ora
il nostro modulo applicativo Reader potrà
utilizzare tutto quanto reso disponibile nel Subsystem
Book. Ciò è ulteriormente evidente
dalla figura 12, in cui se selezioniamo il modulo
Subsystem di Reader notiamo che afferisce, come
Subsystem utilizzato, proprio a Book.
Figura 12 - Subsystem
Reader utilizza Subsystem Book
Subsystem
Reader può utilizzare Subsystem Book in
vari modi. Ad esempio si può dichiarare
uno degli attributi di Reader in modo che sia
di un tipo specificato in Book, ad esempio di
tipo Address (figura 13).
Figura 13 - Riutilizzo
definizione di tipi tra Subsystem
Si
può poi definire una associazione tra i
due Subsystem, ad esempio tra la classe Reader
e la classe Book (figura 14)
Figura 14 - Associazioni tra Subsystem
(clicca sull'immagine per ingrandire)
Allo
stesso modo, è possibile aggiungere a uno
dei componenti di Reader (ad esempio al suo session
component ReaderDetails) dei business method che
referenziano le operazioni presenti in Book. Nella
figura 15 si nota l'implementazione di un business
method che calcola e restituisce il numero di
libri associati ad un lettore.
Figura 15 -Implementazione di un Business
Method
(clicca sull'immagine per ingrandire)
A
questo punto, compilata l'applicazione Subsystem
Reader e immaginando che il Subsystem Book sia
"up and running", cioè attivo
e in esecuzione, facciamo partire anche il Subsystem
Reader.
Figura 16 - Subsystems Book e Reader
(clicca sull'immagine per ingrandire)
Attiviamo
la pagina di gestione del generico lettore (Reader),
per crearne uno nuovo e la prima cosa che notiamo
è la presenza nell'attributo address degli
elementi caratteristici del tipo complesso Address
definito in Book (figura 17).
Figura 17 - Creazione nuovo lettore
(clicca sull'immagine per ingrandire)
Sempre
sulla pagina di gestione del generico lettore
(Reader), se facciamo clic sul tab Reader.book,
attiviamo l'associazione tra Reader e Book, e
questo ci permette di selezionare un libro da
associare al lettore corrente. Si noti che i libri
disponibili sono - ovviamente - quelli che avevamo
precedentemente inserito in figura 7 (figura 18).
Figura 18 - Associazione tra Subsystem
(clicca sull'immagine per ingrandire)
Immaginando
di avere associato a questo lettore due libri
e sempre partendo dalla pagina di gestione del
generico lettore (Reader), attiviamo la funzione
booksPerReader già vista in figura 15,
e che ci restituisce esattamente il numero di
libri associati al lettore, dimostrando un riutilizzo,
in ambito Subsystem Reader, dei metodi definiti
nel Subsystem Book (figura 19)
Figura 19 - Calcolo dei libri associati
al lettore
(clicca sull'immagine per ingrandire)
Conclusioni
Affrontare la progettazione e lo sviluppo di applicazioni
J2EE di grandi dimensioni è qualcosa di
complesso e articolato. E' certamente consigliabile
cercare di suddividere l'ambito che si intende
affrontare in sottoprogetti di maggiore semplicità
e maneggevolezza. In questo articolo si è
cercato di illustrare come il concetto di Subsystem,
proposto e definito in ambito UML permetta di
approcciare questo tipo di problematica in modo
concreto e affidabile e si è altresì
cercato, attraverso un esempio semplice ma significativo,
di dimostrare quanto possa essere potente in pratica
l'uso di Subsystem per definire e implementare
differenti parti del proprio sistema, salvo avere
la possibilità di interrelare i vari Subsystems.
E' un modo per affrontare realtà complesse
suddividendo il problema principale in sottoproblemi,
e affrontandoli separatamente in modo efficace,
produttivo e rapido. Think big, start small, move
fast, non dimentichiamolo!
Bibliografia
[1]
H. Tai, K. Mitsui, T. Nerome, M. Abe, K. Ono,
and M. Hori, "Model-driven development of
large-scale Web applications", on line copy
su http://www.research.ibm.com/journal/rd/485/tai.html
[2]
Mokabyte - "Uso della Model Driven Architecture
nello Sviluppo di Applicazioni J2EE", parte
1 http://www.mokabyte.it/2004/07/mda-1.htm e parte
2 http://www.mokabyte.it/2004/09/mda-2.htm)
[3]
Compuware White Papers "Addressing the business
challenges of Java/J2EE development", on
line copy su http://javacentral.compuware.com/members/downloads/pdf/OJj2ee.pdf
[4]
Scott W. Ambler, "UML Package Diagramming
Guidelines", on line copy su http://www.agilemodeling.com/style/packageDiagram.htm
[5] Jan JÄurjens "Formal Semantics for
Interacting UML subsystems" online copy su
http://www4.in.tum.de/~juerjens/papers/fmoods02Talk.pdf
[6]
Compuware Lab "OptimalJ Community" -
http://javacentral.compuware.com
Doriano
Gallozzi è nato a Roma nel 1964 e si
è laureato in Ingegneria Elettronica (indirizzo
Informatica) nel 1989. Da sempre interessato a
problematiche di analisi, progettazione e sviluppo
di Sistemi Informativi, ha lavorato per diversi
anni in aziende del settore informatico italiano
(gruppo ENI, gruppo Telecom Italia), dove ha acquisito
diverse esperienze tanto nel campo della progettazione
e sviluppo del software (in ambiente M/F come
in ambiente distribuito) quanto nel campo dei
RDBMS (DBA su diversi progetti per clienti finali
quali Telecom Italia). Da gennaio 2000 lavora
nella Divisione Prevendita di Compuware Italia.
La sua attività verte principalmente sulla
piattaforma J2EE e tecnologie correlate, ma anche
su ambiti tecnologici quali l'Enterprise Application
Integration, i Portali Web, gli strumenti di Business
Process Modeling.
|