Dr. Carlo Pescio
Object Oriented Analysis

Pubblicato su Computer Programming No. 35


Entriamo nel merito dell'approccio object-oriented all'analisi dei requisiti, introducendo il metodo principale per ottenere un modello object oriented a partire da una descrizione informale del sistema.

Introduzione
Nella scorsa puntata, abbiamo introdotto i concetti di analisi dei requisiti, design architetturale, design dettagliato, implementazione, testing e manutenzione del codice. Da questa puntata, inizieremo a considerare i dettagli dell'analisi dei requisiti, ed entreremo nel merito dell'approccio object oriented all'analisi dei sistemi.
Come abbiamo visto, l'analisi si concentra su cosa il sistema debba fare, non su come debba farlo; Il come e' dominio del design. Rimanendo sempre a livello di "slogan", occorre modellare il problema, non la soluzione. Cio' e' tutt'altro che semplice, in quanto una delle tecniche tipiche dell'uomo per affrontare la complessita' dei sistemi consiste nel risolvere alcuni problemi, confidando che il compito diventi gradatamente piu' semplice. In un certo senso, questo e' il principio di base del divide et impera, ma puo' nondimeno essere fuorviante nell'analisi di grandi sistemi, ove occorre sempre considerare le soluzioni dopo aver compreso, se possible, l'intero problema.

