Università degli Studi di Milano Bicocca – Laurea Magistrale in Informatica
Corso di Evoluzione Sistemi Software e Reverse Engineering 2008/2009 – Prof.ssa Arcelli
Object Oriented Reenginnering Pattern
Tests:Your Life Insurance!
Migration Strategies
Carella Carmine
Faustinoni Fabrizio
Falco Giuseppe
Passoni Alberto
Riferimenti: Object Oriented Reenginnering Pattern - S.Demeyer, S.Ducasse,
O.Nierstrasz, 2008.
1
Tests: Your Life Insurance!
Il tema principale del cluster è: l’utilizzo di strategie di
testing nel contesto della reingegnerizzazione per
ridurre i rischi del processo di cambiamento di un
sistema legacy critico per il business aziendale.
N.B: le strategie di testing presentate non sono le uniche possibili, ma quelle più
rilevanti nel caso di un progetto di reengineering.
2
Pattern che compongono il cluster e loro relazioni:
Tests: You Life Insurance!
3
Write Test to Enable Evolution
OBIETTIVO:
proteggere il valore del legacy system attraverso un testing sistematico.
PROBLEMA:
minimizzare i rischi in un processo di reengineering. Modificare un legacy è
rischioso per il business.
Quali Rischi?
– Non soddisfare l’obiettivo del reengineering;
(miglioramento legacy system  evoluzione)
– Introdurre ulteriore complessità nel sistema;
– Compromettere le funzionalità critiche per il business;
– Intraprendere una strada sbagliata: troppi sforzi per un task che non è
quello designato;
– Aumentare ulteriormente i costi di mantenimento.
Tests: You Life Insurance!
4
Write Test to Enable Evolution
Problema Difficile perché:
• La valutazione dei cambiamenti non sempre è possibile
• Test non sempre è applicabile
– componenti non comprese perché non documentate  test progettato
male
– Dipendenze nascoste, destabilizzano il sistema.
Problema risolvibile
– Sistema in esecuzione e si determina cosa funziona e non funziona
– Sono note le parti del sistema stabili e quelle soggette a cambiamenti
Soluzione
– Un processo di testing basato su test ben progettati.
(Well-designed test)
Tests: You Life Insurance!
5
Well-Designed test – proprietà
– Automatico: test eseguiti senza intervento umano. Test pienamente
automatici.
– Persistente: un test, per essere automatico deve essere memorizzato.
Memorizzare i dati del test, le azioni da eseguire e il risultato atteso.
• Documentazione del sistema;
• Soggetto a controllo delle versioni, come altro codice;
– Ripetibile: dopo ogni implementazione di un cambiamento il test deve
essere rieseguito. Data una nuova funzionalità deve esser possibile
aggiungere facilmente nuovi test tra quelli esistenti (test suite).
– Unit testing: i test dovrebbero essere associati a componenti software
atomiche , per identificare chiaramente quali parti testano e ridurre la
complessità del test.
– Indipendente: minimizzare le dipendenze con gli altri test per evitare
“effetto a cascata”. Il numero di test falliti deve essere un indicatore
del numero di problemi rilevati.
Tests: You Life Insurance!
6
Write Test to Enable Evolution
Vantaggi:
– I test aumentano la fiducia nel sistema e favoriscono cambiamenti
sicuri permettendo l’evoluzione.
– Documenti di test come artifacts di un sistema. Descrizione del sistema
sempre aggiornata, rispetto alla documentazione scritta.
– Framework di supporto esistono per tutti i principali linguaggi object
oriented (Smalltalk, Java C++).
Svantaggi:
–
–
–
–
Allocare risorse umane per scrivere i test
I test dimostrano solo la presenza di difetti, non li risolvono.
È impossibile coprire con i test tutti gli aspetti di un sistema legacy
Test progettati male: il test viene eseguito si pensa tutto va bene, ma
in realtà non sta testando il comportamento desiderato.
Tests: You Life Insurance!
7
Write Test to Enable Evolution
Difficoltà:
–
–
–
–
Troppi approcci di testing esistenti. Scelta dell’approccio più adatto.
Legacy system grandi e non documentati  testing proibitivo
Management è restio nell’investire nel testing.
Convincere gli sviluppatori ad adottare il testing: mostrare come il
testing non solo velocizza lo sviluppo ma anche l’attività di
mantenimento
– Il testing può essere un attività noiosa: utilizzo del toll di supporto più
adatto.
Tests: You Life Insurance!
8
Write Test to Enable Evolution
Conclusioni:
• I test rappresentano una forma tangibile di fiducia nel sistema, perché
permettono di verificare che il sistema sia corretto e possono essere
eseguiti quando si vuole per verificarne la consistenza.
• I test sono la base per il reengineering.
Attività di Mantenimento
documentazione
Fiducia nel sistema
Evoluzione Architetturale
Riduzione dei rischi
Fiducia nei cambiamenti al sistema
Tests Automatici
Tests: You Life Insurance!
9
Write Test to Enable Evolution
Relazioni con altri pattern:
–
–
–
–
Always have a running version
Migrate system incrementally
Grow your test base incrementally
Test the interface, not the implementation
Tests: You Life Insurance!
10
Grow Your Test Base Incrementally
OBIETTIVO:
bilanciare i costi e i benefici dei test, introducendoli
incrementalmente solo quando necessario.
Tests: You Life Insurance!
11
Grow Your Test Base Incrementally
Problematiche:
– Progettazione dei casi di test occupa una notevole quantità di
tempo
 quando fermarmi nel costruire casi di test?
