Anteprima
Vedrai una selezione di 6 pagine su 24
Progettazione del Software - parte 1 Pag. 1 Progettazione del Software - parte 1 Pag. 2
Anteprima di 6 pagg. su 24.
Scarica il documento per vederlo tutto.
Progettazione del Software - parte 1 Pag. 6
Anteprima di 6 pagg. su 24.
Scarica il documento per vederlo tutto.
Progettazione del Software - parte 1 Pag. 11
Anteprima di 6 pagg. su 24.
Scarica il documento per vederlo tutto.
Progettazione del Software - parte 1 Pag. 16
Anteprima di 6 pagg. su 24.
Scarica il documento per vederlo tutto.
Progettazione del Software - parte 1 Pag. 21
1 su 24
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

USES

A uses B significa che A può accedere ai servizi esportati da B attraverso la sua interfaccia. È definito

"staticamente". A dipende da B per fornire i suoi servizi. Quindi A è un cliente di B.

IS_COMPONENT_OF

Usato per descrivere un modulo di livello superiore come costituito da un certo numero di moduli di livello

inferiore. A IS_COMPONENT_OF B significa che B è costituito da diversi moduli, di cui uno è A.

INHERITS

Se il sistema è sviluppato in uno stile orientato agli oggetti, la relazione di ereditarietà consente a un

componente di estenderne un altro. Un erede può accedere ai segreti (alcuni) del suo antenato. I componenti

sono più fortemente connessi con INHERITS che tramite USES.

Contratti

Il modulo (classe) è di per sé una risorsa: è usato da altri per generare istanze. Si introduce la relazione di

ereditarietà, per fattorizzare una parte comune in un componente. Le modifiche (variazioni) sono dei delta

definiti nei sotto-componenti. L'ereditarietà aggiunge ulteriori interdipendenze tra i moduli.

Il design per contratto raffina un principio di design noto, particolarmente adatto per la progettazione OO:

l'interfaccia del modulo (classe) definisce un contratto. Un contratto è un accordo tra un cliente e un

imprenditore. Definisce gli obblighi per ottenere i benefici.

Le precondizioni definiscono ciò che ogni metodo richiede (obbligo per il cliente), mentre le post-condizioni

definiscono ciò che fornisce ogni metodo (obbligo per il contraente). Le precondizioni e le post-condizioni

possono essere espresse usando la logica.

Dovrebbe essere preparata una routine per gestire eventuali input? NO! Ma se la precondizione è debole

(TRUE ovvero senza alcun vincolo), tutti i controlli sarebbero delegati alla routine. Se invece se precondizione

è forte (FALSE ovvero che non può essere invocata da nessuno) la routine non lavora mai. La scelta del

presupposto è una decisione di progettazione: non esiste una regola assoluta, però è preferibile scrivere

semplici routine che soddisfano un contratto ben definito piuttosto che una routine che cerca di tentare ogni

situazione immaginabile.

Possiamo specificare una proprietà che tutti i casi dovrebbero soddisfare: l’invariante. L'invariante è vera

dopo la creazione e prima e dopo ogni operazione. L'invariante definisce un ulteriore obbligo di prova:

l’implementazione della classe la deve soddisfare.

Quindi in una classe:

 1

Costruttori: precondizione -> costruttore -> invariante

 1

Metodi: precondizione & invariante -> metodo -> post-condizione & invariante

Per le precondizioni vale che il cliente è responsabile della loro verità, ma può essere impossibile valutare

l'applicabilità prima dell'applicazione dell'operazione.

Le eccezioni dovrebbero essere sollevate se una delle seguenti condizioni è violata:

 Precondizione

 Invariante

 Post-condizione

Quando il controllo lascia una routine, la sua post-condizione e l'invariante sono vere o viene restituita

un'eccezione. Le eccezioni restituite dovrebbero essere elencate nell'interfaccia della routine.

Le sottoclassi possono aggiungere attributi e metodi e possono ridefinire i metodi, ma hanno dei vincoli

sintattici: covarianza del risultato e contro varianza dei parametri. Inoltre ci sono dei vincoli di semantica:

precondizioni della classe sono figlie delle precondizioni della sottoclasse, mentre le post-condizioni della

sottoclasse sono figlie delle post-condizioni della classe. Ovvero: data una classe A e una sua sottoclasse B, ci

sia un metodo in A che restituisce C e che ha come parametro E, allora se B ridefinisce questo metodo

facendogli restituire D e dandogli come parametro F, deve valere che D estenda C e che E estenda F.

Stili

La comprensione condivisa delle forme di disegno comuni è tipica dei campi di ingegneria maturi. Il

vocabolario condiviso di idiomi di progettazione è codificato in manuali di ingegneria. Il software sta andando

in questa direzione: ma c'è meno maturità.

Esistono componenti e connettori. I componenti possono essere: client, server, filtri, database, strati, …,

mentre i connettori possono essere: chiamate a procedure, eventi broadcast, protocolli database, tubi, ….

Architettura funzionale

Il sistema si decompone in operazioni astratte. Le operazioni si conoscono e si chiamano l’un l’altra. I

connettori sono le chiamate a procedure e i valori di ritorno. Ci sono connettori aggiuntivi tramite dati

condivisi. Esso è lo sviluppo di sistema "tradizionale": le funzioni sono subroutine di programmi monolitici e

i dati sono dati "comuni" tra le routine. Sviluppo di sistema orientato agli oggetti: le funzioni sono metodi di

una classe e i dati sono i dati della classe.

Sistema a strati

Il sistema è organizzato attraverso livelli di astrazione, come una gerarchia di macchine astratte (cipolla).

L’ereditarietà e la gerarchia sono date dalla relazione USE.

Tubi e filtri

