1.39k likes | 1.57k Views
Il paradigma di sviluppo software orientato agli oggetti. CEFRIEL Via Fucini, 2 - 20133 Milano Tel. 02.23954.1 Fax 02.23954.254 E-mail: lavazza@cefriel.it. Sommario. Introduzione Verso il paradigma OO Concetti base Concetti avanzati Metodologie di sviluppo e ciclo di vita OO
E N D
Il paradigma di sviluppo software orientato agli oggetti CEFRIEL Via Fucini, 2 - 20133 Milano Tel. 02.23954.1 Fax 02.23954.254 E-mail: lavazza@cefriel.it
Sommario • Introduzione • Verso il paradigma OO • Concetti base • Concetti avanzati • Metodologie di sviluppo e ciclo di vita OO • Vantaggi (e problemi) dell'approccio object-oriented • Un esempio
1. Introduzione Un nuovo paradigma: perché?
L'evoluzione dell'informatica • La costruzione di programmi passa da una prima fase artistica, ad una artigianale, per arrivare, oggi, ad una concezione industriale dello sviluppo di software • L’ accento è posto su: • qualità • produttività • riusabilità
I fallimenti • Sfondamento del budget • Deadlines mancate • Errori nel progetto dell'applicazione che non viene poi completata o viene (parzialmente) riscritta • Impossibilità di soddisfare la richiesta di applicazioni informatiche (domanda nascosta ed inevasa -> backlog) • Impossibilità di far evolvere una applicazione esistente di pari passo con le esigenze dell'utente
Il software: un prodotto atipico • Miti e realtà • F. Brooks (padre del OS/360) • "Tutti i programmatori sono ottimisti" • "The mythical man-month" • "Aggiungere risorse ad un progetto che è in ritardo ne ritarda ulteriormente la conclusione" Mesi (m) Mesi (m) S=nm Numero di risorse (n) Numero di risorse (n)
Caratteristiche del software • Il software è contraddistinto da 4 peculiarità (Brooks): • Complessità • Labilità • Modificabilità • Invisibilità
Complessità • Difficile identificare tutti gli stati che caratterizzano un programma e quindi il suo comportamento • Difficile perciò trasmettere correttamentre ad altre persone (o applicazioni) informazioni descrittive del programma • La complessità delle strutture dati e dei flussi di controllo rende complesso il processo di manutenzione
Labilità • Non esistono leggi unificanti come nella fisica • Il programmatore non ha reali vincoli su come deve essere utilizzato un linguaggio di programmazione • Uno stesso problema può essere risolto da molti programmi
Modificabilità • Il software è continuamente modificato per • correggere errori e, soprattutto • fornire nuove funzionalità • Il software è dal punto di vista operativo assai facilmente modificabile e riproducibile
Invisibilità • Mentre per altri manufatti (es. turbine, motori, ...) esistono validi mezzi di rappresentazione (schemi, diagrammi di prestazioni e consumi, ...), il software non dispone ancora di tecniche efficaci per descriverne la struttura, le funzionalità e le prestazioni
Qualità del prodotto "software" • Qualità interne VS qualità esterne • Le qualità interne implementano le qualità esterne
Fattori di qualità (1) • Affidabilità • Le funzionalità offerte corrispondono ai requisiti • Correttezza • rispetto delle specifiche • Robustezza • il programma riesce a funzionare anche in condizioni non specificate nei requisiti • sicurezza • innocuità
Fattori di qualità (2) • Manutenibilità • facilità ed economicità del processo di manutenzione • (60-70% dei costi complessivi di una applicazione) • manutenzione correttiva (20%) • manutenzione adattativa (20%) • manutenzione perfettiva (60%) • Riusabilità • l’applicazione non viene sviluppata ex-novo ma impiegando componenti esistenti che vengono assemblati • Estendibilità • il programma può essere facilmente adattato a nuove esigenze
Fattori di qualità (3) • Interoperabilità • il programma può essere usato in congiunzione con altri pacchetti • Efficienza • Portabilità • Verificabilità • Semplicità d'uso ...
Modularità (1) • Divide et impera • Un sistema è modulare se è diviso in parti che hanno un buon grado di omogeneità interna, una sostanziale autonomia individuale ed una ridotta interazione con le altre parti (i moduli sono fortemente coesi e scarsamente connessi)
Modularità (2) typedef ... type1; init (type1 *par) { par = ...;} proc1(type1 par) {....} typedef ... type2; init (type2 *par) { par = ...;} proc2(type2 par) {....} int var; main() { .... var = 23; proc(); if (var ==23) .... } void proc() { var = 24; .....} main() { type1 a; type2 b; init(a); init(b); ......} Used by
Cinque criteri di modularità (1) • Scomponibilità modulare • scomporre un problema in sottoproblemi di minori dimensioni e quindi più facilmente affrontabili • ES: top-down design • Componibilità modulare • ri-aggregare moduli esistenti per risolvere problemi nuovi • riusabilità • ES: librerie, Unix shell • la progettazione top-down produce, in generale, moduli non riusabili
Cinque criteri di modularità (2) • Comprensione modulare • capire un modulo osservando solo il modulo in questione e quelli "confinanti" • manutenibilità • Continuità modulare • un piccolo cambiamento nelle specifiche comporta cambiamenti in un solo (o pochi) moduli • estendibilità • ES: uso di costanti simboliche • Protezione modulare • errori a run-time in un modulo influenzano solo il modulo stesso (o al massimo si propagano ai confinanti)
Come ottenere la modularità (1) • Unità linguistiche modulari • il linguaggio di programmazione deve avere il concetto di "modulo" • relazioni con • scomponibilità, componibilità, protezione • Poche interfacce • ciascun modulo deve comunicare con il minor numero possibile di altri moduli • in un sistema composto da n moduli il numero delle interazioni tra i moduli deve essere quanto più possibile vicino a (n-1) e lontano da n(n-1)/2 • relazioni con • protezione, continuità
Come ottenere la modularità (2) • Interfacce piccole • ogni modulo deve scambiare il minor numero possibile di informazioni con gli altri moduli • relazioni con • protezione • continuità • Interfacce esplicite • il fatto che due moduli A e B comunichino deve risultare evidente sia dal codice di A che dal codice di B • relazioni con • scomponibilità • componibilità • continuità • comprensione
Come ottenere la modularità (3) • Information hiding • il modulo deve distinguere tra informazioni pubbliche ed informazioni private • relazioni con • continuità
Il primo passo verso la OOP • Tipi di dati astratti • struttura dati descritta da un punto di vista "esterno", dei servizi offerti e delle proprietà dei servizi • ES: moduli di ADA • Genericità • la possibilità di usare la stessa implementazione per un certo insieme di tipi di dati astratti, definiti a meno di un parametro • Overloading • l'uso degli stessi nomi di funzione per funzioni uguali nella logica, ma diverse nell'implementazione
I tipi tradizionali (1) • Tipi base (integer, boolean, real, character, ecc.) • Costruttori (array, record, ...) • ortogonalità tra costruttori e tipi • Operazioni predefinite • per i tipi base (+, - , *, /, ||, &&, %, ....) • overloading • per i costruttori (a.y, b[i], ecc.)
I tipi tradizionali (2) • Possono realizzare diversi concetti: • Assembler (C) • Data type (Pascal) • . . . . .
I tipi tradizionali (3) int v[10]; int j; unsigned int i; j= -1; i = j; j == -1, i == 4294967295 printf(" j = %d, i = %u\n", j, i); i = v[10]; j == -1, i == 4294967295 printf(" j = %d, i = %u\n", j, i);
Funzioni definite dall'utente • Troppo dipendenti da come il tipo é costruito • Presuppongono la conoscenza dell'implementazione dei tipi dei parametri no information hiding
Data Types • Data type: una collezione di oggetti e un insieme di operazioni che agiscono su questi oggetti. • Gli "oggetti" in questa accezione sono in realtà i valori (o le combinazioni di valori, per oggetti complessi) permessi dal tipo.
Abstract Data Types • ADT: data type di cui si offre una visione astratta • L'astrazione viene ottenuta attraverso una interfaccia • Per usare l'ADT basta la conoscenza dell'interfaccia • La definizione dell'ADT é completata dall'implementazione dei dati e delle operazioni, che é nascosta agli utenti (information hiding) • L'ADT rappresenta sia i dati che le operazioni (incapsulamento)
Abstract Data TypesSpecifica di un ADT • Nome dell'ADT • Lista degli ADT utilizzati • Lista delle operazioni definite (costruttrici ed utilizzatrici). Per ogni operazione: • segnatura • descrizione del significato dell'operazione • a parole • con qualche formalismo
structure Natural: use: Boolean sort: Nat constants: Zero, MAX_INT var: x,y: Nat constructors: Nat Succ(Nat) operations: Boolean Equal(Nat, Nat) Nat Inc(Nat) Nat Add(Nat, Nat) axioms: Equal(Zero, Zero) = True; Equal(Zero, Succ(x)) = False; Equal(Succ(x), Succ(y)) = Equal(x, y); Inc(MAX_INT) = MAX_INT Inc(x) = Succ(x) Add(x, Zero) = x Add(x, Succ(y)) = if (Equal(x,MAX_INT) or (Equal(Succ(y),MAX_INT)) MAX_INT else Succ(Add(x,y)) end Natural Abstract Data Types un esempio
Abstract Data Typesun esempio di estensione structure Nat2 extends Nat: sort: Nat2 var: x,y: Nat2 operations: Nat2 Sub(Nat2, Nat2) axioms Sub(x, Zero) = x Sub(Succ(x), Succ(y)) = Sub(x, y) Sub(Zero, x) = Zero end Nat2
structure Set[Item]: use: Boolean, Item sort: Set constants: EmptySet var: x,y: Set; e, f: Item; constructors: Set Insert(Set, Item); // inserisce l'elemento creando eventuali ripetizioni operations: Boolean Equal(Set, Set); Boolean IsIn(Set,Item); Set Remove(Set, Item); Set Union(Set, Set); axioms: // validi per set senza ripetizioni IsIn(EmptySet,e) = False; IsIn(Insert(x, e), e) = True; not Equal(e, f) => IsIn(Insert(x, e), f) = IsIn(x, f); Equal(EmptySet, EmptySet) = True; Equal(EmptySet, Insert(x, e)) = False; Equal(Insert(x, e), Insert(y, e)) = Equal(x, y); Equal(x, y) = Equal(y, x); Remove(EmptySet, e) = EmptySet; Remove(Insert(x, e), e) = x; Union(EmptySet, y) = y; Union(x, y) = Union(y, x); Union(Insert(x, e), y) =Insert(Union(x,Remove(y,e)),e); ....... end Set Abstract Data Typesun altro esempio
Abstract Data Types vsAbstract Data Objects • Il concetto di Abstract Data Object é simile al concetto di ADT, salvo che si riferisce ad un singolo oggetto, non ulteriormente istanziabile. • E` più facilmente implementabile nei linguaggi di programmazione senza supporto specifico agli ADT (ad es. variabili static in C).
Abstract Data Types in C? • Esistono linguaggi (Modula2, Ada, CLU) che supportano esplicitamente il concetto di ADT. • E` possibile implementare ADT (o qualcosa di simile) in linguaggi che non forniscono costrutti appositi, per esempio, in C ?
Abstract Data Types in C! • Si consideri il seguente file "stack.h" • implementa piuttosto bene l'interfaccia di un ADT. typedef struct intstack *istackp; /* puntatore a pila di interi */ istackp create_intstack(); /* crea una nuova pila */ void push(istackp s, int e); int pop(istackp s); int top(istackp s); void printstack(istackp s); int isempty(istackp s); • Si noti che il dettaglio di come é realizzata la pila non traspare (starà in stack.c)
Abstract Data Types: verso l'OO • Gli ADT introducono diversi concetti del paradigma object-oriented: • astrazione (separazione interfaccia / implementazione) • estendibilità • genericità • instanziabilità
I concetti base del paradigmaObject-Oriented • classi • oggetti • ereditarietà • polimorfismo • dynamic binding
Classe • Definizione • un modulo che definisce un nuovo TIPO di dato astratto • è un costrutto per implementare un tipo • Una classe definisce un insieme di possibili oggetti • Costituita da un insieme di proprietà (SLOT) e dalle procedure che operano su tali proprietà (METODI) • contenuti privati • slot e metodi che possono essere acceduti solo dai metodi dell'oggetto • contenuti pubblici • slot e metodi che possono essere acceduti da qualsiasi oggetto
Classe: un esempio (1) class date { int month, day, year; public: void set(int, int, int); void get(int*, int*, int*); void next(); void print(); }; void date::print() { ... } main() { date today; ... today.day++; ERROR }
Classe: un esempio (2)costruttori class date { int month, day, year; public: date(int, int, int); // day month year date(char*); // date in string representation date(int); // day, today's month and year date(); // default date ..... }; date today(4); date july4("July 4, 1983"); date now; //inizializzazione di default
Oggetto • Definizione • istanza di una classe (corrisponde al concetto di variabile per i tipi dei linguaggi tradizionali) • Modellano le entità proprie del dominio applicativo • Ogni oggetto ha associato proprietà e procedure • Un oggetto incapsula: • stato = valore di attributi • comportamento = metodi • Un metodo si invoca mandando un messaggio all'oggetto
Oggetti complessi • Sono oggetti costruiti a partire da oggetti più semplici. • Deve essere fornito un insieme minimo di costruttori: struct, array, ecc. • I costruttori devono essere ortogonali rispetto alla struttura degli oggetti cui si applicano. • Occorre fornire operatori per gestire gli oggetti complessi. • Questo vuol dire che in generale un'operazione effettuata su un oggetto complesso generico (cioé avente qualunque struttura) deve propagare transitivamente i propri effetti ai componenti dell'oggetto operando. • Esempio: "deep" e "shallow" copy.
Identità degli oggetti • Un oggetto esiste indipendentemente dal suo valore. • Concetto noto e diffuso nei linguaggi di programmazione imperativi, dove l'identità è data dal nome della variabile o dalla locazione in memoria. • Esistono due relazioni di equivalenza sugli oggetti: • identità (due oggetti sono in realtà il medesimo oggetto) • uguaglianza (due oggetti hanno lo stesso valore) • Se l'oggetto è complesso l'uguaglianza può essa stessa essere "deep" o "shallow".
Identità degli oggetti - condivisione • Grazie alla object identity, due oggetti possono condividere un componente. • Graficamente, un generico oggetto è rappresentabile come un grafo.
Identità degli oggetti - condivisione • Esempio: una persona ha un nome, un età e un insieme di figli. • Carlo e Maria hanno entrambi un figlio di 15 anni di nome Luca. Sono possibili due situazioni: • Luca é il figlio di Carlo e Maria • Ci sono due persone di nome Luca di 15 anni, uno figlio di Carlo e uno di Maria • Un sistema basato sull'identità rappresenta in modo naturale entrambe le situazioni: Carlo Maria Carlo Maria Luca Luca Luca
Identità degli oggettiAggiornamento di oggetti condivisi • Quando un oggetto condiviso viene aggiornato tutti gli oggetti cui appartiene automaticamente ed immediatamente vedono il cambiamento. • Es: carlo->figlio->anni += 1 • Questo meccanismo è al tempo stesso potente e pericoloso (side-effects). Carlo Maria Carlo Maria 16 Luca 15 Luca
Tipi e classi • Esistono due grandi categorie di sistemi object-oriented: • Sistemi che supportano solo il concetto di classe (Smalltalk, Gemstone, ecc.) • Sistemi che supportano anche il concetto di tipo (C++, Eiffel, O2, ecc.)
Tipi • Il concetto di tipo é legato al concetto di ADT e al concetto di tipo come dichiarazione statica della natura degli oggetti manipolati da un programma allo scopo di permettere la verifica di alcune proprietà di correttezza dei programmi a compile-time.