Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
Trasformazione dei progetti in software
Il codice deve essere funzionante, ben organizzato e deve avere delle qualità come la modificabilità e la comprensibilità. Quest'attività non è automatica ma piuttosto nella trasformazione c'è spazio per ulteriori modifiche di progetto anche se di entità minore. L'attività di trasformazione del progetto in codice è guidata da tutte le attività svolte in precedenza ovvero analisi dei requisiti e progettazione. Questa in particolare ci fornisce in output:
- Diagramma delle classi di progetto che impatta sul codice del software per quanto riguarda le classi e la loro struttura.
Per ogni classe del diagramma delle classi di progetto possiamo definire nel codice una classe (o un'interfaccia), per ogni attributo o associazione verranno definite variabili di istanza della classe, e per ogni operazione verranno definiti i metodi. Non ci dà dettagli sulle
istruzioni da scrivere all'interno dei metodi.- Diagramma di interazione: impattano sulle istruzioni che possiamo scrivere nei diversi metodi (come la creazione di oggetti e l'invocazione di metodi).
- L'ordine di trasformazione dovrebbe essere quello dalla classe meno accoppiata alla classe più accoppiata.
- Scrittura del TEST: il test deve essere il più semplice per poter far fallire il codice. Semplice significa che...
Deve essere un test la cui scrittura per la soluzione venga fatta in massimo un paio d'ore.
Scrittura del codice per far passare il test: Il codice più semplice per passare quello specifico test, gli altri casi condizionali verranno presi in considerazione dopo. Qui ci interessa avere un feedback veloce.
Refactoring del codice se necessaria. Serve a mettere ordine nella scrittura del codice. Il codice non deve essere uso e getta quindi deve avere qualità.
I test che possiamo prendere in considerazione sono:
- Unitari: test che servono a verificare unità di programmazione (metodi o al massimo classi). Normalmente vengono eseguiti in modo automatizzato. In java viene fatto utilizzando il framework JUnit
- Di Integrazione: Servono a verificare che il sistema, composto da diverse parti, collabori correttamente con queste.
- End to End: Servono a verificare il sistema nella sua interezza, Stimolano tutte le parti per questa verifica.
Accettazione: Sono test molto importanti che vengono specificati con riferimento a degli scenari importanti. Se questi vengono superati il sistema viene accettato altrimenti no. Normalmente per uno scenario di caso d'uso si scrive uno o più scenari di accettazione. Questi test vengono integrati nel ciclo iterativo precedente (scrivi un test che fallisce, fai passare il test, fai il refactor) per scrivere test di accettazioni che falliscono. Per fare sì che passino vengono scritti tanti test unitari.
Le conseguenze nello sviluppo guidato dai test sono:
- Feedback sul codice che è stato realizzato
- Documentare il codice ed il test
- Migliore organizzazione del codice perché per poter scrivere i test il codice è ben organizzato.
- Fiducia nei cambiamenti: nello sviluppo iterativo si cambia molte volte il codice per estenderlo, lo sviluppo guidato sui test ci rassicura sulla paura che questi cambiamenti portino ad un malfunzionamento
Una prima definizione è che il refactoring è una pratica per preparare il codice all'introduzione di nuove funzionalità o nell'applicazione di cambiamenti. Può essere utile anche per evitare ridondanze o cambiare l'assegnazione delle responsabilità. Tutte comunque attività per migliorare la qualità del codice.
Una seconda definizione dice che è un metodo disciplinato per ristrutturare il codice senza modificarne il suo comportamento esterno. L'idea è quella di separare in modo netto la ristrutturazione del codice con la modifica del suo comportamento. Prima infatti si ristruttura il codice senza modificare il comportamento, eseguire i test fatti in precedenza e se questi continuano a "passare" possiamo dire che abbiamo fatto una buona riorganizzazione perché non abbiamo cambiato il comportamento. L'attività di trasformazione
vienefatta passo per passo facendo delle piccole trasformazioni (seguite ognuna dal proprio test). Alcune forme comuni direfactoring sono:
- Riorganizzare metodi e dati: se abbiamo metodi troppo lunghi conviene crearne nuovi più piccoli
- Muovere caratteristiche tra classi: utile per cambiare le responsabilità degli oggetti. Riduciamo l'accoppiamento.
- Trattare con le generalizzazioni: Separare da una classe la sua interfaccia e prepararci per il polimorfismo.
LEZIONE 11 - Ulteriore analisi a Oggetti
Nella prima iterazione si prende in considerazione lo scenario di successo di base, senza l'interazione con sistemi esterni. Nella seconda iterazione si prendono in considerazioni altri scenari con interazioni con sistemi esterni e il collegamento tra gli strati.
Nella modellazione di dominio abbiamo visto nella prima iterazione la definizione di classi, attributi e associazioni. In questa seconda iterazione ci occuperemo di aggiungere al modello elementi
condizioni che devono concorrere affinché sia lecito definire la generalizzazione/specializzazione sono 3, e devono verificarsi tutte. In particolare sono: 1. La definizione della superclasse deve essere più generale di quelli delle sottoclassi. 2. I membri delle sottoclassi sono anche membri della superclasse (è un aspetto estensionale). 3. Le sottoclassi aggiungono caratteristiche specifiche alla superclasse. Un esempio può essere quello dei tipi di pagamento (carta di credito, contanti, assegno). Le sottoclassi sono tra loro sorelle. La generalizzazione/specializzazione è un'astrazione relativa alla presenza di caratteristiche comuni tra le classi. Il suo uso definisce una relazione tra una superclasse e una sottoclasse. La superclasse rappresenta la generalizzazione del concetto rappresentato dalla sottoclasse, la sottoclasse, al contrario, rappresenta una specializzazione della superclasse.caratteristiche strutturali (attributi e associazioni) della superclasse devono essere anche le caratteristiche strutturali della sottoclasse. Il fatto che sia lecito utilizzare le generalizzazioni/specializzazioni non è detto che sia utile. Quando è utile definire una sottoclasse:
- Se la sottoclasse ha delle proprietà strutturali aggiuntive di interesse: se per la sottoclasse possiamo specificare degli attributi o delle partecipazioni ad associazioni significative per la sottoclasse ma non per la superclasse e le sorelle.
- Se la sottoclasse è caratterizzata da un comportamento diverso: dalla superclasse o dalle sorelle.
Una linea guida da seguire è quella di non identificare solo una sottoclasse, ma identificare una partizione (insieme disgiunto e coprente) della superclasse. In questo caso diremo che la superclasse è astratta (non può essere istanziata direttamente).
Quando è utile definire una superclasse? Se le
potenziali sottoclassi rappresentano variazioni di un concetto simile e se hanno caratteristiche comuni. Possiamo supporre di aver prima identificato delle classi disgiunte, che rappresentano variazioni di un concetto simile, e poi capire che è utile inserire una superclasse. In essa verranno inserite le parti comuni. Abbiamo visto come gestire meglio la modellazione delle informazioni. Vediamo adesso come identificare le operazioni di sistema. Bisogna dapprima considerare lo scenario principale di un caso d'uso, identificare le operazioni di sistema e mostrarle in un SSD. Per identificare le ulteriori operazioni di sistema bisogna considerare le estensioni del caso d'uso e identificare le ulteriori operazioni di sistema. Queste ulteriori operazioni di sistema identificate non è sempre necessario (né utile) mostrarle in un diagramma di sequenza di sistema. Conviene disegnare solo quelle che mostrano iterazioni interessanti e non banali. Una precisazione daifare sui contratti (il modo in cui rappresentiamo il comportamento) è che nelle post-condizioni bisogna specificare solo la creazione di istanze da sottoclassi concrete e mai da superclassi astratte.
LEZIONE 12 - Ulteriori Pattern per l'assegnazione di responsabilità
PURE FABRICATION
Suggerisce di avere delle classi che non rappresentano informazioni ma comportamenti. La decomposizione in classi infatti può essere dettata da una decomposizione rappresentazionale (se ispirata al modello di dominio) o da decomposizione comportamentale come appunto quelle suggerite da Pure Fabrication. Queste ultime possono rappresentare algoritmi, strategie o servizi. Per servizi si intende un insieme di operazioni correlate che non trova spazio in un'altra classe del dominio.
Il problema è: A chi assegnare le responsabilità quando le soluzioni suggerite da Information Expert o Creator non sono appropriate perché violano Low coupling e High Cohesion o altri.
principi? La soluzione suggerita è: assegnare un insieme altamente coeso di responsabilità ad una classe artificiale (non ispirata al modello di dominio) che sostiene coesione alta, accoppiamento basso e riuso cosicché la progettazione di questa invenzione è molto pulita (pura) da cui il nome Pure Fabrication.
INDIRECTION (intermediario) L'introduzione di un intermediario nella progettazione può ridurre l'accoppiamento e avere un effetto benefico nel progetto. Il Problema: dove assegnare una responsabilità per evitare l'accoppiamento diretto tra due o più elementi? La Soluzione suggerita è di assegnare la responsabilità ad un oggetto intermediario così da non esserci accoppiamento diretto. Molti design pattern che sono delle Pure Fabricarion sono anche delle indirezioni.
POLYMORPHISM I linguaggi di programmazione a oggetti contengono concetti di polimorfismo, interfacce e sovrascrittura. Il problema: Come
La soluzione suggerita è: quando le alternative o i comportamenti variano con il tipo, assegnare le responsabilità del comportamento ai tipi per i quali il comportamento varia, utilizzando operazioni polimorfe. I