Introduzione Le due componenti principali dei programmi



Scaricare 584 b.
Pagina9/9
13.12.2017
Dimensione del file584 b.
1   2   3   4   5   6   7   8   9

// usa la spada

  • }

  • };

  • ...



  • Erediarietà multipla

    • L’ereditarietà multipla permette di derivare una classe da due o più classi base. La sintassi viene estesa per permettere una lista di classi base

    • L’ ereditarietà multipla viene spesso utilizzata per combinare un’interfaccia ed una implementazione, ma è molte volte sintomo di un cattivo disegno



    dynamic_cast

    • dynamic_cast opera una conversione, se è possibile, fra due tipi. Il puntatore ritornato NON è nullo soltanto se il tipo dell’oggetto su cui si opera è quello che ci si aspetta



    Ereditarietà (4)

    • Una classe derivata estende la classe base e ne eredita tutti i metodi e gli attributi



    Esempio: shape



    Cerchi e quadrati



    Cerchio



    Cerchio (2)



    Quadrato



    Codice Applicativo (Client)



    Polimorfismo



    Interfaccia astratta



    Ereditarietà e riuso del codice



    Attenzione alle generalizzazioni...

    • Attenzione: scegliere le relazioni di ereditarietà può essere non banale.

    • Un quadrato è un rettangolo?



    Ereditarietà multipla

    • Una classe può ereditare da più classi



    Strategie di sviluppo di un progetto

    • Requisiti: cosa l’utente vuole

    • Analisi: la visione dell’informatico dei requisiti

    • Disegno: l’aspetto del sistema software

    • Produzione: codifica

    • Testing: debugging e verifica dei requisiti

    • Mantenimento: installazione del prodotto e controllo del funzionamento per il resto della sua vita



    Modello a cascata



    Modello evoluzionario



    Confronto fra i modelli di sviluppo

    • A cascata

    • Processo lineare (si torna al passo precedente solo in caso di problemi)

    • Confinamento delle attività in ogni fase

    • Facile da gestire (gestione delle scadenze)

    • Difficile da modificare

    • Prodotto utilizzabile solo alla fine del processo



    Requisiti

    • Definizione delle richieste da parte dell’utente del programma (o di una sua parte) sul sistema

    • Si parla di programmazione per contratto perchè l’utente richiede solamente la definizione del servizio richiesto NON la metodologia seguita per fornirglielo

      • è possibile delegare parte del lavoro richiesto ad altri
      • il sistema è indipendente da chi è il suo utente
    • INCAPSULAMENTO!



    Analisi

    • Comprensione e razionalizzazione delle richieste dell’utente

    • Costruzione di un modello

      • astrazione (semplificazione delle relazioni)
      • rilevanza (identificazione degli oggetti chiave)
    • Da non trascurare: analisi delle soluzioni esistenti. Può far risparmiare molto tempo!!!



    Disegno



    Disegno (2)

    • Dopo ogni ciclo bisogna analizzare i rischi, la stabilità del disegno e la complessità delle classi

    • Se una classe è troppo complessa conviene dividerla

    • Ad ogni ciclo il numero di modifiche deve diminuire

    • Architetture troppo complesse devono essere modularizzate



    Codifica

    • C’è poco da dire…

    • Non sopravvalutate questa fase:



    Testing

    • Debugging: è ovvio… il codice non deve dare errori.

    • Use cases: specificano il comportamento del sistema in una regione.

    • Scenarios: sono esempi concreti di use cases. Per definizione se tutti gli scenari sono soddisfatti correttamente il test è positivo.



    Metodi di sviluppo del software

    • Un metodo comprende:

    • Una notazione

      • mezzo comune per esprimere strategie e decisioni
    • Un processo

      • specifica come deve avvenire lo sviluppo


    Metodi Object Oriented

      • Booch Method by Grady Booch
      • OMT by Jim Rumbaugh
      • Objectory (Use Cases) by Ivar Jacobson
      • CRC by R.Wirfs-Brock
    • Di recente introduzione: UML

      • uno standard OMG (Object Management Group), dal novembre 1997


    UML per l’analisi e il disegno

    • Class Diagrams: aspetto statico del sistema. Classi con attributi e metodi e relazioni tra di esse.

    • Sequence e collaboration digrams: comportamento dinamico del sistema. Sequenza dei messaggi scambiati fra gli oggetti.

    • Use case diagrams: illustra gli use cases, le relazioni fra di essi e gli attori che vi partecipano.

    • State diagrams: descrive gli stati in cui ogni oggetto si può trovare e le modalità con cui passa da uno stato all’altro



    Concetti delle classi rivisitati

    • Relazioni tra oggetti

    • Decomposizione funzionale all’interno di una classe

      • responsabilità dei metodi
    • Decomposizione funzionale tra più classi

      • responsabilità delle classi


    Rappresentazione delle classi



    Rappresentazione di una classe C++ in UML



    Attributi e metodi



    Principali relazioni fra classi

    • associazione

    • aggregazione by reference

      • (il composito non vive senza il componente)
    • aggregazione by value

      • (aggregazione fisica: esistenza contemporanea)
    • dipendenza

    • generalizzazione (inheritance)



    Aggregazione (contenimento)



    Cardinalità e direzionalità



    Dipendenza



    Generalizzazione (ereditarietà)



    Class Diagram di “Shape”



    Class Diagram



    Class Diagram



    Object Sequence Diagram



    Object Collaboration Diagram



    CRC Classi, Responsabilità, Collaborazioni



    Assegnare Responsabilità

    • Identificare i protagonisti

    • Analizzare il ruolo dei vari oggetti

    • Concentrarsi sul comportamento non la rappresentazione

    • Cercare Oggetti con proprietà comuni:

    • Definire le interfacce (le operazioni che soddisfano le responsabilità)

    • Una corretta assegnazione delle responsabilità è la chiave di una buona modularità e riuso



    Collaborazione tra classi

    • Le responsabilità vanno suddivise tra i vari oggetti del sistema

    • non deve esistere un controllo centralizzato

    • Un oggetto deve compiere le proprie responsabilità e delegare ad altri operazioni specifiche

      • Legge di Demeter: non usate oggetti lontani:
      • Invece di: traiettoria.listapunti().aggiungi(Punto);
      • usare: traiettoria.aggiungiPunto(Punto);


    Identificare Relazioni

    • Cercare collaborazioni

    • Cercare aggregazioni

    • Cercare generalizazioni

    • Come un client conosce il suo service provider?



    Relazioni

    • Logiche

    • Generalizazione: Is-a

    • Aggregazione: Has

    • Dipendenza: Knows



    Avere o essere?

    • Uno dei punti critici è distinguere se il rapporto fra due oggetti è del tipo avere o essere:

      • Un LorentzVector è un Vector o ha un Vector?
      • Una Traccia è un vector o ha un vector?
      • Un Rivelatore è una Superficie o ha una superficie?
    • Per risolvere il problema bisogna guardare a cosa fanno!



    Principio di Liskov

    • Gli oggetti figli possono essere usati ovunque l’oggetto genitore è richiesto



    Composizione by value o by refrence

    • In C++ la scelta fra aggregazione by value o by refrence può seguire questo schema:

      • Tipi semplici (int, float, …): by value
      • Parte dello stato dell’oggetto: by value
      • Oggetti condivisi: by reference
      • Assegnati a run time: by reference
    • Oggetti condivisi by reference: attenzione a chi ha la responsabilità di crearli e cancellarli! (1 new  1 delete!)



    Approccio Outside-in

    • Il corretto approccio è quello di guardare il sistema dall’esterno.

    • Identificare prima di tutto gli oggetti che interagiscono con l’utente esterno e i messaggi a cui devono saper rispondere (think client!)

    • In seguito identificare gli oggetti che forniscono servizi a questi ultimi e così via

    • Gli algoritmi vengono per ultimi!!!



    CRC Workshop

    • Metodo per la definizione si una architettura bilanciata

    • Ogni partecipante svolge il ruolo di una classe.

      • Individuazione delle classi
      • Contrattazione delle responsabilità
      • Definizione delle collaborazioni
      • Difesa dal tentativo di assegnazione di responsabilità contrarie alla natura della classe


    Regole per il CRC workshop

    • Tentate di rifuutare le responsabilità

      • Dovrei? (Non sono io che lo devo fare!)
      • Potrei? (Non ho i mezzi, o lo stato per farlo!)
    • Cercate di fare poco lavoro

      • Se avete dovuto accettare una responsabilità cercate di far fare il lavoro a qualcun’altro
    • Potenziate i collaboratori, non interferite



    Design Patterns

    • Sono elementi di software OO riutilizzabile

    • Piccoli insiemi di classi che collaborano implementando dei comportamenti tipici

      • Creational patterns
      • Structural patterns
      • Behavioral patterns
    • I principali sono raccolti in un libro:

    • E. Gamma et al., Design Patterns



    Factory



    Proxy



    Composite



    Gruppo di Shapes



    Codice del modello composite



    Codice del modello composite



    Strategy



    Observer



    Appendice: strighe C-style

    • Le variabili carattere sono gestite come array di char (un char contiene un solo carattere)

      • accesso agli elementi tramite la sintassi degli array
      • carattere nullo usato come terminatore (‘\0’)
    • Funzoni di libreria per la gestione dei char* :

      • #include per utilizzarle
      • int strlen(const char*); lunghezza della stringa
      • int strcmp(const char*, const char*); confronto di due stringhe
      • char* strcpy(char*, const char*); copia la seconda stringa nella prima


    Appendice: la classe string

    • Per semplificare la gestione delle stringhe è stata creata la classe string

      • #include per usarla
      • Definiti gli operatori standard:
        • = per l’assegnazione
        • + e += per la concatenazione
        • == e tutti gli altri operatori relazionali per il confronto
        • [] per l’accesso agli elementi
      • Disponibile sintassi simile a quella dei contenitori STL:
        • iteratori: string::iterator e string::const_iterator
        • funzioni begin() , end() , size() , ecc...
      • Interoperabilità con char*:
        • char* c=“Pippo”; string s=c;
        • char* c1 = s.c_str(); s += c;


    Confronto stringhe C-style e string

    • #include

    • #include

    • int main(){

    • int err=0;int big=1000000;

    • char* c1=“LLLong string”;

    • for(int i=0;i

    • int len=strlen(c1);

    • char* c2=new char[len+1];

    • strcp(c2,c1);

    • if(strcmp(c2,c1))err++;

    • delete[] c2;

    • }

    • cout<

    • return 0;

    • }



    Appendice:operazioni di I/O

    • Si utilizza la libreria iostream

      • Gli operatori di stream >> e << dirigono il flusso da/per le unità desiderate:
        • cout : standard output. Si sono già visti molti esempi
        • cerr : standard error. Si usa come cout
        • cin : standard input (normalmente la tastiera)


    Overloading degli operatori di I/O

    • Gli operatori << e >> possono essere ridefiniti per consentire operazioni del tipo:

        • Vector2D v(1,2);
        • cout << “Il vettore v vale “ << v << endl;
    • Si utilizza una funzione friend:

      • class Vector2D {
      • friend ostream& operator <<(ostream& os, const Vector2D v);
      • [...]
      • }
      • ostream& operator <<(ostream& os, const Vector2D v){ os << “(“ << v.x() << “,” << v.y() << “)”;}
    • Si ottiene:

        • Il vettore v vale (1,2)


    Appendice: I/O con files

    • E’ possibile definire altre unità di I/O

      • Si utilizza la libreria fstream (include iostream)
      • I files di input sono dichiarati ifstream
      • I files di output sono dichiarati ofstream
      • I files di input/output sono dichiarati fstream
      • Costruttore con argomento const char* (nome file)


    Appendice: I/O in memoria

    • E’ possibile definire unità di I/O in memoria (non legate a files)

      • Si utilizza la libreria sstream (include iostream)
      • Le unità di input sono dichiarati istringstream
      • Le unità di output sono dichiarati ostringstream
      • Le unità di input/output sono dichiarati stringstream
      • I costruttori non hanno argomento
      • Il metodo str() applicato ad un oggetto di questo tipo ritorna la stringa (string) contenuta nell’unità:
        • ostringstream messaggio;
        • messaggio << “Ciao!” << endl;
        • string s=messaggio.str();


    Appendice: Manipolatori di I/O

    • Modificano il comportamento di una stream.



    Appendice: Manipolatori di I/O (2)

    • I seguenti manipolatori richiedono:

      • #include


    Esempio di I/O con manipolatori

    • Non tutti i compilatori supportano tutti i manipolatori!!!



    Per saperne di più

    • sugli elementi di base del linguaggio C++

      • **** Lippman, Lajoye, The C++ Primer, 3rd Edition - Addison Wesley
      • *** Pohl, Object-Oriented Programming Using C++, 2nd Edition - Addison Wesley
      • *** Stroustrup, The C++ Programming Language, 3rd Edition - Addison Wesley
    • su trucchi e tranelli in C++

      • **** Myers, Effective C++, Addison Wesley
      • **** Myers, More Effective C++, Addison Wesley
      • *** Coplien, Advanced C++, Addison Wesley
    • su STL

      • **** Glass, Schuchert, The STL
        ,
        Prentice Hall
      • *** Ammeraal, Wiley, STL for C++ Programmers -
      • ** Musser, Saini, STL Tutorial and Reference Guide, Addison Wesley


    Per saperne di più (2)

    • su OO A&D

      • *** Booch, Object-Oriented Analysis and Design with Applications, Benjamin/Cummings
      • *** Booch, Object Solutions, Addison Wesley
    • su UML

    • sui Design Patterns

      • *** Gamma, Helm, Johnson, Vlissides, Design Patterns, Addison Wesley



    1   2   3   4   5   6   7   8   9


    ©astratto.info 2017
    invia messaggio

        Pagina principale