– Impossibile testare tutte le parti che compongono un legacy
system data la loro grandezza e complessità
– I programmatori che hanno realizzato il sw non sono più
reperibili e quindi le conoscenze del legacy sono limitate.
Soluzione:
– Introdurre i test incrementalmente, solo per quelle parti del
sistema su cui stiamo lavorando
Tests: You Life Insurance!
12
Grow Your Test Base Incrementally
Suggerimenti:
– Sviluppare i casi di test nel seguente ordine:
1.
2.
3.
Inizialmente solo per le componenti più critiche e con priorità
più alta.
Per le nuove funzionalità create durante la fase di reengineering.
Per le parti che presentano bug importanti.
– Se si ha una storia dei vecchi bug risolti, usare i vecchi Test
bug come punto di partenza.
– Testare le interfacce e non l’implementazione, iniziando
dalle grandi gerarchie di astrazione e, se avanza tempo,
testare singolarmente le parti.
Tests: You Life Insurance!
13
Grow Your Test Base Incrementally
Vantaggi:
1. Risparmi del tempo (in quanto si sviluppano solo i test
necessari).
2. Costruzione di test per le parti più critiche del sistema.
3. Agevolazione dello sviluppo di funzionalità future e del
mantenimento.
Svantaggi:
–
–
Errori nell’individuazione degli aspetti critici del sistema
 tempo e risorse sprecate.
I test possono dare troppa fiducia in quanto possono
ancora nascondersi bug importanti nel codice.
Tests: You Life Insurance!
14
1. Individuare il sottosistema da modificare (ABC)
2. Introdurre i test solo per il sottosistema ABC e per la componente B
3. Applicare i test alla nuova componente B
Tests: You Life Insurance!
15
Grow Your Test Base Incrementally
CONCLUSIONI:
• Una strategia di test incrementale consente di
iniziare il processo di reengineering prima di aver
sviluppato tutti i test.
• Minimo investimento di risorse nella fase di test
 in quanto questa fase è concentrata
