• Non ci sono risultati.

Progetto dettagliato

5.4 Progetto dettagliato

In questa sezione consideriamo alcune linee guida per la fase di progetto in dettaglio. In questa fase vengono precisati i dettagli delle singole classi e associazioni, e vengono introdotte classi ed associazioni ausiliarie.

5.4.1 Progetto delle classi

Nella fase di progetto architetturale le classi definite nel modello di analisi vengono raggruppate in componenti, eventualmente insieme a qualche nuova classe introdotta in questa fase. Generalmente queste classi non sono sta-te definista-te completamensta-te, quindi nel progetto dettagliato bisogna arrivare prima di tutto al completamento della loro definizione. Per questo occorre:

1. specificare completamente attributi ed operazioni gi`a presenti, indican-do visibilit`a, modificabilit`a, tipo e direzione dei parametri;

2. aggiungere operazioni implicite nel modello, per esempio costruttori e distruttori;

3. aggiungere operazioni ausiliarie, se necessario.

Oltre a completare e raffinare le definizioni delle singole classi, si posso-no fare delle operazioni di ristrutturazione, per esempio scomponendo una classe in classi pi´u piccole, oppure riunendo pi´u classi in una, o ridistri-buendo fra pi´u classi le rispettive operazioni, sempre cercando la massima coesione entro ciascuna classe. `E possibile anche riorganizzare le gerarchie di generalizzazione.

5.4.2 Progetto delle associazioni

Le associazioni rappresentano i percorsi logici attraverso cui si propagano le interazioni fra i vari oggetti. Nel progetto delle associazioni si cerca di ottimizzare tali percorsi, ristrutturandoli se necessario, per esempio aggiun-gendo associazioni ausiliarie che permettono un accesso pi´u efficiente, o anche eliminando associazioni ridondanti.

Le associazioni devono poi essere ristrutturate in modo da permettere la loro implementazione nei linguaggi di programmazione. Questi, infatti, non hanno dei concetti primitivi che corrispondano direttamente alle associazio-ni, che devono quindi essere tradotte in concetti a pi´u basso livello. A questo

scopo bisogna prima di tutto che le associazioni definite nel modello di analisi (ed eventualmente nel modello architetturale) vengano specificate completa-mente, indicandone la navigabilit`a, le molteplicit`a ed i nomi dei ruoli, oppure il nome dell’associazione. Avendo precisato queste informazioni, si possono considerare i casi seguenti (Fig. 5.26).

1 1..* 1..* 1..* 1..* 1 1 1 1 1 1..* 1..* 1 account User Accont* account User Account User {ordered} User Account List<Account> Account User Ownership Account uno a uno uno a molti User Account molti a molti

Figura 5.26: Realizzazione delle associazioni.

Associazioni da uno a uno e da molti a uno

In questo caso l’associazione pu`o essere implementata come un semplice pun-tatore (e in questo caso si lascia immutata nel modello) o anche come un attributo, se la classe associata `e molto semplice (p.es., string) oppure se si vuole modellare una composizione.

Associazioni da uno a molti

Nell’associazione da uno a molti un’istanza della classe all’origine dell’as-sociazione `e associata ad un gruppo di istanze dell’altra classe. In questo

5.4. PROGETTO DETTAGLIATO 181 caso conviene introdurre una classe contenitore, possibilmente scelta fra le numerose classi (o template) di libreria disponibili per i vari linguaggi. La scelta della classe contenitore dipende dalle propriet`a del gruppo di istanze, in particolare quelle di unicit`a (se ogni elemento appare una sola volta o no) e dell’ordinamento. Queste propriet`a si possono rappresentare con le propret`a UML unique, nonunique, ordered, unordered. Per modellare le associazioni si pu`o scegliere di lasciarle come sono, con l’indicazione di queste propriet`a che serve da guida per il programmatore nella scelta della classe contenitore, oppure rappresentare questa classe esplicitamente.

Associazioni da molti a molti

Questo tipo di associazione si realizza introducendo una classe intermedia, come in Fig. 5.26, e risolvendo le asociazioni risultanti come nei casi prece-denti.

Letture

Capitolo 6

Convalida e verifica

Ogni attivit`a industriale richiede che vengano controllate la correttezza, la funzionalit`a e la qualit`a dei prodotti finiti, dei prodotti intermedi e dello stesso processo di produzione. Come spiegato nella Sez 2.1.7, nell’attivit`a di convalida i prodotti vengono confrontati con i requisiti dell’utente, mentre nella verifica il confronto avviene con le specifiche. Ricordiamo che i requisiti sono generalmente imprecisi e necessariamente informali, mentre le specifiche (risultanti dalla fase di analisi dei requisiti) sono precise e possono essere for-mali. La verifica pu`o quindi contare su procedimenti pi´u metodici e rigorosi, per`o non `e sufficiente ad assicurare la bont`a del prodotto, poich´e le specifiche stesse, che ne sono il punto di riferimento, possono non essere corrette rispet-to ai requisiti e devono essere a loro volta convalidate. Verifica e convalida devono quindi completarsi a vicenda. Aforisticamente, si dice che con la ve-rifica ci accertiamo che il prodotto sia fatto bene (building the product right) e con la convalida ci accertiamo che il prodotto sia quello giusto (building the right product).

Nel seguito, faremo riferimento solo alla verifica (e marginalmente al-la convalida) del codice, pur tenendo presente che, come gi`a accennato, i prodotti di ogni fase del processo di sviluppo devono essere verificati o convalidati.

6.1 Concetti fondamentali

Introduciamo qui alcuni concetti fondamentali nel campo della convalida e della verifica, cominciando dai termini errore, anomalia, e guasto1:

Guasto (malfunzionamento, failure) un comportamento del programma non corretto rispetto alle specifiche.

Anomalia (difetto, fault, bug) un’aspetto del codice sorgente che provoca dei guasti.

Errore errore concettuale o materiale che causa anomalie.

Gli errori sono quindi la causa delle anomalie, che a loro volta sono la causa dei malfunzionamenti. Osserviamo per`o che non c’`e una corrispon-denza diretta e biunivoca fra anomalie e guasti. Un particolare guasto pu`o essere provocato da una o pi´u anomalie, e l’effetto di una anomalia pu`o essere bilanciato, e quindi nascosto, da quello di un’altra. Alcune anomalie possono non provocare alcun guasto. Ma soprattutto, il problema fondamentale `e che in genere un malfunzionamento avviene in presenza di alcuni dati di ingresso e non di altri.

Le attivit`a rivolte alla ricerca e all’eliminazione delle anomalie si possono classificare come segue:

Analisi statica esame del codice sorgente. Analisi dinamica esecuzione del codice.

Debugging ricerca delle anomalie a partire dai guasti, e loro eliminazione. Conviene inoltre distinguere fra convalida o verifica in piccolo e in grande, cio`e a livello di singolo modulo (o unit`a) o di sistema.