|
|
|
| << | < | > | >> |Indice
Prefazione XIII
Capitolo 1 Introduzione 1
1.1 Cos'è un computer 1
1.2 Cos'è la programmazione 2
1.3 Anatomia di un computer 3
1.4 Traduzione in codice macchina
di programmi leggibili dagli utenti 8
1.5 Linguaggi di programmazione 10
1.6 Progettazione ed evoluzione
dei linguaggi di programmazione 11
1.7 Acquisire familiarità con il computer 14
1.8 Compilare un programma semplice 17
Sintassi 1.1: un semplice programma 18
1.9 Errori 22
1.10 Il processo di compilazione 24
1.11 Algoritmi 27
Riepilogo 28
Letture 30
Esercizi di ripasso 30
Esercizi di programmazione 32
Capitolo 2 Tipi di dati fondamentali 35
2.1 Tipi di numeri 35
Sintassi 2.1: Istruzione di output 37
Sintassi 2.2: Definizione di variabile 38
Sintassi 2.3: Commenti 43
2.2 Input e output 44
Sintassi 2.4: Istruzione di richiesta
di input 47
2.3 Assegnazione 48
Sintassi 2.5: Assegnazione 50
Sintassi 2.6: Cast 54
2.4 Costanti 56
Sintassi 2.7: Definizione di una costante57
2.5 Aritmetica 59
Sintassi 2.8: Chiamare una funzione 62
2.6 Stringhe 68
2.6.1 Variabili stringa 68
2.6.2 Stringhe secondarie 69
Sintassi 2.9: Chiamare una funzione
membro 69
2.6.3 Concatenazione 70
2.6.4 Output formattato 72
Riepilogo 74
Letture 75
Esercizi di ripasso 75
Esercizi di programmazione 78
Capitolo 3 Oggetti 85
3.1 Costruire oggetti 86
Sintassi 3.1: Costruzione di un oggetto 87
Sintassi 3.2: Definizione di un oggetto 87
3.2 Utilizzare gli oggetti 88
3.3 Oggetti della vita reale 93
3.4 Visualizzare le forme grafiche 96
3.5 Strutture grafiche 97
3.6 Scegliere un sistema di coordinate 104
3.7 Richiedere l'input dalla finestra
di grafica 108
3.8 Confrontare le informazioni visive
e numeriche 109
Riepilogo 113
Letture 114
Esercizi di ripasso 115
Esercizi di programmazione 116
Capitolo 4 Controllo di base del flusso 121
4.1 L'istruzione if 121
Sintassi 4.1: Istruzione if 122
Sintassi 4.2: Istruzione di blocco 123
4.2 L'istruzione if/else 126
Sintassi 4.3: Istruzione if/else 126
4.3 Operatori relazionali 128
4.4 Verificare i dati in input 132
4.5 Cicli semplici 136
Sintassi 4.4: Istruzione while 137
4.6 Elaborare una sequenza di dati in input 140
4.7 Utilizzare le variabili booleane 143
Riepilogo 149
Letture 149
Esercizi di ripasso 150
Esercizi di programmazione 152
Capitolo 5 Funzioni 159
5.1 Funzioni viste come "scatole nere" 159
5.2 Scrivere funzioni 160
Sintassi 5.1: Definizione della funzione162
5.3 Commenti associati alle funzioni 165
5.4 Valori restituiti 168
Sintassi 5.2: Istruzione return 169
5.5 Parametri 171
Sintassi 5.3: Dichiarazione di funzione,
o prototipo 174
5.6 Effetti collaterali 175
5.7 Procedure 176
5.8 Parametri passati per riferimento 177
Sintassi 5.4: Parametro passato
per riferimento 178
5.9 Ambito delle variabili e
variabili globali 180
Sintassi 5.5: Parametri passati per
riferimento dichiarati come costanti 180
5.10 Miglioramento graduale 182
5.11 Dallo pseudocodice al codice 185
5.12 Analisi dettagliate 191
5.13 Requisiti indispensabili 196
Sintassi 5.6: assert 196
Riepilogo 201
Letture 202
Esercizi di ripasso 202
Esercizi di programmazione 206
Capitolo 6 Classi 213
6.1 Scoprire le classi 214
6.2 Interfacce 217
Sintassi 6.1: Definizione della classe 217
6.3 Incapsulamento 220
6.4 Funzioni membro 222
Sintassi 6.2: Definizione della funzione
membro 223
6.5 Costruttori predefiniti 226
Sintassi 6.3: Definizione di un
costruttore 227
6.6 Parametri nei costruttori 230
Sintassi 6.4: Costruttore con elenco di
inizializzazione dei campi233
6.7 Accedere ai campi dati 234
6.8 Confrontare funzioni membro e
funzioni non membro 236
6.9 Compilazione separata 238
Riepilogo 244
Letture 244
Esercizi di ripasso 244
Esercizi di programmazione 246
Capitolo 7 Controllo di flusso avanzato 251
7.1 Alternative multiple 251
7.2 Istruzioni nidificate 259
7.3 Operazioni booleane 263
7.4 La legge di De Morgan 267
7.5 Il ciclo for 269
Sintassi 7.1: Istruzione for 270
7.6 Il ciclo do 275
Sintassi 7.2: Istruzione do/while 276
7.7 Cicli nidificati 280
7.8 Elaborare testo in input 284
7.9 Simulazioni 288
Riepilogo 294
Letture 294
Esercizi di ripasso 294
Esercizi di programmazione 299
Capitolo 8 Test e debugging 305
8.1 Lo unit test 305
8.2 Selezionare i casi di test 310
8.3 Valutare i risultati dei test 311
8.4 Asserzioni 314
8.5 Tracciabilità dell'esecuzione
del programma 315
8.6 Il debugger 316
8.6.1 Utilizzare il debugger 317
8.6.2 Una sessione di debugging
di esempio 319
8.6.3 Spostarsi in un programma 321
8.6.4 Esaminare gli oggetti 323
8.7 Strategie 324
8.7.1 Riprodurre l'errore 324
8.7.2 Dividere e conquistare 325
8.7.3 Conoscere le operazioni che
dovrebbe svolgere il programma 325
8.7.4 Osservare tutti i dettagli 326
8.7.5 Comprendere ciascun errore
prima di correggerlo 326
8.8 Limiti del debugger 326
8.8.1 Funzioni ricorsive 326
8.8.2 Registro delle variabili 327
8.8.3 Errori che spariscono utilizzando
il debugger 327
Riepilogo 329
Letture 330
Esercizi di ripasso 330
Esercizi di programmazione 331
Capitolo 9 Vettori e array 333
9.1 Utilizzare vettori per memorizzare
collezioni di dati 333
Sintassi 9.1: Definizione della
variabile vettoriale 334
9.2 Indici vettoriali 336
Sintassi 9.2: Indice del vettore 336
9.3 Parametri di tipo vettore e vettori
come valori restituiti 343
9.3.1 Rimuovere e inserire elementi 346
9.4 Vettori paralleli 350
9.5 Array 354
9.5.1 Definire e utilizzare gli array 354
Sintassi 9.3: Definizione della variabile
di array 354
9.5.2 Array passati come parametri 356
9.5.3 Array di caratteri 358
9.5.4 Array bidimensionali 361
Sintassi 9.4: Definizione di array
bidimensionali 362
Riepilogo 369
Letture 369
Esercizi di ripasso 369
Esercizi di programmazione 371
Capitolo 10 Puntatori 379
10.1 Puntatori e allocazione della memoria 379
Sintassi 10.1: Espressione new 380
Sintassi 10.2: Definizione di una
variabile puntatore 380
Sintassi 10.3: Deriferimento di un
puntatore 382
10.2 Rilasciare la memoria dinamica 384
Sintassi 10.4: Espressione delete 385
10.3 Utilizzi tipici dei puntatori 388
10.4 Array e puntatori 393
10.5 Puntatori a stringhe di caratteri 399
Riepilogo 403
Esercizi di ripasso 403
Esercizi di programmazione 406
Capitolo 11 Ereditarietà 409
11.1 Classi derivate 409
Sintassi 11.1: Definizione della
classe derivata 410
11.2 Chiamare il costruttore della
classe base 415
Sintassi 11.2: Il costruttore con
l'inizializzatore della classe base 416
11.3 Chiamare le funzioni membro della
classe base 417
11.4 Polimorfismo 423
Sintassi 11.3: Definizione di una
funzione virtuale 426
Riepilogo 433
Esercizi di ripasso 433
Esercizi di programmazione 437
Capitolo 12 Stream 441
12.1 Leggere e scrivere file di testo 441
12.2 La gerarchia di ereditarietà delle
classi di tipo stream 445
12.3 Stream di tipo stringa 448
12.4 Argomenti della riga di comando 451
12.5 Accesso casuale 457
Riepilogo 464
Letture 464
Esercizi di ripasso 465
Esercizi di programmazione 466
Capitolo 13 Design orientato agli oggetti 473
13.1 Il ciclo di vita del software 473
13.2 Schede CRC 478
13.3 Coesione 480
13.4 Coupling 482
13.5 Relazioni tra le classi 484
13.6 Implementare le associazioni 488
13.7 Esempio: visualizzare una fattura 489
13.7.1 Requisiti 490
13.7.2 Schede CRC 490
13.7.3 Diagrammi UML 493
13.7.4 Commenti sulle classi e
sulle funzioni 493
13.7.5 Implementazione 495
13.8 Esempio: un gioco educativo 501
13.8.1 Requisiti 501
13.8.2 Schede CRC 502
13.8.3 Diagrammi UML 505
13.8.4 Definizione dei commenti
di classi e funzioni 506
13.8.5 Implementazione 507
Riepilogo 518
Letture 519
Esercizi di ripasso 519
Esercizi di programmazione 520
Capitolo 14 Ricorsività 523
14.1 I numeri dei triangoli 523
14.2 Permutazioni 527
14.3 Pensare in modo ricorsivo 533
14.4 Funzioni ricorsive ausiliarie 537
14.5 Ricorsività reciproca 538
14.6 Efficienza della ricorsività 542
Riepilogo 549
Esercizi di ripasso 550
Esercizi di programmazione 550
Capitolo 15 Ordinamento e ricerca 555
15.1 Ordinamento per selezione 555
15.2 Analisi dell'algoritmo dell'ordinamento
per selezione 558
15.3 Analisi delle prestazioni dell'algoritmo
di ordinamento per selezione 559
15.4 Ordinamento per unione 561
15.5 Analisi dell'algoritmo di ordinamento
per unione 565
15.6 Algoritmi di ricerca 569
15.7 Ricerca binaria 571
15.8 Cercare e ordinare dati reali 574
Riepilogo 577
Letture 577
Esercizi di ripasso 577
Esercizi di programmazione 580
Capitolo 16 Introduzione alle strutture
di dati 583
16.1 Liste collegate 583
16.2 Implementare le liste collegate 588
16.2.1 Le classi delle liste, dei nodi
e degli iteratori 588
16.2.2 Implementare gli iteratori 589
16.2.3 Implementare l'inserimento e
la cancellazione 591
16.3 Stack e code 600
16.4 Altri contenitori standard 603
16.5 Algoritmi standard 604
Riepilogo 606
Letture 606
Esercizi di ripasso 606
Esercizi di programmazione 607
Capitolo 17 C++ avanzato 611
17.1 Overloading degli operatori 611
17.1.1 Funzioni di definizione
degli operatori 612
Sintassi 17.1: Definizione
dell'overloading dell'operatore 612
17.1.2 Overloading degli operatori
di confronto 613
17.1.3 Input e output 613
17.1.4 Overloading degli operatori di
incremento e decremento 616
17.1.5 Funzioni membro di overload
degli operatori 617
17.2 Gestione automatica della memoria 618
17.2.1 Distruttori 619
Sintassi 17.2: Definizione del
distruttore 619
17.2.2 Overloading dell'operatore
di assegnazione 620
17.2.3 Costruttori di copie 624
17.2.4 Gestione della memoria
per le liste collegate 628
17.3 Modelli 630
Sintassi 17.3: Definizione della classe
modello 632
Sintassi 17.4: Definizione della funzione
membro modello 633
17.4 Classi nidificate e namespace 640
Sintassi 17.5: Dichiarazione della classe
nidificata 641
Sintassi 17.6: Definizione del
namespace 643
Sintassi 17.7: Alias del namespace 643
17.5 Gestione delle eccezioni 644
17.5.1 Segnalare le condizioni
di errore 644
Sintassi 17.8: Generare un'eccezione 645
17.5.2 Rilevare le eccezioni 646
Sintassi 17.9: Blocco try 647
17.5.3 Gli stack 649
17.5.4 Specifiche per le eccezioni 651
Sintassi 17.10: Specifica per le
eccezioni 652
Riepilogo 654
Letture 654
Esercizi di ripasso 654
Esercizi di programmazione 656
Capitolo 18 Interfacce grafiche utente 661
18.1 Il toolkit wxWindows 662
18.2 I frame 663
18.3 Inserire un controllo di testo
nel frame 667
18.4 I menu 670
18.5 Gestire gli eventi 672
18.6 Gestire il layout 675
18.7 Disegnare immagini 679
18.8 Gli eventi del mouse 684
18.9 Le finestre di dialogo 688
18.10 Un esempio completo 691
Riepilogo 702
Esercizi di ripasso 703
Esercizi di programmazione 704
Appendice A Guida di stile di
programmazione in C++ 705
A.l Introduzione 705
A.2 File sorgenti 706
A.3 Funzioni 708
A.4 Variabili locali 709
A.5 Costanti 709
A.6 Classi 710
A.7 Controllo di flusso 710
A.7.1 Istruzione if 710
A.7.2 Istruzione for 711
A.7.3 Controllo di flusso non lineare 711
A.8 Aspetti lessicali 712
A.8.1 Convenzioni di denominazione 712
A.8.2 Rientri e spazi bianchi 712
A.8.3 Parentesi graffe 713
A.8.4 Impaginazione personalizzata 713
Appendice B Riepilogo del linguaggio C++
e delle librerie 715
B.l Riepilogo delle parole chiave 715
B.2 Riepilogo degli operatori 718
B.3 Sequenze di caratteri escape 720
B.4 Tabella del codice ASCII 721
B.5 Librerie di funzioni standard 722
B.6 Contenitori 726
B.7 Algoritmi ed eccezioni 729
B.8 Libreria proposta da questo volume 731
B.9 Libreria wxWindows 733
Glossario 739
Indice analitico 749
|
| << | < | > | >> |Pagina XIIIPrefazioneQuesto libro offre un'introduzione tradizionale alla scienza informatica utilizzando strumenti attuali. Impostata secondo un punto di vista scientifico, l'attività di programmazione viene presentata in modo accessibile, completo e approfondito. La programmazione è il tema centrale della scienza informatica ed è per questo che qui si insegnerà a programmare. Sebbene questo testo abbia un'impostazione tradizionale, utilizza le tecniche più moderne in tre modi.
* Il linguaggio di programmazione adottato è un subset di C++.
Sebbene C++ sia molto lontano dall'essere un linguaggio didattico, il suo
utilizzo nell'insegnamento ha un significato pragmatico. C++ viene ampiamente
utilizzato nell'industria del software. Ambienti di programmazione pratici ed
economici sono disponibili per tutte le piattaforme principali. C++ è abbastanza
esaustivo da riuscire a trasmettere concetti di programmazione. Questo libro
riduce l'utilizzo di costrutti potenzialmente passibili di errore attraverso
l'impiego di funzionalità più attuali dello standard di C++, come i parametri di
riferimento, la libreria di stream, la classe
string
e il modello
vector * Utilizzo immediato degli oggetti. Gli oggetti vengono introdotti in due fasi. Dal Capitolo 2 in avanti i lettori impareranno a utilizzare gli oggetti, in particolare stringhe, stream, istanze delle classi semplici Time ed Employee e alcune funzioni grafiche. I lettori acquisiranno familiarità con i concetti di creazione degli oggetti e di chiamata delle funzioni membro man mano che il libro prosegue lungo un percorso tradizionale, trattando il branching e i cicli, le funzioni e le procedure. Nei Capitoli 5 e 6 i lettori impareranno a implementare le classi e le funzioni membro. * Utilizzo facoltativo delle funzioni grafiche. A molti utenti potrebbe interessare l'approfondimento degli aspetti legati alla grafica. Questo libro include numerosi esercizi in cui la programmazione tradizionale e quella grafica si rafforzano a vicenda. Per farlo viene utilizzata una libreria grafica molto semplice che è disponibile per diverse piattaforme molto diffuse. A differenza delle librerie grafiche tradizionali, questa utilizza gli oggetti in modo molto diretto ed efficace. L'utilizzo di questa libreria è facoltativo. Il Capitolo 8 contiene un'introduzione alla programmazione di interfacce grafiche utente mediante l'impiego di un toolkit open-source (utilizzabile gratuitamente) simile alla libreria Microsoft Foundation Class.
La scelta del linguaggio di programmazione ha un notevole impatto
sull'efficacia didattica di qualsiasi libro che affronti l'argomento. Lo scopo
di questo libro è tuttavia quello di insegnare concetti informatici e non tutti
i dettagli di C++. Questo linguaggio viene utilizzato come strumento per
padroneggiare i fondamenti della scienza informatica.
Impostazione pedagogica Ogni capitolo inizia con una panoramica degli obiettivi trattati e un'introduzione a supporto. I capitoli sono disseminati di cinque tipi di note che aiutano il lettore, chiamate Errore comune, Suggerimento, Consiglio, Approfondimento e Curiosità. Queste note sono segnalate in modo da non interrompere il flusso del materiale principale. Alcune note sono brevi, altre occupano più pagine e hanno lo scopo di rendere più completa e convincente la spiegazione degli argomenti. | << | < | > | >> |Pagina 243Programmazione: arte o scienza? Si discute tanto sul fatto che lo studio dei computer debba essere o meno considerato una scienza. La considerazione che questo ambito di studio venga chiamato scienza informatica non sembra particolarmente significativa; poche persone, con l'eccezione forse di bibliotecari e sociologi, possono ritenere che le scienze bibliografiche e le scienze sociali siano settori scientifici a tutti gli effetti. Una disciplina scientifica si propone l'obiettivo di scoprire determinati concetti fondamentali che rispettino le leggi naturali e si basa sul metodo scientifico: si pongono ipotesi che vengono verificate mediante esperimenti riproducibili da altri operatori del settore. Per esempio, un fisico può sviluppare una sua teoria sulla nascita delle particelle nucleari e il tentativo di confermare o smentire questa teoria può essere condotto mediante esperimenti con l'acceleratore di particelle. Se un esperimento non viene verificato, la teoria è destinata a una morte prematura, come nel caso della ricerca sulla fusione fredda sviluppata nei primi anni '90 nell'Università dello Utah. A dire il vero può capitare anche ai programmatori di eseguire esperimenti. Si possono provare diverse procedure di calcolo per ottenere determinati risultati, oppure si possono configurare diversi sistemi operativi misurando le prestazioni che si ottengono. In ogni caso l'obiettivo principale non ha comunque niente a che vedere con la scoperta di nuove leggi della natura. Alcuni scienziati informatici scoprono l'esistenza di concetti fondamentali. Una categoria di questi risultati afferma per esempio che è impossibile scrivere tipi particolari di programmi, a prescindere dalla potenza del computer utilizzato. Per esempio, è impossibile scrivere un programma che possa leggere due file di programmi C++ qualsiasi e produca un output in grado di stabilire se questi due programmi ottengono sempre risultati identici fra loro. Un programma di questo tipo sarebbe molto comodo per valutare i compiti degli studenti ma nessuno, non importa quanto possa essere bravo, sarà mai in grado di scrivere un programma che possa funzionare correttamente con tutti i file in input. Va aggiunto inoltre che la maggior parte dei programmatori scrive programmi e non si preoccupa di investigare i limiti che il calcolo con il computer presenta. Ci sono persone che considerano la programmazione una specie di arte o maestria. Un programmatore che sappia scrivere in modo elegante codice che sia facile da leggere e funzioni con un ottimo livello di efficienza può effettivamente essere considerato un valido artigiano del settore. Da qui a parlare di arte ce ne corre, dato che un oggetto artistico richiede la presenza di un pubblico in grado di apprezzarne le qualità: in genere il codice di un programma non viene nemmeno visto dall'utente del programma. Ci sono poi quelli che considerano lo studio dei computer una disciplina a carattere ingegneristico. Così come l'ingegneria meccanica si basa su concetti matematici fondamentali di statica, anche per i computer è possibile definire una serie di concetti fondamentali di tipo matematico. Nell'ingegneria meccanica si ritrova comunque qualcosa che va oltre la matematica, per esempio la conoscenza dei materiali e la pianificazione dei progetti; lo stesso si può dire per lo studio dell'informatica. Da un certo punto di vista, lo studio dell'informatica non dispone delle stesse basi presenti in altre discipline ingegneristiche. Non c'è uniformità di vedute rispetto a quello che si deve considerare una condotta professionale nel settore dei computer. A differenza dello scienziato vero e proprio, la cui responsabilità principale è legata alla ricerca della verità, l'ingegnere deve fronteggiare esigenze in conflitto tra loro che fanno riferimento a qualità, sicurezza e costi del proprio lavoro. Le discipline a carattere ingegneristico prevedono la presenza di organismi professionali che stabiliscono per i propri associati una serie di comportamenti standard. Il settore dei computer è relativamente nuovo e in molti casi non si conosce ancora la procedura corretta che permette di raggiungere determinati risultati con la massima efficienza. Tutto ciò rende difficile la definizione di standard professionali. Che cosa si può dedurre da questo ragionamento? In base alla propria esperienza, come è meglio considerare la disciplina informatica: un'arte, un mestiere, una scienza oppure un'attività ingegneristica? | << | < | > | >> |Pagina 47313 Design orientato agli oggettiObiettivi didattici Gli argomenti affrontati in questo capitolo sono: * analisi del ciclo di vita del software; * esame delle classi e delle funzioni membro; * la coesione e il coupling; * metodo della scheda CRC; * comprensione dei diagrammi di classe UML; * utilizzo del design orientato agli oggetti per creare programmi complessi; * studio degli esempi del processo di design orientato agli oggetti. Per implementare un sistema di software con successo, semplice come un lavoro preparatorio o complesso come un sistema di monitoraggio del traffico aereo, è necessario pianificare, progettare e testare. In realtà, per i progetti più ampi, è necessario dedicare molto più tempo alla pianificazione piuttosto che alla stesura del codice e all'esecuzione del test.
Se nel lavoro di sviluppo si trascorre la maggior parte del tempo davanti al
computer a codificare e a correggere gli errori, probabilmente è perché vi si
dedicano troppe ore. Si potrebbe ridurre il tempo complessivo pensando più alla
fase di pianificazione e di design. Questo capitolo esamina come affrontare
questi compiti in modo sistematico.
13.1 Il ciclo di vita del software In questo paragrafo si esaminerà il ciclo di vita del software: le attività che si svolgono tra la fase di ideazione iniziale del programma di software e la fase di ritiro definitivo dal commercio. Molti progettisti di software suddividono il processo di sviluppo nelle cinque fasi seguenti: * analisi * design * implementazione * test * installazione Nella fase di analisi, si decide cosa si ritiene che il progetto debba attuare; non si pensa al dettaglio di come il programma realizzerà i suoi compiti. L'output della fase di analisi è un documento dei requisiti, che descrive nei dettagli ciò che il programma sarà in grado di portare a termine. Una parte di questo documento può essere un manuale utente che spiega il funzionamento del programma affinché l'utente possa trarre i benefici promessi. Un'altra parte imposta i criteri delle prestazioni: quanti input il programma deve essere in grado di gestire e in quanto tempo, o la memoria massima e i requisiti della memorizzazione su disco. Nella fase di design, si sviluppa un progetto per implementare il sistema. Si descrivono le strutture di dettaglio per il problema da risolvere. Se si utilizza il design orientato agli oggetti, si stabilisce quali classi occorrono e le loro funzioni membro più importanti. L'output di questa fase è una descrizione delle classi e delle funzioni membro, contenente diagrammi che mostrano le relazioni tra le classi. Nella fase di inplementazione, si scrive e si compila il codice del programma per implementare le classi e le funzioni membro esaminate nella fase di design. L'output di questa fase è il programma completato. Nella fase di test, si eseguono i collaudi necessari per verificare che il programma funzioni correttamente. L'output di questa fase è un rapporto che descrive i test eseguiti e i loro risultati. Nella fase di installazione, gli utenti installano e utilizzano il programma per lo scopo previsto. Quando si gestisce un grande progetto software, l'organizzazione di queste fasi non è ovvia. Un responsabile deve sapere quando porre fine all'analisi e iniziare il design, quando porre fine alla codifica e iniziare l'esecuzione del test e così via. Nella gestione dei progetti software si istituiscono le procedure formali. Una procedura formale individua le attività e i risultati delle diverse fasi e indica le linee guida di attuazione delle fasi e di passaggio da una all'altra. Quando le procedure di sviluppo formali furono istituite per la prima volta all'inizio degli anni '70, i progettisti dei software si attenevano a un semplicissimo modello visuale di queste fasi. Postulavano che una fase si sarebbe eseguita fino al termine, il suo output si sarebbe riversato sulla fase successiva e quest'ultima sarebbe iniziata. Questo modello viene definito modello a cascata dello sviluppo dei software (Figura 13.1). In un mondo ideale il modello a cascata è affascinante: si immagina cosa fare, si pensa a come farlo, lo si realizza, si verifica di averlo fatto bene e si consegna il prodotto al cliente. Tuttavia se questo modello fosse applicato rigidamente non funzionerebbe. Era molto difficile elaborare una specifica perfetta dei requisiti. Nella fase di design era piuttosto frequente scoprire che i requisiti non erano coerenti o che una loro piccola modifica avrebbe generato un sistema più facile da progettare e più utile per il cliente; tuttavia l'analisi della fase era conclusa e i progettisti non avevano altra scelta: dovevano considerare come validi i requisiti esistenti, gli errori e tutto il resto. Questo problema si ripeteva durante l'implementazione. I progettisti potevano anche credere di risolvere il problema nel modo più efficiente possibile, ma quando il design era effettivamente implementato, il programma creato non si dimostrava così veloce come avevano ipotizzato. La transizione successiva è certamente nota. Quando il programma veniva consegnato al dipartimento di verifica della qualità per l'esecuzione dei test, si scoprivano molti errori che sarebbero stati corretti meglio implementando oppure addirittura riprogettando il programma; tuttavia il modello a cascata non lo consentiva. Infine quando i clienti ricevevano il prodotto ultimato, non ne erano affatto soddisfatti. Anche se essi di solito erano coinvolti nella fase di analisi, spesso non erano certi di quello che gli occorreva. In fin dei conti può essere molto difficile descrivere come si vuole utilizzare un prodotto che non si è mai visto prima. Tuttavia quando i clienti iniziavano a utilizzare il programma, si rendevano conto di cosa avrebbero voluto. Ovviamente era troppo tardi e dovevano tenersi ciò che avevano in mano. Disporre di un livello di iterazione è ovviamente necessario. Deve essere semplicemente presente un meccanismo per affrontare gli errori della fase precedente. Il modello a spirale, proposto da Barry Boehm nel 1988, suddivide il processo di sviluppo in varie fasi (Figura 13.2).
Le fasi iniziali si concentrano sulla costruzione dei
prototipi.
Un prototipo è un piccolo sistema che mostra alcuni aspetti del sistema finale.
Dal momento che i prototipi modellano solo una parte del sistema e non devono
resistere all'uso improprio dei clienti, possono essere implementati
rapidamente. È comune costruire un
prototipo di interfaccia utente
che mostra l'interfaccia utente in azione. Esso offre ai clienti la possibilità
di familiarizzare maggiormente con il sistema e di suggerire i miglioramenti
prima della conclusione dell'analisi.
È possibile costruire altri prototipi per convalidare le interfacce con i
sistemi esterni, per testare le prestazioni e così via. Le lezioni apprese dallo
sviluppo di un prototipo possono essere applicate all'iterazione successiva
della spirale.
Incorporando prove ripetute e riscontri da parte del cliente, una procedura di
sviluppo che segue il modello a spirale ha una possibilità maggiore di generare
un sistema soddisfacente. Tuttavia è presente anche un rischio. Se i progettisti
ritengono di non dover svolgere un buon lavoro perché possono sempre compiere
un'altra iterazione, ci saranno sempre troppe iterazioni e la procedura
richiederà molto tempo prima di giungere al termine.
|