solo su quelle parti che si intendono
modificare e non su tutto il sistema.
Tests: You Life Insurance!
16
Use a testing framework
OBIETTIVO:
Incoraggiare gli sviluppatori a scrivere ed utilizzare i test di regressione,
fornendo un framework che ne renda facile lo sviluppo, l’organizzazione
l’esecuzione.
e
PROBLEMA – Come incoraggiare il team a fare testing?
Problema Difficoltoso :
- i test sono noiosi da creare;
- richiedono la creazione di dati ad-hoc per essere effettuati;
- è difficile capire la differenza tra un test fallito ed un
unexpected error.
Tests: You Life Insurance!
17
Use a testing framework
LA SOLUZIONE E’ FATTIBILE:
- I test (la maggior parte) seguono lo stesso pattern
CREAZIONE DATI DI PROVA
ESECUZIONE DI ALCUNE AZIONI
VERIFICA ESITO
- l’infrastruttura per eseguire i test è semplice
QUINDI…
Utilizzare un framework di testing
che consenta di comporre una test suite a
partire da test case specifici
Tests: You Life Insurance!
18
Use a testing framework
POSSIBILE PROBLEMA:
- Non esiste un framework di test per il linguaggio che si sta utilizzando
NIENTE PAURA!
Combinare le informazioni che si possiedono in accordo con i seguenti
principi:
- L’utente fornirà casi prova utilizzabili come test e fornirà asserzioni sui
risultati;
- Il framework fornisce un feedback in caso di successo insuccesso
del test
INDICA PRECISAMENTE IL TEST CHE E’ FALLITO
GLI ERRORI DEVONO ESSERE COLLOCATI IN UN REPORT
- Il framework consente la creazione di test suite
Tests: You Life Insurance!
19
Use a testing framework
PRO:
Un framework per i test semplifica la formulazione dei test
invoglia i programmatori ad effettuarli.
ed
CONS:
La fase di test richiede impegno, disciplina e supporto;
E’
difficoltoso convincere il team dell’utilità del testing;
E’ complicato inserire la fase di test all’interno del processo di
sviluppo di un team che non l’ha mai considerata.
Tests: You Life Insurance!
20
Use a testing framework
ESEMPI:
Junit (test framework for Java)
- I test sono definiti come sottoclassi di TestCase
- Utente deve definire i metodi setUp(), runTest() e tearDown()
- Gli errori sono gestiti e segnalati mediante l’utilizzo della classe
TestResult
- TestCase fornisce metodi standard come assertEquals e asserdFails
- I test possono essere inseriti all’interno di una TestSuite
ESISTONO FRAMEWORK DI TEST SPECIFICI PER OGNI TIPO DI LINGUAGGIO: Ada, ANT, C, C++, Delphi, .Net (all
languages), Eiffel, Forte 4GL, GemStone/S, Jade, JUnit Java, JavaScript, k language (ksql, from kbd), Objective C,
Open Road (CA), Oracle, PalmUnit, Perl, PhpUnit, PowerBuilder, Python, Rebol, ‘Ruby, Smalltalk, Visual Objects
and UVisual Basic.
Tests: You Life Insurance!
21
Test the Interface, Not
the Implementation
OBIETTIVO:
costruire test riusabili che non si focalizzino sui dettagli di
implementazione, ma piuttosto su comportamenti esterni, per
sopravvivere ai cambiamenti del sistema
PROBLEMA:
Sviluppare test che siano resistenti nel tempo ai cambiamenti della
componente a cui sono legati.
Problema difficile perché:
• mentre evolve, il legacy system deve continuare a supportare il processo di
business;
• non si può perdere troppo tempo nella scrittura dei test;
• non impiegare troppe energie per scrivere test che diventeranno presto
obsoleti.
Tests: You Life Insurance!
22
Test the Interface, Not
the Implementation
Problema risolvibile:
– Le interfacce dei componenti dicono cosa deve esser testato
– Le interfecce tendono a essere più stabili dell’implementazione.
Soluzione:
– Sviluppare test di tipo black-box che sfruttano le interfacce pubbliche
delle componenti.
– Costruire la soluzione:
• Come dati di test utilizzare valori estremi (minimo e massimo);
• Se ci sono molte componenti fine-grained utilizzare una strategia
top-down per sviluppare i test;
• Se si sta modificando una funzionalità ben precisa utilizzare una
strategia bottom-up per testarla.
Tests: You Life Insurance!
23
Test the Interface, Not
the Implementation
Vantaggi:
– Se l’implementazione cambia è poco probabile che la sua interfaccia
subisca modifiche  test sull’interfaccia è più riusabile;
– Black-box tests possono essere usati per più implementazioni della
stessa interfaccia;
– I test sulle interfacce sono più semplici da realizzare;
– Evita di scrivere i test troppo presto;
Svantaggi:
– I Black-box test non coprono tutto il codice;
– Se l’interfaccia cambia, bisogna modificare il test;
– La classe non fornisce la giusta interfaccia per l’applicazione del
black-box test, allora altre strategie di testing (white-box testing).
Tests: You Life Insurance!
24
Test the Interface, Not
the Implementation
Conclusioni:
– Le interfacce di un componente, sono una conseguenza
della sua interazione con altre componenti; il black-box
test può essere utile nel verificare le principali interazioni
di un sistema
– Black-box test hanno maggiori probabilità di sopravvivere
ai cambiamenti del sistema, perché le interfacce tendono
ad essere più stabili.
Relazioni con altri pattern:
– Record business rule as tests.
Tests: You Life Insurance!
25
Record Business Rules as Tests
OBIETTIVO:
Mantenere il sistema al passo con le regole di
business da esso implementate codificandole come
Test.
Tests: You Life Insurance!
26
Record Business Rules as Tests
Problematiche:
• La documentazione spesso non contiene i dati relativi ai piani
business
• Regole business spesso sono implicite nel codice
• Il cambiamento degli sviluppatori provoca l’aumento dei rischi
• Cambiamento per fattori esterni
• Risoluzione problematica semplice poiché le regole business
seguono delle linee guida
Tests: You Life Insurance!
27
Record Business Rules as Tests
Soluzione:
• Scrivere test eseguibili che registrano gli affari come casi di
test.
• Gli sviluppatori scrivono i test funzionali
• I clienti scrivono i test di integrazione
Tests: You Life Insurance!
28
Record Business Rules as Tests
Vantaggi:
• Regole esplicite, riduzione dipendenza umana
• Prima di effettuare la reingegnerizzazione del legacy system si
devono registrare le regole business
• Permette l’evoluzione delle regole business: aggiunta di nuove
features e test di regressione per verificare la loro correttezza
Tests: You Life Insurance!
29
Record Business Rules as Tests
Svantaggi:
• I test codificano solo eventi concreti
• La logica business prevede molti casi, ma non tutti vengono
trattati
• Registrare business rules non significa estrarre business rules.
L’estrazione con la corrente tecnologia è ancora un sogno.
• Registrare business rules è difficile se cambia il team
Tests: You Life Insurance!
30
Record Business Rules as Tests
Conclusioni:
• I test sono un buon metodo per documentare ciò che il
sistema fa.
• Documentando i business rules come test, posso garantire la
descrizione di esso durante l’implementazione
Tests: You Life Insurance!
31
Write Test To Understand
Obiettivo
Registrazione della comprensione di parte del codice sotto
forma di test eseguibili, in modo da essere utili quando si
modificherà il sistema in futuro
Tests: You Life Insurance!
32
Write Test To Understand
Problematiche
•
•
•
•
Codice non sempre comprensibile
Ipotesi su quello che il codice fa e validazione di tali ipotesi
Specificare il comportamento del sistema
Documentazione obsoleta appena si cambia il codice
Tests: You Life Insurance!
33
Write Test To Understand
Soluzione
• Codificare ipotesi e conclusioni come test eseguibili
Tests: You Life Insurance!
34
Write Test To Understand
Vantaggi
•
•
•
•
•
I test aiutano la comprensione
I test offrono specifiche precise di certi aspetti del sistema
I test sono applicati a diversi livelli di comprensione
I test sviluppati aiuteranno il futuro reengineering
Maggiore precisione nella creazione e uso dell’oggetto
Tests: You Life Insurance!
35
Write Test To Understand
Svantaggi
• Scrivere test comporta la perdita di tempo
• Oggetti testati non hanno un’astrazione
• Non va bene per processi concorrenti
Tests: You Life Insurance!
36
Write Test To Understand
Conclusioni
• Per scrivere test automatici bisogna partite dal sistema preso
in considerazione e capirlo
• Registrazione per settare il piano per una futura reingegnerizzazione
Tests: You Life Insurance!
37
Migration Strategies
Migration Strategies
38
Migration Strategies
Introduzione
Dopo i test la reingegnerizzazione è a buon punto, si ha una buona
conoscenza del sistema legacy e si sono scritti i test che iniziano la fase di
evoluzione.
Domande
• Siamo sicuri che il nuovo sistema sarà accettato?
• Come migrare verso il nuovo sistema nonostante quello vecchio sia
ancora in uso?
• Si può testare il nuovo sistema prima che sia pronto?
Migration Strategies
39
Migration Strategies
Punti chiave:
•
•
•
•
Migrazione Big-bang rischiosa
Troppe modifiche creano confusione negli utenti
Feedback
Gli utenti devono fare il loro lavoro, ma non vogliono essere
distratti da soluzioni incomplete
• Data legacy devono rimanere intatti
Panoramica
Il reengineering non è sufficiente, bisogna introdurre la
migrazione graduale verso un nuovo sistema in modo da
essere indolore agli utenti.
Migration Strategies
40
Migration Strategies
Migration Strategies
41
Involve The User System
• Obiettivo:
massimizzare il numero di cambiamenti coinvolgendo l'utente
a ogni step
Migration Strategies
42
Involve The User System
Problematiche:
• I sistemi sono vecchi. Gli utenti vogliono sapere come
funziona e come aggirare i problemi.
• La gente odia il dover imparare qualcosa di nuovo a meno che
non sia qualcosa di semplice
• La percezione dell'utente di ciò che è necessario per
migliorare un sistema.
• Gli utenti possono avere difficoltà a valutare un documento di
progettazione.
• E‘ difficile essere entusiasti di un nuovo sistema che non è
pronto per l'uso.
Migration Strategies
43
Involve The User System
Soluzione:
Coinvolgere direttamente gli utenti e tenerli aggiornati sul
sistema.
Passi:
•
•
•
•
chiedere agli utenti le priorità.
dividere le priorità in fasi.
utenti e sviluppatori si devono tenere in contatto.
avere dei feedback sulle versioni intermedie.
Migration Strategies
44
Involve The User System
Vantaggi:
• I requisiti devono essere aggiornati e validati spesso, per
andare verso il risultato sperato
• Se gli utenti hanno la sensazione d'essere utile per ottenere i
risultati saranno invogliati a lasciare feedback positivi
• Gli utenti saranno coinvolti durante lo svolgimento del
progetto, eliminando il successivo periodo di formazione
Migration Strategies
45
Involve The User System
Svantaggi:
• Gli sviluppatori possono avvertire gli utenti che il loro
coinvolgimento può distrarre dal lavoro di
reingegnerizzazione del sistema.
• Aumento delle aspettative e mettere pressione
supplementare sul vostro team.
• Può essere difficile coinvolgere gli utenti
• Non è possibile coinvolgere tutti, e gli utenti che sono lasciati
fuori potrebbero sentirsi trascurati
Migration Strategies
46
Involve The User System
Conclusioni:
• Si utilizzano i feedback per assicurare che si stanno
affrontando le reali esigenze del cliente.
Migration Strategies
47
Build confidence
Obiettivo:
• aumentare le chances di avere successo attraverso risultati
dimostrativi a ogni fase.
Migration Strategies
48
Build confidence
Problematiche
• Alcuni progetti vogliono dei requisiti e devono rientrare in un
badget.
• Gli utenti raramente dicono ciò che realmente vogliono
• Difficoltà nel convincere gli utenti sui legacy system
Migration Strategies
49
Build confidence
Soluzione:
• creare un atmosfera positiva per dimostrare che molti
risultati positivi sono ottenibili grazie a questo clima
Fasi:
• Suddividere il lavoro in piccoli step per avere il più presto
possibile un nuovo risultato
Migration Strategies
50
Build confidence
Vantaggi
• Utenti e sviluppatori possono vedere i reali progressi
• Facilità nella stima dei costi
Migration Strategies
51
Build confidence
Svantaggi
• sincronizzazione
• avere successo aumenta le aspettative
• lavoro extra
• Alcuni requisiti sono difficili da dividere.
• Re-ingegnerizzazione difficile
• Difficoltà nel convincere gli utenti e gli sviluppatori
Migration Strategies
52
Build confidence
Conclusioni
• lavorando a piccoli step si riducono i rischi, aumentano la
confidenza e si tiene sempre traccia sul progresso del lavoro
Migration Strategies
53
Migrate Systems Incrementally
• Obiettivo:
Evitare la complessità e il rischio di big-bang
reengineering causati dai frequenti
implementazioni.
Migration Strategies
54
Migrate Systems Incrementally
Problematiche
• I progetti spesso sono sviluppati guardando avanti, ma questo
può portare a nuove richieste
• Le reali richieste vengono fuori sempre dopo.
• Più tardi si distribuisce il sistema e più tardi arrivano i
feedback
• Impossibile distribuire un sistema incompleto
Migration Strategies
55
Migrate Systems Incrementally
Soluzione
Implementare un primo aggiornamento del sistema legacy
non appena è possibile e migrazione incrementale.
Passi
• Decomposizione del sistema legacy.
• Scegliere una parte da analizzare.
• Mettere in atto i test per la parte e le parti che dipendono
da essa.
• Prendere le misure opportune per il wrap, la reengineer o
la sostituituzione la componente.
• Distribuire i componenti aggiornati e ottenere un feedback.
Migration Strategies
56
Migrate Systems Incrementally
Vantaggi
• È possibile ottenere subito il feedback degli utenti.
• Si vede quello che il sistema fa alla fine di ogni fase.
• Gli utenti imparano questo nuovo sistema durante la sua
costruzione.
• Il sistema è sempre implementato.
• Il sistema è in fase di sperimentazione, non è possibile saltare i
test.
Migration Strategies
57
Migrate Systems Incrementally
Svantaggi
• Si dovranno impiegare risorse per mantenere il sistema in
esecuzione
• Difficoltà nella migrazione verso una nuova architettura
• Rischioso cambiare un sistema che si sta ancora utilizzando
Migration Strategies
58
Migrate Systems Incrementally
Conclusioni
• Ottenere i feedback positivi
• Utenti invogliati se utilizzano molto frequentemente il
sistema e non hanno problemi
Migration Strategies
59
Prototype the Target Solution
• Obiettivo:
valutare il rischio di migrazione verso una
nuova soluzione mediante la costruzione di un
prototipo.
Migration Strategies
60
Prototype the Target Solution
• Problematiche:
– E’ rischioso effettuare cambiamenti radicali su un sistema
funzionante.
– Difficoltà nell’analizzare l’impatto dei cambiamenti del
sistema con le funzionalità esistenti.
• Soluzione:
– Sviluppare un prototipo della nuova soluzione e valutare
con riguardo i nuovi requisiti.
Migration Strategies
61
Prototype the Target Solution
• Suggerimenti:
– Identificazione dei più grossi rischi tecnici del progetto di
reengineering:
• Scelta di una nuova architettura.
• Migrazione dei dati del legacy al nuovo sistema.
• Decidere se implementare un prototipo esplorativo o
piuttosto un prototipo evolutivo.
Migration Strategies
62
Prototype the Target Solution
– Un prototipo esplorativo sarà utile per valutare la
fattibilità di una scelta tecnica.
Deve essere progettato per rispondere a domande che
possono riguardare:
• Questioni tecniche, (esempio: se la nuova piattaforma è in
grado di soddisfare i limiti di prestazioni fissati dal sistema
legacy),
• Questioni di usabilità che richiedono la partecipazione e la
valutazione da parte degli utenti.
Migration Strategies
63
Prototype the Target Solution
- Un prototipo evolutivo, è destinato a, eventualmente,
sostituire un componente del sistema legacy.
La nuova architettura non può più solo sostenere
adeguatamente i servizi del sistema legacy, ma anche
superare le gli ostacoli che limitano le soluzioni del
sistema. Il prototipo deve essere progettato anche
per superare tali limiti.
Migration Strategies
64
Prototype the Target Solution
• Vantaggi:
– Un prototipo può essere costruito velocemente in quanto
non deve implementare tutte le funzionalità del sistema.
– E’ possibile “tagliare” parti del sistema legacy per rendere
avviabile il prototipo.
– Aiuta a capire se la nuova soluzione può funzionare.
• Svantaggi:
– Gli sviluppatori non sono motivati a spendere tempo per
sviluppare i prototipi.
Migration Strategies
65
Always Have a Running Version
• Obiettivo:
Aumentare la fiducia nei cambiamenti grazie a
un regolare rebuild del sistema.
Migration Strategies
66
Always Have a Running Version
• Problematiche:
– Può essere difficile fare la demo di un sistema software in
fase di sviluppo, o di discutere i problemi con gli utenti,
poiché spesso la demo non è stabile.
– L’Integrazione delle modifiche di più versioni del sistema
può risultare molto complessa e lenta.
• Soluzione:
– Instituire un processo di integrazione dei nuovi
cambiamenti e sviluppi quotidianamente.
Migration Strategies
67
Always Have a Running Version
• Suggerimenti:
– Avere a disposizione sia un sw di gestione delle versioni
che di gestione delle configurazioni. (SVN)
– Assicurarsi di avere i regression test delle parti su cui si sta
lavorando.
– Creare un processo per controllare le componenti del
sistema e che esegua i regression Test. Le iterazioni del
processo devono essere più brevi possibili in modo da
consentire cambiamenti che dovranno essere integrati nel
sistema funzionante.
Migration Strategies
68
Always Have a Running Version
• Vantaggi:
– Si ha sempre una versione funzionante che può essere
usata come demo.
– Si ha sempre una versione funzionante su cui avviare i
regression test.
– Si possono validare velocemente le modifiche al sistema.
• Svantaggi:
– Bisogna integrare sempre e continuamente le modifiche.
Migration Strategies
69
Regression Test After Every Change
• Obiettivo:
Aumentare la confidenza essendo sicuri che quello
che funzionava prima funzioni ancora.
Migration Strategies
70
Regression Test After Every Change
• Problematiche:
– In un sistema complesso, anche piccoli cambiamenti
possono avere effetti collaterali, imprevisti. Un
cambiamento apparentemente innocuo può creare
enormi bug, senza che essi vengano immediatamente
scoperti.
• Soluzione:
– Eseguire il test suite ogni volta si pensi di aver raggiunto
uno stato stabile del sistema
Migration Strategies
71
Regression Test After Every Change
• Vantaggi:
– E’ più facile che costruirsi ogni volta una versione
funzionante.
• Svantaggi:
– E’ necessario scrivere i test.
– I sistemi legacy non dispongono di adeguati regression
test. Ci si dovrà aiutare con Grow Your Test Base
Incrementally
Migration Strategies
72
Regression Test After Every Change
• Conclusioni:
– Regression Test After Every Change garantisce che quello
che funzionava prima funziona ancora.
– Se si costruiscono costantemente i test, oltre che scoprire i
vari difetti del software, si otterrà una suite test riusabile
che aumenterà la fiducia nelle modifiche fatte.
Migration Strategies
73
Make a Bridge to the New Town
OBIETTIVO:
Migrare i dati dal legacy system al nuovo sistema, in parallelo mentre
sono entrambi in esecuzione con un bridge tra i due.
PROBLEMA:
Come migrare in modo incrementale i dati dal legacy system al nuovo
sistema mentre entrambi sono in funzione ?
Problema difficile perché:
• Alcune componenti del legacy system potrebbero essere in fase di
sostituzione;
• La sostituzione di componenti critiche è molto rischiosa;
• Durante la migrazione, i dati utilizzati da un legacy devono essere
Migration Strategies
disponibili;
74
Make a Bridge to the New Town
Soluzione: costruire un data bridge per trasferire incrementalmente i dati
dal legacy system al nuovo sistema, in modo automatico quando le nuove
componenti richiedono i dati dalle rispettive componenti del legacy.
Come costruire la soluzione:
• Identificare le componenti del legacy system e del nuovo sistema che
gestiscono gli stessi dati;
• Implementare un data bridge:
– Invisibile al nuovo sistema;
– Responsabile per qualunque conversione di dati;
– Ridireziona le richieste di lettura dal nuovo componente al legacy, se i dati non sono già
migrati.
• Modificare la componente del legacy per ridirezionare le richieste di
scrittura alla nuova componente in modo che i nuovi dati siano aggiornati;
• Quando tutti i dati sono stati trasferiti
rimuovere il bridge e il componente75
Migration Strategies
legacy.
Make a Bridge to the New Town
New System
Component
3: external write
1: read
1.1: read
Legacy System
Component
3.1: external write
Data Bridge
1.2: write
3.2: external write
Data
Store
Richiesta di scrittura dall’esterno (utente o altro sistema).
Richiesta di lettura dal nuovo componente.
Migration Strategies
76
Make a Bridge to the New Town
Vantaggi:
• Iniziare ad utilizzare il nuovo sistema senza aver terminato la fase di
migrazione dei legacy data.
Svantaggi:
• Senza l’esistenza di un mapping chiaro tra i legacy data e i dati del nuovo
sistema, è difficile implementare un bridge
• Una volta che il trasferimento è avvenuto è difficile tornare indietro
• Aumento del overhead generale causato dal bridge
Conclusione
Un bridge tra il vecchio e il nuovo sistema permette agli utenti di iniziare
ad utilizzare il nuovo sistema prima che sia completo; il bridge isola i due
sistemi  architettura del nuovo sistema non è influenzata dal legacy
system.
Relazioni con altri pattern:
Migration Strategies
• Migrate your system incrementally
77
Present the Right Interface
PROBLEMA
Durante il processo di migrazione, il nuovo sistema come accederà ai
servizi del legacy system ?
Problema difficile perché:
• Il nuovo sistema non è ancora completo  deve utilizzare i servizi del
legacy;
• Il legacy non ha le giuste interfacce necessarie al nuovo sistema.
Problema risolvibile
• Non bisogna accedere ai servizi del legacy direttamente.
Migration Strategies
78
Present the Right Interface
Soluzione
• Identificare le astrazioni (interfacce) per il nuovo sistema e usare dei
wrapper per il vecchio sistema in modo da emulare le nuove astrazioni.
• Esempio: libreria grafica in linguaggio procedurale da utilizzare in un
sistema object-oriented.
– Troppo costoso reimplementarla nell’ottica object-oriented.
– Soluzione 1: libreria come una classe utility (static)
– Soluzione 2: creare un modulo wrapper che presenta la giusta
interfaccia object-oriented.
Vantaggi
• Separare il nuovo sistema dai servizi del legacy system fin dall’inizio
usando le giuste astrazioni;
• Ridurre il rischio che la nuova architettura venga influenzata dalla vecchia.
Migration Strategies
79
Present the Right Interface
Svantaggi:
• Le nuove interfacce potrebbero non essere stabili.
• Sbagliare nel creare le giuste astrazioni (wrappare codice procedurale
come utility class)
Conclusione
• Introduce un nuova e più adatta interfaccia per le componenti del legacy
system.
• Scegliere la giusta interfaccia non costringe a pensare in termini di design
del legacy system e permette di considerare approcci alternativi.
Relazioni con altri pattern
• Deprecate Obsolete Interfaces
• Distinguish Public from Published Interface
Migration Strategies
80
Distinguish Public from Published
Interface
OBIETTIVO
• Facilitare lo sviluppo parallelo, distinguendo interfacce published instabili
da interfacce public stabili.
PROBLEMA
• Come permettere la migrazione da interfacce del legacy a interfacce del
nuovo sistema mentre queste ultime sono ancora in fase di sviluppo ?
Problema difficile perché
• Migrazione al nuovo sistema il più presto possibile;
• Non congelare le interfacce delle componenti del nuovo sistema troppo
presto;
• Cambiare le interfacce a un componente che è largamente usato può
rallentare lo sviluppo;
Problema risolvibile
Migration Strategies
• Lo stato delle interfacce può essere
controllato.
81
Distinguish Public from Published
Interface
Soluzione
• Fare una distinzione tra le interfacce
– Public: identificano componenti pronte per essere utilizzate dal resto del sistema;
– Published: identificano componenti che sono ancora instabili per essere utilizzati in
modo definitivo dall’intero sistema, ma posso essere utilizzabili da un sottosistema.
Come costruire la soluzione
• Le interfacce “published” non sono supportate dai linguaggi di
programmazione  utilizzare strategie alternative (convenzione sui
nomi):
– JAVA: dichiararle come protected  public quando diventano stabili;
– C++: dichiarale public o protected e inoltre dichiarare friends le componenti che
possono utilizzarle  public quando diventano stabili e rimuovere la dichiarazione
friends.
Migration Strategies
82
Distinguish Public from Published
Interface
Vantaggi:
• I client che utilizzano interfacce published sono consapevoli che saranno
modificate.
Svantaggi:
• Trasformare un’interfaccia da published a public comporta un overhead
per i client che dovrebbero aggiornarsi alla nuova interfaccia;
• Dubbio: un client dovrebbe usare interfacce non stabili o i servizi del
legacy system ?
Conclusioni
• Quando si crea una nuova interfaccia (Present the right interface), questa
potrebbe non essere stabile, allora bisogna distinguere tra interfacce
published e public. Quando le interfacce diventano stabili vengono
definite public e quelle obsolete eliminate.
Migration Strategies
83
Deprecate Obsolete Interfaces
OBIETTIVO:
Lasciare agli utenti il tempo di reagire ai cambiamenti delle public
interface “etichettando” quelle obsolete come “deprecate”.
PROBLEMA – Come modificare un’interfaccia evitando di
“spiazzare” tutti gli utenti?
Problema Difficoltoso :
- potrebbe provocare perdita di utenti (DA UN LATO);
- lasciare un’interfaccia obsoleta causa problemi di
manutenzione futura (DALL’ALTRO LATO);
- non tutti i cambiamenti sono proficui.
Migration Strategies
84
Deprecate Obsolete Interfaces
LA SOLUZIONE E’ FATTIBILE:
- L’interfaccia vecchia e quella che la deve sostituire possono
coesistere per un periodo di tempo.
QUINDI…
Etichettare la vecchia ed obsoleta interfaccia come “deprecata”
così da segnalare all’utente che verrà certamente rimossa e
sostituita da una migliore nella prossima release.
Migration Strategies
85
Deprecate Obsolete Interfaces
SOLUZIONE:
- Implementare la nuova interfaccia e “deprecare” quella vecchia;
- Deprecare = informare i clienti che l’interfaccia subirà modifiche atte
al miglioramento;
- Valutare per quanto la vecchia interfaccia debba essere usata e se si
possa già eliminare in una prossima release.
NOTA: In Java, il meccanismo di “deprecazione” è una funzionalità:
aggiungendo “@deprecate” nel javadoc si effettua l’operazione citata,
inoltre anche il compilatore genera warning se il codice è compilato con
l’opzione “-deprecate”.
Migration Strategies
86
Deprecate Obsolete Interfaces
ALTRO APPROCCIO:
- Informare gli utenti della deprecazione di interfacce inserendo ciò
nella documentazione;
- Spostare o rinominare il componente deprecato. I clienti possono
continuare ad utilizzare tale componente ma devono adattarsi a
compilarlo ogni volta;
- Rimpiazzare i componenti deprecati con componenti identici ma che
in più generano warning.
Migration Strategies
87
Deprecate Obsolete Interfaces
PRO:
Gli utenti non devono abituarsi istantaneamente ai cambiamenti;
C’è il tempo di adattare la mente ai cambiamenti.
CONS:
Gli utenti sono liberi di ignorare la deprecazione.
DIFFICOLTA’:
E’ difficile rintracciare tutti gli utenti che utilizzano un determinato
componente deprecato;
E’ difficile capire quando deprecare un componente.
BENEFICI:
La deprecazione impone ai progettisti di effettuare una valutazione
sull’impatto dei cambiamenti Migration
che si Strategies
vogliono introdurre.
88
Conserve Familiarity
OBIETTIVO:
Evitare cambiamenti radicali che potrebbero alienare l’utente.
PROBLEMA – Come effettuare una revisione accurata di un
sistema legacy senza interrompere il modo di operare degli utenti
che lo utilizzano per compiere il loro lavoro?
Problema Difficoltoso :
- I sistemi legacy prevedono cambiamenti “importanti”;
- Gli utenti non sono soddisfatti dei sistemi legacy ma li
capiscono bene.
Migration Strategies
89
Conserve Familiarity
LA SOLUZIONE E’ FATTIBILE:
- E’ possibile effettuare una migrazione incrementale verso una nuova
e migliore soluzione.
QUINDI…
Introdurre solo una costante,
cioè un basso numero di cambiamenti
tra una release e la successiva.
Migration Strategies
90
Conserve Familiarity
PRO:
Ogni release non impone dei cambiamenti significativi e
drastici dei modi di lavoro degli utenti (è tutto graduale).
DIFFICOLTA’:
Qualche volta sono necessari dei drastici e radicali
cambiamenti.
CONCETTO CHIAVE:
Troppi cambiamenti tra le release incrementano il rischio di
difetti e decrementano la capacità di adattarsi degli utenti.
Migration Strategies
91
Use Profiler Before Optimizing
OBIETTIVO:
Evitare sforzi di reengineering relativi all’ottimizzazione ed alla verifica
della presenza di colli di bottiglia.
PROBLEMA – Quando di deve effettivamente riscrivere una
porzione di codice che è evidentemente inefficiente?
Problema Difficoltoso :
- nella reingegnerizzazione del software si possono trovare
molti algoritmi semplici ed “ingenui” nel codice legacy;
- può essere difficile prevederne l’impatto sulle performance
e si può perdere tanto tempo nel fare supposizioni;
- il codice ottimizzato è sempre più complicato.
Migration Strategies
92
Use Profiler Before Optimizing
LA SOLUZIONE E’ FATTIBILE:
- Esistono tool che individuano dove potrebbero esserci dei problemi
di performance.
SOLUZIONE:
Prima di ottimizzare una parte di sistema che è chiaramente
inefficiente si deve utilizzare un “profiler” che esprime se essa è un
potenziale collo di bottiglia.
Non ottimizzare nulla fino ad un riscontro (positivo) da parte del
profiler.
Qualora si decidesse di proseguire, creare dei banchmark che
dimostrano i guadagni di prestazione.
Migration Strategies
93
Use Profiler Before Optimizing
PRO:
Nessuno spreco di tempo nell’ottimizzazione delle parti che non
producono significativi miglioramenti di performance.
CONS:
Gli algoritmi “ingenui” sopravvivono comunque a lungo nel sistema.
NOTAZIONI:
Il miglioramento delle performance di una porzione di codice dipende
da quanto tempo il programma rimane in run su quella porzione (questa
informazione è data dal profiler).
Migration Strategies
94
Scarica

Tests: Your Life Insurance!