I filtri ottengono e mettono i dati sui loro tubi di ingresso e uscita; ignorano l'esistenza (e l'identità) di altri

filtri. Sono possibili diversi regimi di controllo: batch sequenziali e batch concorrenti. I vantaggi sono: che il

sistema è compositivo (comportamento complessivo come composizione dei comportamenti individuali),

orientamento al riuso (tutti i filtri possono essere messi insieme in linea di principio) e la facilità di modifica

(si può aggiungere/sostituire i filtri). Gli svantaggi sono che non c’è persistenza e la tendenza a un

organizzazione a batch.

Sistemi basati su eventi

Gli eventi vengono trasmessi a tutti i componenti registrati. Nessuna denominazione esplicita del

componente bersaglio. I suoi vantaggi sono: che gli eventi vengono trasmessi a tutti i componenti registrati,

che non c’è nessuna denominazione esplicita del componente bersaglio, che sono sempre più utilizzati per

le moderne strategie di integrazione e che è facile aggiungere e cancellare registrazioni di componenti. Gli

svantaggi sono che ci possono essere potenziali problemi di scalabilità e che non esiste un ordine degli eventi.

Sistemi basati su repository

I componenti comunicano solo attraverso un repository. Di solito i componenti sono attivi, il repository è

passivo e un ulteriore componente (gestore transazioni) legge le transazioni di ingresso e chiama funzioni

appropriate.

Ma esistono anche casi (come il caso Blackboard) dove i componenti leggono e scrivono nel Blackboard. Le

modifiche dello stato del Blackboard attivano dei componenti: un Blackboard è un repository attivo.

UML

Ragionare sui sistemi complessi è difficile. Costruire sistemi complessi è difficile. Come valutare aspetti

notevoli dei sistemi o l’efficacia di soluzioni costruttive senza affrontare l’intera complessità di un sistema

reale?

I modelli rappresentano il linguaggio dei progettisti: rappresentano il sistema da costruire o costruito, sono

un veicolo di comunicazione e descrivono in modo “visuale” il sistema da costruire. I modelli sono uno

strumento per gestire la complessità. I modelli consentono di analizzare caratteristiche particolari del

sistema.

Un sistema reale è caratterizzato da un alto numero di elementi e spesso solo una minima parte di tale

elementi risulta “interessante”, dove “Interessante” dipende dal contesto. Un modello può e deve trascurare

i dettagli irrilevanti. L’astrazione è la descrizione di un sistema (o di parte di esso) che ne riporta solo le

caratteristiche rilevanti. Un sistema è modulare se è diviso in parti che hanno una sostanziale autonomia

individuale ed una ridotta interazione con le altre parti: i moduli sono scarsamente connessi e fortemente

coesi (divide et impera).

La scomponibilità modulare consiste nel scomporre un problema in sotto-problemi di minori dimensioni e

quindi più facilmente affrontabili. La componibilità modulare consiste invece nel riaggregare moduli esistenti

per risolvere problemi nuovi avendo così riusabilità. La comprensione modulare consiste nel capire un

modulo osservando solo quello e i "confinanti”. La continuità modulare si ha se un piccolo cambiamento nelle

specifiche comporta cambiamenti in un solo (o pochi) moduli implementando così l’estendibilità. La

protezione modulare si ha se errori in un modulo influenzano solo il modulo stesso (o al massimo si

propagano ai confinanti).

Un modulo deve comunicare con il minor numero possibile di moduli: in un sistema con n moduli il numero

di comunicazioni deve essere vicino a (n - 1) e lontano da n * (n - 1) / 2 (poche comunicazioni). Ogni modulo

deve scambiare il minor numero possibile di informazioni con gli altri moduli (interfacce piccole). Il fatto che

due moduli A e B comunichino deve risultare evidente sia dal codice di A che dal codice di B (interfacce

esplicite). Il modulo deve distinguere tra informazioni pubbliche ed informazioni private (information hiding).

Un sistema complesso ha molteplici “aspetti” che devono essere descritti per rappresentare adeguatamente

il sistema. Difficile comprimere in un unico modello informazioni di natura anche molto diversa. Soluzione:

non un modello, ma più modelli, ciascuno specializzato per fornire un certo tipo di informazioni.

L’attività di sviluppo del software produce svariati semilavorati, ognuno di essi è scritto in un qualche

“linguaggio”:

 Linguaggi di programmazione e affini (C++, Java, HTML)

 Linguaggi naturali (italiano, inglese)

 Linguaggi di descrizione

Le “descrizioni” vengono prodotte in svariate fasi del processo. I linguaggi di descrizione sono linguaggi adatti

a scrivere “descrizioni”. Le loro caratteristiche sono:

 Completezza: il linguaggio deve mettere a disposizione strumenti per descrivere tutti gli aspetti di

interesse

 Accuratezza: si deve poter costruire una descrizione precisa

 Consistenza: il linguaggio deve aiutare a evitare contraddizioni in diverse rappresentazioni nella

stessa descrizione

 Comprensibilità: la descrizione deve essere facilmente comprensibile da parte di chi la deve

interpretare (per modificarla, per utilizzarla come riferimento)

 Formalità: rigore con cui sono definite la sintassi e la semantica del linguaggio

 Stile: quale aspetto del sistema è più facile descrivere utilizzando il linguaggio (comportamento o

proprietà)

I linguaggi di descrizione possono essere:

 Informali: tipicamente linguaggi naturali (italiano, inglese), spesso usati perché sono facilmente

comprensibili dal committente

 Semi-formali: hanno

Dettagli
Publisher
A.A. 2017-2018
24 pagine
2 download
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher tovy97 di informazioni apprese con la frequenza delle lezioni di Progettazione del software e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi dell' Insubria o del prof Morasca Sandro.