(:title Ingegneria del Software - Appunti del 4 Maggio 2009:)
Torna alla pagina di Ingegneria del Software
:: Ingegneria del Software - Appunti del 4 Maggio 2009 ::
Architetture di componenti
Le architetture per realizzare fisicamente componenti saranno oggetto di più approfondite lezioni verso la fine del corso, quando studieremo nel dettaglio EJB. Tuttavia, il professore ha deciso di anticiparci qualcosa ora così da comprendere meglio i prossimi argomenti.
Facciamo un riassunto delle puntate precedenti. Lo scopo di suddividere il nostro sw in componenti è quello di avere una successiva facilità di manutenzione, visto che la manutenzione è la parte più costosa del processo di sviluppo del software.
UML ci fornisce alcuni strumenti per pensare ad una suddivisione in componenti; tuttavia si tratta di un'operazione eseguita durante la fase di implementazione e dipendente dal linguaggio e dall'architettura scelta. Esistono degli standard language independent, ma solo in linea di principio.
Quando decidiamo di dividere in componenti, utilizziamo fondamentalmente i criteri di stereotipia e di coesione.
Dynamic Linking
Ma il componente non è solo un modo per catalogare le classi, come potrebbe esserlo uno stereotipo. Oltre a ciò, il componente definisce anche:
- le unità di distribuzione del software;
- la tecnica di dynamic linking che andrò poi ad utilizzare.
Sul primo punto, ovvero le unità di distribuzione del software, è già stato detto qualcosa. Al momento dell'installazione, se il nostro software è modulare, è possibile scegliere quale moduli installare e su quali macchine della rete.
Il secondo punto riguarda invece il come i nostri componenti effettivamente comunicheranno. Il linking è quella fase del processo di compilazione in cui i riferimenti che il mio programma fa verso altri programmi o librerie vengono riempiti. Il link dinamico è un link che non viene eseguito del tutto in fase di compilazione, bensì in fase di esecuzione.
Se non ci fosse la possibilità di eseguire un link dinamico non potremmo avere librerie condivise, e tutti i programmi sarebbero dei monoliti giganteschi con, compilate all'interno, tutte le librerie di cui necessitano.
Chi definisce gli standard?
Nel mondo del software, gli standard vengono proposti dalle singole industrie, e se piacciono vengono ratificati. Per esempio, UML è stato inventato dalla Rational, e poi è stato codificato ed ora lo usano tutti.
I grandi componenti del mondo degli standard dei componenti sono:
- Microsoft
- Resto del mondo, tramite OMG (Object Management Group, lo stesso che ratifica UML)
Ci sono varie caratteristiche di un'architettura a componenti che portano alla sua eleggibilità a standard. Le vedremo meglio in futuro, ma ricordiamo già da ora la transazionalità, ovvero la proprietà per cui l'esecuzione di diverse operazioni su diversi componenti o va tutta a buon fine, o fallisce completamente e non rimane niente in sospeso o a metà, e la possibilità di installare parti di software su macchine diverse per configurazione hardware e software.
OMG ha prodotto OMA (Object Management Architecture), che è uno standard al quale si rifanno le varie architetture di componenti.
Il Software Bus
Parlavamo prima della necessità di avere un linker dinamico. Concretamente, ciò si realizza mediante un software bus, ovvero un programma il cui scopo è quello di ricevere chiamate dai componenti e di smistarle agli altri componenti, attivandoli e disattivandoli a seconda delle necessità.
Così come un bus fisico, su di una scheda madre, riceve segnali e li smista ai controller giusti, così il bus software riceve messaggi dai componenti, e li smista ai destinatari giusti.
Il primo software bus è stato ORB, ovvero Object Request Broker. A partire da ORB è stato creato lo standard CORBA, cioè Common Object Request Broker Architecture. Noi non lo studieremo, lo ricordiamo solo per motivi storici.
Concettualmente, un software bus ha a che fare con:
- eventi: sono generati dai componenti, e vengono inoltrati al software bus. Gli altri componenti devono venir notificati dell'accadere di questi eventi
- naming: l'assegnamento ad ogni componente di una URN (Universal Resource Name) che permette l'identificazione univoca del componente stesso tra tutti gli altri registrati presso lo stesso software bus, così che si possa fare appello al componente giusto.
Le aziende di software inoltre coltivano un sogno segreto, relativo alle funzionalità del software bus. La loro speranza è che il software bus si possa accollare tutte le responsabilità non funzionali di un software, come ad esempio i requisiti di security, di persistenza e così via. Le aziende dovrebbero scrivere codice rispettando i soli requisiti funzionali, e con la serena certezza che tutti i requisiti non funzionali sarebbero stati gestiti ed implementati dal software bus. Pia speranza? Non lo sappiamo ancora.
Quando si sente parlare di middleware, altro non è che un appellativo del software bus: è "middle" perché sta in mezzo a tutti.
EJB
Enterprise Java Beans è l'architettura a componenti di Java. È strettamente language dependent, essendo stata pensata appositamente per Java.
L'idea su cui si sono basate le prime versioni di EJB era quella di avere client leggeri e server pesanti. La "pesantezza" riguardava due fronti: quello delle responsabilità, e quello del carico di CPU. Sulle macchine server dovrebbero girare degli application server, ai quali, nel corso degli anni, sono state demandate sempre più responsabilità, secondo la visione delle aziende illustrata prima.
Tuttavia, ci si è resi conto che proprio a livello di CPU il carico di lavoro per una singola macchina era un po' troppo, e ultimamente si sta facendo marcia indietro. Ricordo che la Sun qualche anno fa aveva lanciato dei thin client, ma non hanno avuto molto successo. L'impiegato medio non vuole un pc poco potente connesso ad un server centrale, perché non può giocare ad Open Arena nelle pause.
EJB ci offre un mare infinito di sigle, in puro stile Java. Le cito qui, senza svilupparle troppo:
- JNDI = il servizio di naming
- JDBL = connettività a database
- JTA e JTS = transactional API e Service
- JPS = Java Server Pages, ovvero la possibilità di eseguire programmi Java come script per pagine dinamiche
COM e DCOM
L'architettura COM è stata l'architettura principale di Windows per diversi anni. Da essa è nata DCOM, che altro non è che Distributed COM.
COM nasce da OLE, ovvero Object Linking ad Execution. OLE forniva, ai tempi, quella tanto decantata possibilità di linkare ad esempio un foglio di Excel in una pagina Word, e di farlo funzionare come se fossimo stati direttamente in Excel. Molti Office fa ciò era una sorta di miracolo, un passo in più rispetto al copia & incolla.
COM fornisce anche uno standard binario: le DLL per le librerie sulla stessa macchina, e le OCX per le librerie chiamate in una rete.
Un oggetto COM ha dei metodi e uno stato. Internamente è composto di classi. Ha almeno un'interfaccia esterna, chiamata IUnknown', che deve essere sempre presente. Quando chiamo un COM, posso chiamare la sua interfaccia IUnknown e farmi dire quali sono le altre interfacce, e che metodi esse hanno. Questo è comodo perché non sono obbligato a conoscere l'interfaccia di un metodo prima di chiamarlo. Ovvio che se invece la conosco salto l'intervista ad IUnknown e vado avanti direttamente.
COM offre inoltre la possibilità di estendere un'interfaccia, aggiungendo nuove funzionalità. Nel mondo della teoria, quando aggiorno un COM, dovrei tenere quello vecchio ed estenderlo con un COM nuovo. In questo modo, le applicazioni vecchie che facevano appello al COM vecchio potranno continuare a funzionare, mentre le applicazioni nuove potranno usare il COM nuovo.
Ma non è così.
Spesso, troppo spesso, le versione nuove sono andate a sostituire in toto le versioni vecchie. Espongono più o meno la stessa interfaccia, ma non le stesse funzionalità. Pertanto, accade che un'applicazione possa esplodere improvvisamente quando chiama un COM che all'apparenza è uguale a quello di cui lei ha nozione, ma che ritorna valori un po' diversi. Inoltre, diversi COM presentavano interfacce non documentate, e diverse applicazioni le utilizzavano.
Questo è il motivo per cui, dopo un po' di tempo, il sistema Windows diventa instabile. Windows non ha alcun modo per verificare quali versioni dei COM vengono installate, e quali versioni di un determinato COM sono desiderate da un'applicazione.
.NET
.NET sostituisce COM. Non è più basato sul codice nativo, ma sul bytecode, un po' come Java. Il problema di chiamate a COM misteriosi che fanno crashare tutto viene notevolmente ridimensionato, perché all'interndo di una virtual machine è più facile recuperare dagli errori senza far morire l'applicazione.
.NET in realtà presenta una Common Language Runtime, che è il target di destinazione per diversi linguaggi di programmazione, attraverso uno stack predefinito di librerie. Quando si compila un programma, questo viene tradotto in un linguaggio intermedio detto MSIL (Microsoft Intermediate Language), e poi compilato tramite tecniche JIT (Just In Time, cioè la prima volta che viene chiamato).
Il diagramma dei componenti
Dopo questa carrellata sulle architetture di componenti, dobbiamo ricordare che nei diagrammi di componenti non si mettono le proprietà del middleware che abbiamo appena visto. Al massimo, nelle note che lo corredano scriverò che useremo EJB, ad esempio, e poi se la vedranno i programmatori.
Va poi notato che questo trasferimento di responsabilità dal software al middleware si traduce in un parallelo trasferimento di reponsabilità dal programmatore al sistemista, e per questo motivo occorrono sistemisti in gamba.
...continua...
Torna alla pagina di Ingegneria del Software