Gestire la complessita'
Uno dei cardini dell'ingegneria del software e' lo studio di tecniche per ridurre la complessita' intrinseca dei sistemi; cio' richiede non solo l'adozione di appropriate metodologie di sviluppo, ma anche la corretta forma mentale [1]: raramente gli hacker, per quanto brillanti, sono destinati a sfolgoranti carriere nello sviluppo di sistemi complessi. Un professionista sa bene che i sistemi sono complessi ed adotta ogni metodo di comprovata efficiacia per ricondurre la complessita' del sistema all'interno dei limiti efficacemente trattabili dagli esseri umani: se non altro, qualora si ritenga eccezionalmente capace, perche' altre persone possano accedere ai risultati del suo lavoro.
Ogni metodo di analisi e design proposto nel corso degli anni utilizza alcune tecniche di base per ridurre la complessita' del sistema a livelli piu' trattabili. L'astrazione sui dati e sulle funzioni e' una di tali tecniche: anziche' concentrarsi sull'intero sistema, si individuano gli elementi fondamentali e le loro relazioni, si modella un sistema piu' astratto, e poi si scende nel dettaglio dei singoli sottosistemi.
Alcuni metodi di analisi e design assumono poi prospettive diverse: in genere, alcuni si concentrano sui dati (intesi come struttura, ad esempio il modello entita'-relazione) o sulle funzioni (l'approccio strutturato). l difetti (che e' forse meglio definire limiti) di tali metodi, che restano comunque validi e che possono vantare, in alcuni casi, una visione formale che manca al modello object oriented, sono sostanzialmente due:

- non forniscono una visione globale del sistema, in quanto analizzano dati e funzioni in modo distinto o parziale.
- non sono omogenei nel passaggio da analisi a design ad implementazione.

L'approccio object oriented, i cui principi di base sono qui riassunti nella cornice "classi e oggetti", incapsula dati e funzioni in un'unica struttura (l'oggetto), permettendo quindi una visione piu' completa del ruolo dei dati e delle funzioni, ed ha inoltre il vantaggio di utilizzare le stesse tecniche di astrazione nei passi di analisi, design, ed implementazione, che pertanto possono essere visti come raffinamenti successivi di un unico processo. Questo riduce gli errori dovuti all'errata interpretazione dei documenti di analisi durante il design, o del design durante l'implementazione, e rende piu' semplice la previsione dell'impatto che modifiche a livello di requisiti o di design potranno avere in fase di manutenzione. Inoltre, tende a ridimensionare un problema ben noto, ovvero "la sindrome di incompetenza apparente": nell'uso delle tecniche strutturate, ad esempio, accade spesso che i programmatori giudichino i progettisti e gli analisti incompetenti, e viceversa. Cio' e' in gran parte motivato dal fatto che l'analisi tende ad essere cosi' distante dall'implementazione che le richieste nei due sensi sono viziate da una grande incomprensione di fondo. In molti casi, la comunicazione tra i vari livelli e' piu' semplice se si utilizzano le metodologie object oriented, poiche' le diverse figure professionali parlano un linguaggio comune, anche se si concentrano su aspetti diversi ed hanno attitudini diverse (un bravissimo programmatore con scarse attitudini per le pubbliche relazioni avra' comunque problemi nel ruolo di analista).
Altra caratteristica fondamentale dell'approccio orientato agli oggetti, se confrontato ad esempio con la progettazione secondo il metodo data-flow od il metodo di Jackson [2] e' la mancanza di sequenzialita'. In particolare, il metodo data-flow e' strettamente legato all'idea di una trasformazione sequenziale dei dati; tuttavia, le modalita' operative, e quindi le sequenze di operazioni eseguite, sono uno dei punti piu' frequentemente soggetti a modifiche durante la vita del sistema. Cio' rappresenta un punto debole dei metodi citati, in quanto l'analisi stessa tende a modificarsi in modo anche radicale quando le modalita' operative cambiano; questo si riflette negativamente sul design e sull'implementazione.
Nell'approccio object-oriented, invece, l'idea stessa di sequenzialita' e' in larga misura assente: un oggetto ha un suo stato interno e delle funzioni che operano su di esso. In principio, non vi e' nessuna regola che dica "la funzione 'a' deve essere chiamata prima della funzione 'b'"; se vi trovate in casi simili, probabilmente vi e' un errore nel vostro modello. Da notare che, a livello di design e di implementazione, operazioni impossibili da compiere quando l'oggetto e' in un determinato stato (il pop di un elemento da uno stack vuoto) verranno gestite con asserzioni ed eccezioni, ma in generale non vi sono dipendenze temporali tra le funzioni proprie di un oggetto. La mancanza di sequenzialita' intrinseca sembra molto promettente per la programmazione parallela e concorrente [3].

Il riutilizzo del software inizia dall'analisi
Molti testi che trattano l'analisi ed il design secondo un particolare approccio (data flow, strutturata, object oriented, eccetera) hanno la sfortunata tendenza a considerare l'analisi come un evento unico nella storia dei sistemi. In realta', sistemi tra loro simili vengono continuamente costruiti e migliorati: il riutilizzo, tanto popolare di questi tempi, dovrebbe cominciare dalla fasi di analisi e di design.
Supponiamo che vi venga commissionato un sistema per l'analisi dei dati in tempo reale; dopo le necessarie discussioni con il cliente, e' molto saggio non gettarsi immediatamente a modellare il sistema, ma analizzare se possibile alcuni prodotti simili e cercare di ricostruire i requisiti che hanno portato alla costruzione di un simile sistema (una forma di reverse-engineering molto blanda). In questo modo, potremmo giungere a conclusioni sorprendenti circa la completezza dei dati che abbiamo raccolto dalle nostre discussioni con il committente, e avremo modo di considerare, durante la fase di modellazione vera e propria, anche il "punto di vista" di altri prodotti.
Altro scenario tipico di riutilizzo e' lo sviluppo di un sistema simile ad uno precedentemente realizzato: tale evento e' abbastanza comune per gli esperti di un particolare settore. In realta', gli esperti sono piu' produttivi e ottengono in genere risultati migliori nel loro campo di competenza, proprio perche', in modo piu' o meno cosciente, riutilizzano conoscenze, strutture, modelli tra i vari progetti. Il riuso del codice stesso e' invece spesso impedito da clausole contrattuali.
Queste semplici norme di buon senso hanno portato anche allo sviluppo di alcuni settori di ricerca, che tentano di portare tali nozioni a livello piu' formale e strutturato; lo studio dei design patterns [4] e' una delle nuove interessanti promesse dell'ingegneria del software, la cui semplice filosofia di fondo e' di creare un catalogo di strategie di attacco per i diversi problemi (comunicazione tra processi in ambiente distribuito, realizzazione di automi finiti, eccetera). E' interessante notare che in alcuni settori dell'informatica, come lo sviluppo di compilatori, esista gia' una classificazione dei problemi cosi' ampia che una gran parte del dominio (grammatiche, analizzatori lessicali, parser) si puo' considerare esplorata e formalizzata; non a caso, in tali settori possiamo trovare degli ottimi strumenti per la generazione automatica di codice (compiler compilers).

Usare il giusto metodo di analisi
Per quanto l'approccio object-oriented sia molto versatile ed efficace, non sempre si dimostra il migliore: cio' avviene in quanto si tratta tutto sommato di un paradigma giovane. Se consideriamo il succitato sviluppo di compilatori, troveremo una enorme bibliografia ed ottimi tool, tuttavia quasi nulla e' stato pensato in termini object-oriented; ricondurre risultati noti all'interno di un paradigma differente puo' essere intellettualmente stimolante, ma professionalmente deleterio se si hanno tempi piuttosto stretti.
Lo stesso avviene in diversi altri settori: nel corso degli anni, sono stati sviluppati alcuni metodi specializzati per la soluzione di problemi specifici; spesso si indicano tali linee guida, metodi e soluzioni stereotipate come problem frames [5]. Se le vostre necessita' ricadono esattamente in uno dei frames esistenti, cercare una soluzione ex-novo con l'approccio object oriented puo' non essere l'approccio vincente; puo' invece essere interessante applicare le metodologie object oriented a specifiche fasi di uno dei frames esistenti (ad esempio, all'interno dell'Environment-Effect frame per modellare sistemi embedded). Con questa dovuta precisazione, intesa a ricordare che non esiste la soluzione definitiva a tutti i problemi, terminiamo la parte introduttiva per concentrarci invece sulle peculiarita' del paradigma object oriented.

Iniziare l'analisi
Il primo passo dell'analisi e' certamente l'acquisizione della conoscenza necessaria a comprendere il dominio del problema: l'analista dovra' essere in grado di discutere con gli specialisti dimostrando competenza e di trasformare il risultato delle sue conversazioni in un modello chiaro e completo della realta'. Meglio ancora, dovra' essere in grado di raggiungere rapidamente una comprensione dell'insieme (non dei dettagli) persino piu' organica della visione dei committenti: d'altra parte, e' spesso da questo che la sua professionalita' viene giudicata. Conseguenza diretta di tale necessita' e' la tendenza a diventare "esperti" di un settore, evitando il continuo apprendimento di realta' differenti; "l'esperto" di automazione industriale conosce a fondo le problematiche tipiche e la terminologia adeguata per l'ambiente in cui opera e i suoi passati successi possono positivamente influenzare l'eventuale committente.
Il secondo passo, che puo' in una certa misura coincidere con il primo, consiste in una serie di discussioni o "interviste" con il committente, con i potenziali utenti, ed eventualmente con altre figure di contorno, che siano di rilevanza ai fini della comprensione del problema. Risultato di tali conversazioni e' normalmente una raccolta di requisiti, vincoli, richieste e desideri, espressi in modo tutt'altro che formale, esplicito o consistente. In questa fase, e' spesso utile rimanere ad un livello di astrazione piuttosto elevato, evitando di concentrarsi sui dettagli del problema.
La terza fase, com'e' semplice capire, consiste nel filtrare i requisiti ottenuti in modo da ottenere un modello piu' chiaro del problema, sempre espresso in linguaggio naturale, seppure eventualmente con l'ausilio di grafici; naturalmente, le varie fasi possono in parte coincidere, per cui non e' irrealistico pensare di abbozzare un primo modello object oriented gia' a questo punto. Tuttavia vi sono buone ragioni per rimanere a livello di linguaggio naturale: normalmente, infatti, il risultato delle interviste e' un groviglio inconsistente, ed a questo punto dovremo tornare a confrontarci con committente, esperti, utenti, e cosi' via, sino ad ottenere un primo livello di confidenza nella rappresentazione informale del problema.
Infine (quarta fase) potremo passare dal linguaggio naturale al formalismo object oriented, con le tecniche che vedremo tra breve; di norma, alcuni punti saranno incompleti, e potremo concentrarci su di essi singolarmente, ripetendo le fasi precedenti. Almeno, in teoria; nel mondo reale, spesso le varie fasi si sovrappongono in modo tale da rendere indistinguibili i confini, e spesso ci si trova a discutere con l'utente sulla base di classi ed oggetti. Vedremo in seguito alcuni accorgimenti per rendere la specifica object-oriented dei requisiti piu' comprensibile anche per i non addetti, evitando frustrazioni ed incomprensioni.

Dalle parole alle classi
Esistono diverse tecniche che guidano verso la formalizzazione dei requisiti informali cosi' raccolti in un diagramma object oriented; il metodo qui presentato e' stato introdotto da Booch [6] ed in seguito raffinato dallo stesso e da altri influenti autori, tuttavia in questa sede ho ritenuto opportuno arricchirlo con note e consigli tratti dall'esperienza su progetti reali, nonche' adattarlo meglio alla grammatica italiana. Se avete relegato alcune definizioni tipiche dell'analisi logica (predicati verbali, predicati nominali, avverbi, ecc) nei recessi dei vecchi compiti di scuola, un piccolo ripasso di queste nozioni ormai lontane non fara' male alla comprensione della tecnica qui esposta. Vedremo ora la strategia generale, per tornare in seguito se necessario a ridiscutere i singoli punti.
Come abbiamo visto, l'analisi dei requisiti si concentra su cosa deve essere fatto, non su come; vedremo ora che l'analisi object oriented si concentra innanzitutto su chi debba fare qualcosa, e poi su cosa debba fare.
La formalizzazione inizia individuando all'interno della descrizione informale del sistema, ottenuta come risultato dei passi precedenti, tutti i nomi e le parti nominali, cercando, se non lo si e' gia' fatto, di eliminare i sinonimi e gli omonimi, sostituendone le occorrenze o costruendo un dizionario dei termini. Gli elementi evidenziati potranno essere oggetti, o classi, o attributi di un oggetto. Infatti, nella descrizione in linguaggio naturale i nomi giocano solitamente il ruolo di soggetti o complementi oggetto, oppure definiscono caratteristiche di altri oggetti. Potranno esistere particolari relazioni tra gli oggetti cosi' trovati (ereditarieta', contenimento), che tuttavia verranno analizzate in seguito. Osserviamo che mentre un nome puo' individuare un attributo, non tutti gli attributi sono individuati dai nomi (vedremo oltre come trovarli esaustivamente). Il risultato, a questo punto, e' un insieme di nomi che possono corrispondere a classi, oggetti, od attributi.
Occorre ora eseguire un primo passo di raffinamento: inizialmente, abbiamo insistito sull'importanza di modellare il problema e non la soluzione. In realta', e' abbastanza normale "inquinare" la descrizione informale con elementi appartenenti allo spazio della soluzione anziche' allo spazio del problema. Cio' puo' essere anche intenzionale, ai fini di ottenere una migliore presentazione e strutturazione del modello informale, tuttavia e' indispensabile filtrare tali elementi prima di proseguire. Non necessariamente dovremo eliminare parte del lavoro fatto: potremmo ad esempio conservare le informazioni importanti in un promemoria per il design.
Cerchiamo ora di distinguere, all'interno dello spazio dei nomi, tra oggetti/classi ed attributi; questo passo puo' essere controverso, ovvero possono esistere diverse partizioni tutte lecite e consistenti: d'altra parte, il lavoro di analisi comprende anche la valutazione di modelli alternativi e di punti di vista contraddittori. Se vi trovate in una situazione di ambiguita' che non riuscite a risolvere, in funzione del tempo che potete dedicare all'analisi potete scegliere il modello apparentemente piu' realistico (e confidare nella saggezza della scelta) o portare a termine l'analisi secondo le alternative piu' sensate e confrontare i risultati finali, al limite in termini del design risultante.
Gli oggetti e le classi si distinguono dagli attributi in quanto elementi attivi del sistema (ovvero, essi svolgono delle funzioni all'interno del sistema stesso): ad esempio, un contenitore puo' essere un elemento attivo, mentre la sua dimensione od il suo colore (notiamo che sono comunque nomi!) saranno in genere elementi descrittivi del sistema stesso, ed in quanto tali attributi.
Esiste un metodo piu' sistematico per la ricerca di classi ed oggetti? Normalmente, si possono utilizzare le azioni contenute nella descrizione informale, che associate ai soggetti che le realizzano permettono di distinguere tra oggetti ed attributi.
Vediamo in dettaglio: si evidenziano tutti i verbi, le parti verbali ed i predicati verbali; ogni azione viene poi associata ad un soggetto nello spazio dei nomi. Tali nomi saranno eleggibili a dignita' di oggetto o classe, in quanto elementi attivi del modello. Nuovamente, e cio' vale ad ogni passo ed evitero' quindi di ripeterlo in seguito, grande attenzione va prestata a sinomi e omonimi; inoltre, termini estremamente ambigui come "fare" andrebbero innanzitutto sostituiti con altri dalla semantica piu' caratterizzante.
A questo punto, i nomi rimanenti sono probabilmente attributi, e come tali vanno ricondotti ad elementi gia' trasferiti nello spazio degli oggetti/classi. Se non e' possibile capire a quale oggetto/classe faccia riferimento un attributo, probabilmente c'e' un errore nel modello ed occorre riesaminare con attenzione le scelte eseguite. Notiamo che alcuni dei nomi rimanenti potrebbero essere oggetti che giocano un ruolo esclusivamente passivo, tuttavia cio' e' spesso indice di un modello inesatto.
Come abbiamo visto, non e' sufficiente analizzare lo spazio dei nomi per trovare tutti gli attributi; occorre considerare anche gli aggettivi: ad esempio, nella frase "contenitori rossi e gialli" abbiamo una possibile classe "contenitore", ed un attributo implicito "colore" individuato dagli aggettivi "rossi" e "gialli". La strategia in questo caso e': evidenziare gli aggettivi, risalire dall'istanza dell'aggettivo (come "rossi" e "gialli") alla caratteristica generale (colore), trovare l'oggetto/classe cui tale aggettivo si riferisce, ed aggiungere il corrispondente attributo.
Osserviamo che, come sottoprodotto della distinzione tra oggetti/classi ed attributi, abbiamo gia' ottenuto l'elenco delle operazioni (metodi) che ogni oggetto/classe deve compiere. Le operazioni avranno in genere dei parametri, che possono essere estratti dalla descrizione informale considerando sia i complementi oggetto della frase, sia gli avverbi associati ad ogni verbo relativo ad una classe. In genere, molti dei parametri saranno gia' presenti come oggetti od attributi nella descrizione del problema; in ogni caso, una valutazione critica del modello e' indispensabile in ogni fase.
Veniamo infine all'ultimo passo fondamentale per la realizzazione di uno schema di massima (mancheranno infatti le relazioni tra oggetti, che considereremo piu' avanti): la distinzione tra oggetti e classi, e la conseguente astrazione (nel modello object oriented, compariranno solo le classi; gli oggetti compaiono solo come parametri delle operazioni).
In gran parte, la distinzione fra oggetti e classi e' un semplice processo di astrazione: da un'istanza della classe (ovvero un oggetto) presente nella descrizione informale del sistema, e ormai presente nella partizione oggetto/classe dello spazio dei nomi, si deve risalire al concetto generale, alla classe astratta cui l'oggetto appartiene. Si tratta di un compito in genere molto semplice per gli esseri umani, ed in effetti gran parte dell'efficacia dell'approccio object oriented risiede proprio nell'utilizzo di schemi di classificazione tipici della mente umana.
Entro certi limiti, tuttavia, possiamo farci nuovamente coadiuvare dall'analisi logica della descrizione informale: in genere, i predicati nominali con sostantivo aggettivizzato ("le mosche sono insetti") indicano una relazione oggetto/classe. Tuttavia, per esperienza, posso dire che simili frasi sono molto rare nelle descrizioni dei sistemi.

Alcune importanti note
Per quanto il metodo descritto sembri semi-algoritmico, in realta' vi e' un ampio spazio discrezionale: in molti casi, decidere se qualcosa fa parte dello spazio del problema o delle soluzioni e' un compito arduo; lo stesso dicasi, in casi non banali, per la selezione degli oggetti e degli attributi. Pertanto, e' importante almeno inizialmente sperimentare visioni alternative, specialmente se vi sono scelte opinabili, e puo' essere realmente utile confrontare le proprie idee con altri specialisti. Ricordate sempre che i metodi e le tecniche sono importanti, ma non vi sono sostituti per il talento e l'esperienza.
Inoltre, il metodo su esposto non e' l'unico approccio all'analisi object oriented, per quanto sia il piu' universalmente accettato per la sua comprovata validita'. Ad esempio, alcuni sviluppatori ripongono grandi speranze nel metodo RDD, Responsibility-Driven-Design, che al di la' del nome e' in realta' in gran parte un metodo di analisi per lo spazio dei problemi. Gli approcci alternativi saranno l'argomento di una futura puntata, dopo che il metodo qui presentato sara' stato completamente discusso ed esemplificato.
Infine, specialmente trattando sistemi di grandi dimensioni, puo' essere utile l'impiego di uno strumento C.A.S.E. (Computer Aided Software Engineering) che supporti l'OOA e magari anche l'OOD e l'OOP. In una futura puntata, presenteremo alcuni degli strumenti esistenti e analizzeremo le caratteristiche salienti dei migliori ambienti per il supporto all'analisi object oriented.

Rappresentare il primo risultato
Veniamo al risultato di questa prima formalizzazione dei requisiti: avremo distinto le varie classi, i loro attributi, le loro operazioni, ed i parametri delle operazioni stesse. Come possiamo rappresentare tali strutture? Ovviamente, possiamo cercare di mantenere tutto a livello di linguaggio naturale, tuttavia qualche ausilio schematico si rivela presto prezioso per rendere l'intero modello maneggevole. In effetti, esistono diversi schemi grafici per la rappresentazione di classi, attributi, relazioni tra classi, e cosi' via, e si tratta infatti di un argomento che approfondiremo adeguatamente, insieme con una serie di considerazioni psicologiche sulle rappresentazioni grafiche.
Tuttavia, lo scopo della prima formalizzazione e' solo quello di trasformare i requisiti informali, raccolti da discussioni ed interviste, in un modello piu' organico, che comunque dovra' ancora essere discusso a fondo con utenti, committenti ed esperti, prima di passare a raffinare il modello.
A tal fine, una rappresentazione in forma tabulare, come si puo' vedere in figura 1, e' normalmente piu' semplice e meno intimidatoria per i non addetti di un complesso grafo con classi e relazioni. Notiamo che il livello di precisione e' alto ma il livello di dettaglio e' minimo: in particolare, per gli attributi non sono ancora stati stabiliti i tipi corrispondenti, operazione che spesso si rimanda alla fase di design. Le colonne "azioni" e "parametri e risultato" possono essere fuse in un'unica colonna, introducendo un minimo di sintassi piu' formale, o lasciate separate come nell'esempio dato, dove e' comunque evidente che i parametri si riferiscono all'azione immediatamente a sinistra sulla stessa riga.
Alcuni autori (es. Coad e Yourdon) suggeriscono di utilizzare dei fogli adesivi, tipo Post-It, per le varie caselle, in modo che gli elementi della tabella si possano sostituire agevolmente durante le discussioni; ovviamente, a questo punto si scende piu' che altro nel gusto personale.

Fig. 1
Un esempio di rappresentazione tabulare degli oggetti
Oggetto o ClasseAttributi AzioniParametri e risultato
Sensoreunita' misurata

range ammissibile

deriva termica

...eccetera...

Taratura

Lettura

Posizionamento

valori di riferimento

restituisce valore

posizione geometrica

Motore elettricopotenza

numero di giri al minuto

...eccetera

Start

Stop

Singolo Passo

nessuno

nessuno

nessuno

Verificare il modello
Il momento principale della verifica per il modello e' proprio la presentazione del modello stesso agli utenti o agli esperti del ramo: spesso le incomprensioni ed i malintesi, avuti al momento delle discussioni iniziali, emergono quando il committente inizia ad elencare mancanze nel modello o l'inaderenza del modello stesso alla sua realta' operativa. Nuovamente, in questi casi e' indispensabile usare un tatto da mediatore, poiche' e' possibile che voi abbiate frainteso le sue richieste o che semplicemente il committente non sia in grado di seguirvi nelle vostre astrazioni. Talvolta e' utile fare uso di qualche metafora: un banale parallelo tra lo sviluppo di piccoli e grandi progetti software con la costruzione di una casetta di legno e di un grande palazzo, e delle diverse tecniche e competenze necessarie, e' talvolta piu' convincente di una citazione colta o di un'esposizione eccessivamente tecnica. Ricordate sempre che l'aspetto umano e' fondamentale durante l'analisi dei requisiti.
Una volta che il modello sia in qualche modo accettabile per l'utente, occorre una verifica di tipo tecnico; cosi' come vi sara' capitato di vedere codice scritto da principianti, e definirlo a colpo d'occhio come una schifezza, anche un modello object oriented puo' essere di qualita' molto bassa. Tuttavia, non esistono molti criteri oggettivi su cui basare una valutazione di qualita' dell'analisi: in effetti, mentre nella fase di codifica alcune metriche sono, se non proprio di uso comune, almeno abbastanza diffuse, a livello di analisi e design object oriented il materiale bibliografico sulle valutazioni metriche e' molto scarno, ed e' soprattutto rivolto al design (e verra' quindi presentato quando giungeremo a tale fase); in ogni caso, elenchero' qui di seguito alcuni accorgimenti che possono risultare utili per valutare la bonta' del modello; in gran parte, sono basati sulla mia esperienza personale. Questo elenco si arricchira' in seguito, quando considereremo anche le relazioni tra le classi; al solito, le eccezioni sono sempre presenti, per cui i criteri esposti vanno considerati delle linee guida e non dei sacri comandamenti.

- Usate il linguaggio e la terminologia adatta al problema da modellare. Ogni settore ha una sua terminologia specifica, e comprendere ed usare le parole adatte semplifichera' enormemente la comunicazione con gli addetti ai lavori. Questa raccomandazione si estende anche al design, ed in larga misura anche all'implementazione.
- Il modello dovrebbe riflettere il problema: se all'interno del modello vi sono elementi "di informatica" come code, stack, automi, e cosi' via, probabilmente state modellando la soluzione e non il problema.
- Le classi dovrebbero essere significative: dovrebbero cioe' corrispondere ad oggetti reali o a concetti propri del dominio del problema. Se non sapete bene che nome dare ad una classe, il modello e' probabilmente mal fondato.
- Le classi dovrebbero essere limitate ad uno stesso livello di astrazione: un modello di un sistema complesso e' spesso realizzato per passi di specializzazione successivi, dove inizialmente si fornisce un modello di massima e poi si analizza in dettaglio ogni componente. Evitate di avere all'interno dello stesso modello classi che siano concettualmente poste a livelli di astrazione molto distanti: "sistema di controllo del traffico aereo" e "lampadina di emergenza" sono ad esempio troppo lontani come dimensione, non solo fisica, per figurare in uno stesso diagramma.
- gli attributi dovrebbero essere semplici: essi dovrebbero riflettere qualita', caratteristiche o stati d'essere dell'oggetto a cui appartengono. Attributi strutturati sono rari e indicano che forse si e' forzato un oggetto in un attributo. Un attributo strutturato come insieme o sequenza di dati elementari omogenei puo' ancora essere accettabile, ma in genere attributi strutturati eterogenei (ad esempio, uno "stato" che comprenda temperatura, pressione, velocita', e cosi' via) devono essere separati nelle loro parti essenziali o assumere la dignita' di oggetto. In questo, vi e' una certa somiglianza con uno dei passi di normalizzazione nel modello relazionale.
- i metodi sono sempre definiti? Abbiamo visto che una delle caratteristiche degli oggetti e' di avere un insieme di metodi che possono essere richiamati in ogni momento. Non vi sono dipendenze temporali esplicite in un modello object oriented. Ovviamente un'operazione puo' fallire se eseguita a partire dallo stato sbagliato, ma occorre verificare che l'operazione "abbia senso" in se' quando applicata in ogni stato. Se cio' non accade, probabilmente e' piu' opportuno introdurre solo qualche funzionalita' di livello piu' alto a livello di analisi, e lasciare la specifica di tali operazioni alla fase di design.
- vi sono parametri troppo ricorrenti nei metodi? Se un elemento, sia esso modellato come un attributo o come un oggetto, e' presente troppo spesso come parametro di funzioni, e' possibile che il modello non sia corretto, ovvero che un oggetto attivo sia stato modellato come passivo. In questo caso, Meyers [7] suggerisce la "regola dell'inversione", ovvero se un dato e' troppo presente nelle funzioni, spostare le funzioni nel dato. Cio' significa far giocare al dato il ruolo di oggetto attivo, spostando le funzioni, che prima prendevano l'oggetto come parametro, all'interno della classe dell'oggetto stesso. Cio' non sempre e' possibile: talvolta, dopo la modifica alcuni altri oggetti, prima attivi, appaiono costantemente come parametri; in tal caso, siamo comunque di fronte ad un modello con un elevato grado di accoppiamento fra le classi, e sarebbe opportuno considerare se non esiste qualche modello alternativo, magari radicalmente diverso, o se piu' semplicemente non abbiamo analizzato il problema in modo superficiale; tuttavia, questa semplice tecnica puo' spesso guidare alla felice ristrutturazione di un modello troppo interconnesso.

Raffinare il modello Il modello cosi' ottenuto e' ancora piuttosto grezzo: in particolare, manca ogni relazione tra le diverse classi, come il contenimento o l'ereditarieta'; le relazioni fra gli oggetti costituiranno il nucleo della prossima puntata. Potete comunque iniziare a sperimentare il metodo descritto su qualche caso concreto, magari su problematiche gia' risolte, e confrontare i risultati cosi' ottenuti con le vostre precedenti realizzazioni.

Reader's Map
Molti visitatori che hanno letto
questo articolo hanno letto anche:

Bibliografia
[1] Dijkstra E.: "The Humble Programmer", Communications of ACM, Ottobre 1972.
[2] Jackson M.: "System Development", Prentice-Hall, 1983.
[3] Chandra, Gupta, Hennessy: "Cool: An Object-Based Language for Parallel Processing", IEEE Computer, Agosto 1994.
[4] Gamma, Helm, Johnson, Vlissides: "Design Patterns", Addison-Wesley, 1994.
[5] Jackson M.: "Problems Methods and Specialization", Software Engineering Journal, Novembre 1994.
[6] Booch G., "Object Oriented Design", Ada Letters, Marzo/Aprile 1982.
[7] Meyers B., "Object Oriented Software Construction", Prentice-Hall, 1988; edizione italiana: "La Produzione del Software Object Oriented", Gruppo Editoriale Jackson, 1991.

Biografia
Carlo Pescio (pescio@acm.org) svolge attivitÓ di consulenza in ambito internazionale nel campo delle tecnologie Object Oriented. Ha svolto la funzione di Software Architect in grandi progetti per importanti aziende europee e statunitensi. ╚ incaricato della valutazione dei progetti dal Direttorato Generale della ComunitÓ Europea come Esperto nei settori di Telematica e Biomedicina. ╚ laureato in Scienze dell'Informazione ed Ŕ membro dell'ACM, dell'IEEE e della New York Academy of Sciences.