venerdì, marzo 31, 2006

Ingegneria del software: 7 aprile 2005

Activity Diagram
Gli stati vengono chiamati attività

Le transizioni sono di solito etichettate con eventi (tutte tipo "quando finisce l'attività)
Le azioni di solito sono nelle attività
Le attività possono essere sia interne che esterne al sistema
Quando usare gli activity diagram:

  • Il flusso interno di un metodo (con eventuali indicazioni di (pseudo) concorrenza)
  • Il flusso di uno use-case (alternativo (o ortogonale) al sequence diagram)
  • La logica all'interno di un business process (caso principe)

Barre di sincronizzazione (fork/join):




Va specificato il punto finale dell'iterazione (punto cerchiato alla fine del grafico qui sopra)
Decisioni:


Piccolo rombo con due uscite etichettate con delle guardie (condizioni)
Non é un automatiscmo derivato da quanto successo prima, ma una vera e propria scelta (tipo scelta dell'utente)

Due attività possono essere connesse da un oggetto (un'attività modifica lo stato dell'oggetto che a sua volta fa partire un'altra attività)

Lo stesso oggetto può comparire può volte (tante quante sono i suoi stati)

Swim lane (corsie della piscina)
Si possono suddividere le attività per assegnargli un responsabile Da notare che in questo grafico possono comparire anche azioni esterne (il bibliotecario rimette il libro restituito sullo scaffale)
Assomiglia alle reti di Petri

User stories, scenari
Approccio con il cliente (cliente non tecnico)
Descrizione di come é lo scenario in pratica (cosa ci si aspetta dal programma)
Atomiche, semplici: descrivono una funzionalità alla volta
Il diagramma use-case descrive le user-stories
L'utente descrive "il sistema" l'architetto scinderà poi in varie parti (ed eventualmente modificherà/integrerà)
E' una vista sulla funzionalità, non sugli oggetti.
Attori: entità esterna al sistema, fonte o destinatario di informazioni (interagisce con il sistema). simboleggia un ruolo, più che una persona
In ogni use case ci deve essere almeno un attore (e vice versa). L'attore primario é il responsabile dell'avvio dello use-case
Esistono delle relazioni fra use-cases:
include (per esempio per fattorizzare funzionalità comuni e riutilizzarle)
extend (viene creato uno use case "virtuale" con dei punti devono essere specializzati (vengono marcati, ma non specificati, sarà lo use case che specializzerà a specificarli)
generalizzazione Uno use case eredita da un altro (scomparsa in UML 2). Generalizzazione dei ruoli: un ruolo potrebbe essere l'override di un altro ruolo.

Package diagram
Non é un vero diagramma
Mette insieme altri diagrammi
Si può mettere insieme (raggruppamento logico) class-diagram e use cases

Component Diagram
Suddivisione del sistema in moduli: File, librerie, eseguibili, tabelle, documenti
In genere un component é l'unità minima aggiornabile (ad esempio una DLL)


Necessario specificare eventuali interfacce implementate! Component2 si appoggia a Component1 per l'interfaccia indicata dalla freccia.

Deployment diagram
Permette di specificare la dislocazione fisica delle istanze dei componenti
Permette di specificare:
Nodi del sistema (le macchine fisiche)
Collegamenti tra i nodi (RMI, HTTP, ecc.)
Disposizione delle istanze dei componenti all'interno dei nodi e loro relazioni
Per evitare che diventi immenso si possono tagliere le informazioni sulle interfacce (già specificate nel component diagram)

martedì, marzo 28, 2006

Ingegneria del software: 4 aprile 2005

UML, DIAGRAMMI DINAMICI
Use Cases (agli effetti esterni)
Interaction Diagram (Sequence e Collaboration)
State Diagram (Dinamiche interne agli oggetti)
Activity Diagram (Possono essere usati per rappresentare flussi di decisioni)

Object Diagram
Ovvero come avvengono le interazioni tra gli oggetti
Ad esempio: oggetti di classe persona: studente e professore legati da esame sarebbero 2 quadrati collegati da una riga (e non 1 rettangolo con freccia ricorsiva)
E’ il diagramma delle classi visto a runtime

Sequence Diagram
Esprimono la dimensione temporale dell’interazione tra gli oggetti.
Sono orientati ai messaggi
Elementi: oggetti anonimi (posso non nominare alcuni oggetti che non devo richiamare), attori (entità esterne che devono interagire con il sistema stesso).
Lifeline: ovvero la linea di vita di ciascun elemento:

Due versioni:
Creare tutti i box all'inizio (1) o crearli quando viene creato effettivamente l'oggetto (2). La vita dell'oggetto é indicata da un box piccolo.


Messaggi come "istanze di associazione" (le classi devono avere un'associazione)
Sia sincroni (chiamate di funzioni) che asincroni.
Chiamata con un messaggio sincrono: freccia orizzontale (cfr 1.1), ritorno freccia tratteggiata aperta (sempre cfr 1.1)
Messaggio asincrono: mezza freccia (cfr 1.2)



Attributi dei messaggi
Numero gerarchico identificativo del messaggio (1, 1.1, 1.1.1, 1.2, 2, 2.1, 2.2)
Nome del messaggio
Condizione [tra quadre]
Iterazione *[tra quadre, preceduto da un asterisco] (condizione di ripetizione del messaggio: continua finché é vera)
Es.:
1 Fai quello [i<6] style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/6463/2288/400/Messaggi2.jpg" border="0"> Alternative: Collaboration Diagram (che é una vista simile, ma più astratta), Activity Diagram (più orientato alla sincronizzazione tra attività parallele), State Diagram (associato ad una singola classe: come evolve agli stimoli che riceve dall'esterno (anche esterno del progetto))

Automi a stati finiti
E' una n-pla: <S,I,U, d, t, s0>
Dove:
S = Insieme finito non vuoto degli stati
I = Insieme finito dei possibili ingressi
U = Insieme finito delle possibili uscite
d = (delta) Funzione di transizione (indica i possibili passaggi da uno stato ad un altro in base ad un input € I) . Può essere una funzione parziale (non definita su tutto SxI): non é detto che si possa passare da ogni stato ad un altro. Può non essere una funzione vera a propria (a partire da uno stato con lo stesso input può portare a più stati, in tal caso si ha un automa NON deterministico).
t = La funzione di uscita (definisce le uscite). t: SxI -> U. Automi di Moore: le uscite dipendono solo dallo stato.
s0 = Lo stato iniziale (s0 € S)

State Diagram
Viene associato alla classe degli oggetti (comportamenti comuni a tutti gli oggetti di quella classe) Non viene fatto per tutte le classi
Vengono segnate le chiamate ad altri oggetti/classi.
Non vengono rappresentati tutti i metodi, ma solo quelli che modificano lo stato dell'oggetto. Es. (copie di libro):

Sarebbe bene segnalare le chiamate che portato uno stato in errore (freccia e stato con scritto "eccezione").
Si possono annotare anche le chiamate a metodi di altre classi/oggetti
Posso anche vedere (a livello di libro e non più di copie). Questo sarebbe un automa non deterministico se non avessi impostato delle guardie (indicazioni di quando un evento porta ad un ramo o ad un altro).
Esistono anche i Time-event: dopo un certo tempo se non sono avvenuti altri eventi avviene un altro evento. Oppure nel caso in cui l'oggetto subisca un evento (ad esempio il numero di copie diventa 0, indipendentemente dal fatto che le copie siano prestate, smarrite, distrutte).
Posso definire un superstato: uno stato formato da altri stati
In un superstato posso avere anche più di una macchina che viene eseguita contemporaneamente... In tal caso si ha che:
in caso di sospensione del superstato viene memorizzato il singolo stato di ogni macchina e poi ripreso
Il superstato termina quando terminano tutte le macchine contenute (si usa una barra di sincronizzazione.

Ingegneria del software: 31 marzo

Pattern
Pattern State
Creare una classe per gestire gli stati di un oggetto
Sostanzialmente: se c’è un oggetto che può avere vari stati deve avere una proprietà che indice lo stato che sia di un tipo astratto che viene poi ereditato da varie “classi stato”.
Una classe Context (contesto dell’oggetto) che implementa l’interfaccia State (una property per leggere/impostare lo stato). Bisogna decidere se è ConcreteState o Context ad impostare lo stato successivo.
La funzione sampleOperation viene ridefinita nei ConcreteState, tale funzione potrebbe ricevere il Context chiamante

Pattern LightWeight
Pattern per i passaggi si stato (da focus al passaggio di stato e non lo stato in se)

Pattern Composite
Gestire strutture ad albero di oggetti.
Il programma mette insieme oggetti complessi da oggetti semplici. Voglio che l’utente possa mettere insieme gli oggetti come vuole e li tratti tutti alla stessa maniera: sia che si tratti di un oggetto semplice, sia un oggetto aggregato m(di primo, secondo o ennesimo livello).
Nell’esempio: tutti gli oggetti sono picture e si sanno autodisegnare
Alternative: usare un interfaccia per il livello comune,
Fare gestire la composizione sull’oggetto composito (costruttore?) o sull’oggetto componente (ridefinire operatore?)
Property IsComposite: indica se un oggetto è composito
Altro esempio: soluzione di espressioni.

Pattern decorator (wrapper)
Può essere visto come un caso particolare di Composite:
Esempio: textbox può avere delle scrollbar (verticale, orizzontale, entrambe) o bordo (singolo, doppio, ecc.)…
Definisco la classe base VisualComponent da cui deriveranno tutte: TextView e Decorator. Decorator ha una proprietà component di tipo VisualComponent. Da Decorator deriveranno poi ScrollDecorator e BorderDecorator. La logica è di mettere un componente dentro l’altro (con nel punto più interno la TextBox e in quelli successivi dei decoratori).

Pattern Command
Componibile, separation
- Cos’è una callback (puntatore a funzione/evento: notifica le funzionalità da invocare in seguito ad un certo evento.
Sono l’equivalente OO delle callback con puntatori a funzione.
In sostanza: il client deve sollevare un evento. Le funzioni collegate all’evento devono essere “wrappate” in oggetti di tipo Command (astratto, interfaccia), Client contiene un oggetto Reciver (collezione di Command?). La classe astratta Command viene specializzata in differenti ConcreteCommand. I Command hanno un oggetto Invoker che avvia il metodo Execute (settando eventuali parametri prima)
Una possibile composizione di pattern: implementare Pattern Composite su Command (Multi Command).

Pattern FactoryMethod
Sopperisce al fatto che un costruttore possa creare sempre e solo lo stesso tipo di oggetti: può darsi che quale sia l’oggetto che servirà dipenderà dallo stato e non sono in grado di dirlo a priori.
In sostanza si definisce un metodo statico che fungerà da costruttore. Tale metodo contiene l’intelligenza per capire quale oggetto creare.
Lo schema si riferisce ad un’applicazione MDI.
Possibile estensione: FactoryMethod in Together

giovedì, marzo 09, 2006

Ingegneria del software: 21 marzo 2005

Modello dei dati
Come definire le classi per risolvere un certo problema.
Non é un procedimento completamente standardizzato, ma creativo.
Possiamo dividere in 3 tipi di classi:
Entity: definiscono il dominio applicativo (corrispondono ai dati che dobbiamo gestire)
Control: Definiscono il comportamento del nostro processo: la logica applicativa.
Boundary: Classi che gestiscono l'interfaccia con l'utente

Lo sviluppo dovrebbe partire dagli Entity Method per scegliere la disposizione in classi:
Estrazione dei nomi
Consiste nel cercare nelle specifiche (in linguaggio naturale) tutti i nomi, poi si sfoltisce
Si consiglia di usare l'inglese
A volte ci sono delle ridondanze che potrebbero essere generalizzazioni
Nomi generici: vanno chiariti meglio (tipo oggetto)
Nomi di eventi e operazioni facilmente non dovrebbero essere classi
Metalinguaggio (system, rules): ovviamente non va considerato come classe
Esterno al sistema: Nomi di oggetti che non interessano il programma (ad esempio giorno)
Attributi: Diventeranno attributi delle classi, non classi
Segue interessante esempio di analisi e studio di una gerarchia di classi (10:00 - 32:00 circa)
Si possono mettere dei constraint sulle relazioni UML: ad esempio: XOR, ecc.

Approccio per tipi di classi comuni
Si pensa ai tipi di oggetti:
    1. Concetti
    2. Cose reali
    3. Ruoli (oggetti esterni che interagiscono con il sistema, anche un'altro sistema lo é (ma anche una persona può coprire un ruolo)) e Persone (interessano per esempio per un'autenticazione)
    4. Eventi
    5. Organizzazioni
    6. Posti

    Collaboration Responsibility Card (CRC)
    Inventate per XP
    Scrivo un foglietto per ogni classe
    Si fa in presenza del cliente, quindi usare un linguaggio domain-oriented
    E' più utile per verificare le classi che per pianificarle

    Design Patterns
    Rende più facile riconoscere situazioni comuni
    I Pattern sono indicazioni per la risoluzione di problemi comuni
    Esiste un wiki interessantissimo sui pattern: http://c2.com/cgi/wiki?CodeSmells
    Anti-Pattern
    E’ la denuncia di soluzioni sbagliate in base alla propria esperienza.
    I Pattern sono una derivazione dell’architettura, il GOF (Gang Of Four) ha introdotto i pattern architetturali per l’informatica.
    Composizione di un pattern:

    • Nome (chiaro)
    • Contesto (quando e perché si presenta il problema che vorremmo risolvere)
    • Forze (perché il problema è difficile, scopi, vincoli e fattori motivanti)
    • Soluzione (di solito in diagrammi simil-UML)
    • Esempi (uno o più esempi di come si è affrontato il problema)
    • Contesto risultante (illustra i benefici del risultato proposto)
    • Razionale: motivazioni della bontà della soluzione
    • Pattern in relazione: ovvero pattern che posso incastrare comunemente con questo
    • Usi conosciuti: Altri contesti d’uso oltre agli esempi
    Meta pattern
    Aiuta a categorizzare i pattern
    Identifica due elementi base:
    1. Hook Method: punti dove si può incastrare un altro pattern. Punto in cui il pattern lascia carta bianca e si può iniettare qualcos’altro.
    2. Template Method: Metodo che coordina generalmente più Hook Method. Parte intoccabile del pattern, scheletro del pattern.
    Unification: Dove template e hook sono nella stessa classe
    Separation: Un metodo in una classe e uno in un’altra
    Connection e recursive connection: Contenuti in classi separate, ma tra loro associate (anche ricorsivamente)
    Nel libro del GOF hanno individuato 23 pattern, suddivisi in:


    • Creazionali: riguardanti la creazione di oggetti (es.: Singleton)Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
    • Comportamentali: come devono interagire le classiChain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor
    • Strutturali: composizione di classi ed oggettiAbstract Factory, Builder, Factory Method, Prototype, Singleton


    Pattern Singleton
    Implementare il concetto di oggetto separatamente da quello di classe (una sola istanza di una classe).
    In pratica si crea un costruttore privato e si mettere un metodo condiviso (Static(1)) che ritorna quell’unica istanza
    Osservazioni:
    Perché non fare una classe statica? Una classe statica o con tutti i membri statici non può essere ereditata. Inoltre potrei cambiare in futuro il numero di istanze disponibili.



    (1) I metodi statici sono “metodi di classe”: ovvero appartengono alla classe e non all’istanza: Sono richiamabili senza nessuna istanza e non possono contenere riferimenti a campi o metodi d’istanza. Metodi e membri statici sono condivisi a tutte le istanze (sono, appunto, legati alla classe)

    Ingegneria del software: 17 marzo 2005

    Object Orientation
    Programmazione modulare:
    Astrazione
    Incapsulamente (e information hiding)

    Esistono delle relazioni fra moduli:
    Una relazione fra moduli é un vettore che unisce una coppia di moduli (prodotto cartesiano sull'insieme degli oggetti)
    2 relazioni:
    USES:
    IS_COMPONENT_OF: l'opposto di USES (se A uses B, allora B is_component_of A)
    Una classe é definita da un contratto: garantisce delle funzionalità che vengono racchiuse al suo
    interno.

    Approcci ai moduli:
    Procedurale: raccolta di funzioni
    Data Pool: dati comuni (raccolta di variabili globali)

    Abstract Object: Vengono messe insieme le procedure ed i dati. Ad esempio: gestione dei files: il risultato della chiamata a funzioni varia a seconda dello stato dell'oggetto.
    Abstract Data Type: Viene definito un modello raggruppando le parti comuni a delle istanze per garantire all'utente (programmatore)
    Generic: Template parametrici rispetto al tipo di una loro parte (ad esempio: array)

    OBJECT ORIENTATION:
    Abstract Data Type: le classi
    Nuove relazioni:
    Ereditarietà (generalizzazione: un tipo deriva da un altro tipo e ne estende le funzionalità)
    Aggregazione: (IS_PART_OF)
    Nuovi concetti e principi:
    Polimorfismo: una classe può "spacciarsi per un altro tipo". 2 tipi di polimorfismo: di ereditarietà: un oggeto di tipo mela può essere "spacciato" per un oggetto di tipo frutta; di interfaccia: rondine e aereo possono essere spacciati per "IFlingObject"
    Dynamic Binding: In fase di esecuzione si sostituisce la corretta implementazione di un metodo per ogni oggetto.
    Ad esempio: se un metodo viene ridefinito si deciderà se chiamare quello "nuovo" o quello della classe base a seconda del tipo di oggetto su cui lo si chiama.
    Le classi:
    Sono il "progetto di costruzione" di un oggetto
    Possono essere un progetto "incompleto": (classi astratte) definiscono solo una parte di comportamento di un oggetto
    Le classi implementano una o più interfacce: contratti delle classi
    In UML il diagramma delle classi é la "vista statica"
    Definita in 3-4 parti:
    Nome della classe, attributi (campi), metodi ed eventualmente proprietà
    A sinistra posso porre: + (publico), - (privato), # internal (protected): disponibile solo per la classe e le sue derivate
    I metodi in corsivo sono quelli astratti. Se il nome della classe é in corsivo la classe é astratta.
    Cercare di fare sempre privato il più possibile

    Generalizzazione (ereditarietà):IS_LIKE_A, CAN_BE_A
    E' possibile definire una parte di oggetto.
    Classi derivate sono polimorfiche rispetto alle classi base (se quadrupede eredita da animale un
    oggetto di tipo quadrupede é anche istanza di animale)
    Permette riuso di codice (in generale le classi derivare dovrebbero estendere le funzionalità (e NON ridurle))
    Generalizzazione può essere anche multipla (una classe può ereditare da più di una classe base). Problema di ereditarietà multipla: (una classe potrebbe derivare 2 volte da un'altra (che implementazione dei metodi devo usare?)
    In UML la generalizzazione é rappresentata con una freccia con il triangolo bianco
    Non riscrivo i metodi ereditati a meno che non ne vada a cambiare l'implementazione (override)

    Relazioni tra classi in UML:
    Una riga collega le due classi.
    Una label sulla riga spiega l'interazione.
    All'attacco della riga viene specificata la molteplicità: può essere un numero o un range (1..* indica 1 o più)
    All'attacco della riga posso anche specificare il ruolo: ad esempio un'acquisto da persona a persona dovrà specificare quale dei 2 é nel ruolo di venditore e quale di acquirente.

    Se c'é una freccia APERTA (a V) indica che la classe da dove parte la freccia deve conoscere l'altra, ma non per forza il viceversa. Sostanzialmente la presenza della riga di congiunzione indica che la classe ha un attributo del tipo dell'altra classe
    Ovviamente si possono mettere più relazioni fra le stesse classi, o relazioni riflessive.
    E' sempre bene stabilire la direzione quando possibile

    Composizione
    Vuole dire che un oggetto fa strettamente parte di un altro oggetto (ad esempio un motore di un aereo)
    Gli oggetti "componenti" (motori) possono interagire verso l'esterno SOLO tramite l'oggetto composito
    (aereo), si indica con una linea iniziata da un rombo (dalla parte dell'oggetto composito)

    Per raggruppare più classi posso usare il package:

    Dipendenza
    E' una dipendeza non statica (non presuppone la conoscenza)... ???
    E' una relazione che non viene rimappata su un attributo/prorpietà di classe
    Poco usata
    Si esprime con una freccia tratteggiata terminata da una freccia a V


    Interfacce
    Sono delle classi astratte senza implementazione di alcun metodo. Possono venire implementate (multiple) anche dai linguaggi che non prevedono ereditarietà multipla.