11
Nei primi anni '70 solo poche persone, specialisti nel settore scientifico-
tecnologico, come matematici e fisici, sentono il bisogno di progettare
algoritmi assai complessi capaci di elaborare un grosso quantitativo di dati
sfruttando i calcolatori presenti in quel periodo. In questa fase il
progettista di software è tipicamente una persona in grado di esprimersi in
modo rigoroso e formalizzato, come richiesto dagli elaboratori.
L’applicazione sviluppata non ha necessità di sopravvivere a lungo, in
quanto una volta che sono stati raggiunti i risultati voluti può essere
tranquillamente cestinata. L'arte di concepire software è ancora alla fase
embrionale; tipicamente il progettista coincide con l'utente del software
stesso.
Successivamente si passa ad una fase nella quale gli utenti finali del
prodotto sono tipicamente persone con solide basi tecnologiche distinti
dalla figura del progettista. Già da ora, seppur ancora non perfettamente
definito, il concetto di ingegneria del software (software engineering, SE)
diviene centrale per poter analizzare, progettare ed implementare sistemi
software molto complessi: nascono così le società che producono software
per il mercato, le cosiddette software house. Rispetto alla situazione
iniziale, nella quale prevalevano aspetti di lavoro individuale e creativo (il
software come arte), si passa a una situazione di lavoro di piccoli gruppi
specializzati (il software come artigianato), spesso di alto livello di
professionalità.
Da parte di chi sviluppa del codice per il mercato, inizia una riflessione su
come sia possibile fornire del software di alta qualità e, soprattutto, con un
approccio che permetta di affrontare temi cruciali come l'organizzazione
del processo di lavoro interno all'azienda, il controllo dei costi gestione
delle risorse umane e tecnologiche. Nasce progressivamente l'esigenza che
la produzione di software venga vista come un'industria, nell'accezione
comune che ne diamo: sostanzialmente il lavoro deve essere pianificato e
coordinato.
12
In una visione industriale diviene obbligatorio definire i concetti, e la
terminologia usata: secondo quanto riportato dal Software Engineering
Institute (SEI, http://www.sei.cmu.edu/) l'ingegneria è
l'applicazione sistematica di conoscenza scientifica per la creazione e
costruzione di soluzioni efficaci (anche rispetto ai costi) dei problemi pratici
al servizio del genere umano,
mentre l'ingegneria del software è
una forma di ingegneria che applica i principi dell'informatica e della
matematica per il raggiungimento di una soluzione efficace (anche rispetto
ai costi) a problemi software.
Una definizione di software è
l'insieme di codice, programmi, eventuale documentazione associata, test e
dati relativi all'operatività di un sistema di elaborazione.
Alla definizione di software contribuiscono anche fattori di tipo tecnico e
organizzativo-gestionale. Ciò che distingue l'ingegneria del software da altre
discipline è la complessità di capire, progettare, costruire un frammento di
software. In definitiva, l'ingegneria del software si occupa dello studio dei
processi relativi alla concezione, costruzione, deployment, evoluzione e
utilizzo di prodotti software.
13
2 Il software: processo e prodotto
Come accade per ogni tipo di prodotto, si rende necessario un processo
produttivo che conduca lo sviluppatore dalle primissime fasi, dove si
analizza e studia la fattibilità del progetto, fino alla consegna del prodotto
finale al cliente. I due termini appena usati, processo e prodotto, sono i
concetti chiave dell'ingegneria del software; in assenza di un processo
produttivo di buona fattura ed alta qualità, è impensabile che il prodotto
sia altrettanto buono.
Definiamo prodotto:
l'insieme di tutti gli artifacts che permettono l'utilizzo di un programma da
parte di un utente. È composto da codice, documentazione, prodotti intermedi
quali casi di test, specifiche di progetto, ecc.
processo:
l'insieme organizzato di pratiche (attività) che sovrintendono alla
costruzione del prodotto da parte del team di sviluppo utilizzando metodi,
tecniche, metodologie e strumenti.
Prodotti e processi software sono divenuti particolarmente critici in quanto
tutti i prodotti e servizi della nostra società sono sempre più basati su
tecnologie informatiche.
Il processo si distingue in processo produttivo e processo evolutivo: del
primo abbiamo già accennato, il secondo invece, che viene spesso
trascurato, focalizza lo sforzo su tutte quelle pratiche che vengono dopo il
rilascio del prodotto stesso. Si va dalla risoluzione dei problemi che sono
sorti dopo l'installazione allo studio di nuove soluzioni ed applicazione che
integrano quelle già esistenti. La facilità con cui un software può evolvere
è legato alla sua malleabilità: quanto più è malleabile un prodotto, tanto
più si presta a modifiche anche radicali con il minimo sforzo, ovvero è
14
possibile cambiare il comportamento di un software operando su piccoli
frammenti di codice in un breve lasso di tempo. Viceversa, se il programma
non è malleabile, già capire dove intervenire diviene un problema.
2.1 Fattori di qualità
In tutte le discipline ingegneristiche vi sono dei parametri che permettono
al cliente, ma anche al responsabile dei lavori, di conoscere in ogni istante
e in ogni fase del processo se ciò che sta producendo soddisfa dei requisiti
di qualità. Approfondiamo qui il problema di come misurare la qualità di
un prodotto, ovvero ci domandiamo come e in base a quali parametri possa
essere valutato in termini oggettivi un processo produttivo o un prodotto
software. In linea teorica, lo sforzo dovrebbe essere rivolto a massimizzare
le qualità del prodotto più che del processo, visto che in assenza di vincoli
temporali, economici e tecnologici l'obiettivo finale è appunto di
massimizzare le qualità del software. Questa affermazione, valida
solamente dal punto di vista teorico, viene quotidianamente contraddetta;
si certifica sul campo che un prodotto software di alta qualità è figlio di un
processo software di alta qualità. Detto ciò, è nostra intenzione illustrare
almeno quei fattori di qualità macroscopici che risultano essere abbastanza
indipendenti dal dominio applicativo. Innanzitutto, si distinguono due
categorie di fattori di qualità, denominate:
• black-box - qualità che l'osservatore vede dall'esterno, senza bisogno
di conoscere, analizzare la struttura interna,
• white-box - quelle che richiedono l'osservazione della struttura
interna.
Alle prime possiamo riferirci quando analizziamo il funzionamento, la
quantità di consumo energetico, mentre le seconde alla leggibilità del
codice, alla sua strutturazione. Ai fini del prodotto e della sua
commercializzazione, le black-box (o qualità esterne) sono le più
15
interessanti e auspicate, ma si verifica empiricamente che le interne
implementano (sono un modo per realizzare) le esterne.
Qual è lo scopo di discutere e cercare di definire le qualità del software?
Innanzitutto, quello di fornire un linguaggio comune per gli addetti ai
lavori. Secondariamente, quello di fornire una lista di riferimento che
faccia da guida al progettista nel definire quali obiettivi di qualità deve
raggiungere un certo progetto. Infine quello di poter valutare gli obiettivi
fissati ad inizio progetto.
Affidabilità, correttezza, robustezza, sicurezza e innocuità
Con affidabilità del software intendiamo capire "quando è possibile fidarsi
del software"; cioè, se le funzionalità offerte corrispondono ai requisiti. La
definizione è volutamente informale ed intuitiva, così da permettere al
progettista di valutare quando dei disturbi sono tollerabili o meno. Ad
esempio, se il software di gestione di un aereo ha come malfunzionamento
l'apertura incontrollata dello sportello bagagli, questo è chiaramente
inaffidabile. Se però, da fermo, impiega una frazione in più di tempo
rispetto a quello preventivato per aprire lo sportello, questo può essere
considerato affidabile.
Un concetto definibile in modo preciso è invece quello di correttezza. Un
software è corretto se soddisfa i requisiti per il quale è stato progettato;
viceversa, è scorretto. Si osserva che non necessariamente un software
corretto si comporta in maniera che intuitivamente si ritiene affidabile.
Infatti, l'attributo di correttezza viene riferito a ciò che viene specificato
come requisito, ma purtroppo non sempre i requisiti specificano
esattamente tutto ciò che si ritiene importante.
Di un software si valuta anche la robustezza, ovvero la capacità a
comportarsi in maniera accettabile anche in presenza di situazioni non
specificate nei requisiti. Per specificare questo fattore di qualità, spesso si
adottano altre due categorie: sicurezza, per le applicazioni che gestiscono
16
grossi flussi di dati, e l'innocuità, connessa tipicamente alla gestione di
situazione critiche che coinvolge vite umane e/o di impianti molto costosi.
Prestazioni
Un prodotto software può ritenersi affidabile, corretto e robusto, ma può
risultare scarsamente usabile a causa delle basse prestazioni, intese come
uso inefficiente di alcune importanti risorse, quale il tempo di esecuzione e
la memoria occupata. Diversi sono gli strumenti per misurare le
prestazioni, dal calcolo della complessità fondata su teoremi matematici,
oppure ambienti simulati.
Usabilità
L'usabilità, detta anche amichevolezza, è una qualità molto apprezzata
soprattutto per quelle applicazioni rivolte ad utenti con un basso livello di
competenze informatiche e/o di dominio oppure per le applicazioni
economico-aziendale. Il software deve essere facilmente usabile,
amichevole; l'utente non deve perdere tempo a lottare per capire come
funziona, piuttosto deve rivolgere l'attenzione al problema che vuole
risolvere.
La caratteristica di usabilità è tipica del prodotto più che del processo; essa
è una qualità esterna. Esempi di usabilità: interfaccia-utente, mouse per il
puntamento, desktop di lavoro, ecc. La valutazione se una data
applicazione risulta amichevole è soggettivo; l'obiettivo primario deve
essere quello di soddisfare una platea vasta di utenti.
Verificabilità
La verificabilità consiste nel poter dimostrare che il software possiede le
caratteristiche richieste all'inizio.
17
Manutenibilità
Spesso trascurata, la manutenibilità è la qualità che più di tutte incide sui
costi complessivi di un'applicazione (si stima attorno al 50 – 60 %). È la
fase che succede dopo il rilascio del software. Si distingue in quattro tipi di
manutenzione:
• correttiva - occupa circa il 20% delle risorse e serve per risolvere
eventuali bachi sfuggiti ai test finali prima della consegna al cliente;
• adattativa - occupa anch'essa circa il 20 % delle risorse, necessita
nel caso in cui le specifiche siano modificate in seguito a variazioni
delle condizioni al contorno. Per fornire qualche esempio: modifica
IVA, scaglioni aliquote IRPEF, prezzario farmacologico, ecc;
• perfettiva - oltre il 50%, comprende tutte quelle attività che
migliorano, arricchiscono di nuove funzionalità e levano quelle
obsolete. Il motivo per cui la manutenzione perfettiva incide
pesantemente sui costi è conseguenza della malleabilità del software.
Nulla è più facile da plasmare che il software: ecco perché, piuttosto
che riprogettare ex-novo un'applicazione ogni volta che sorge una
nuova esigenza, si preferisce far evolvere l'applicazione esistente fino
a farle incorporare nuove caratteristiche che le sono richieste;
• preventiva - meno del 10%, il software si deteriora a causa delle
modifiche. In sostanza, consiste in modifiche che rendono più
semplice le correzioni, adattamenti e migliorie; tale processo è
chiamato software re-engineering.
Riusabilità
Qualità fondamentale sia nel processo che nel prodotto, un software si dice
essere riusabile se è un patrimonio indelebile di una azienda che lo può ri-
assemblare e utilizzare in altre applicazioni. Si rende indispensabile della
18
manutenzione preventiva per rendere “consistente” con le specifiche un
software deteriorato.
Comprensibilità
È fondamentale che un software sia comprensibile da chi lo usa ai fini di
rendere semplice un'eventuale modifica. Per ottenere la comprensibilità
del processo è necessaria la visibilità, o trasparenza. Ciò significa che le
regole del comportamento organizzativo e gestionale devono essere
assolutamente chiare, ben comprese e che le persone siano
responsabilizzate. Un principio fondamentale è la modularità: facendo
riferimento al prodotto software, un sistema è modulare se è diviso in parti
che hanno una sostanziale autonomia individuale e una ridotta interazione
con le altre parti, e che possono essere comprese separatamente le une
dalle altre. Idealmente, la comprensibilità diviene massima se i singoli
componenti non hanno alcuna interrelazione: ognuno costituisce un'entità
autonoma e logicamente separata, che può essere compresa separatamente
da ogni altra entità.
Il principio di modularità è una conseguenza del motto latino divide et
impera ed è strettamente correlato al principio di astrazione. Ciascun
componente (ovvero ciascun modulo) può essere compreso e caratterizzato
astraendo da alcuni dettagli che risultano irrilevanti al fine di
comprendere gli altri componenti che fanno parte del sistema.
Interoperabilità
In base al principio di modularità, l'obiettivo è costruire i singoli moduli che
siano indipendenti fra loro, abbiano delle funzionalità univoche e che, dato in
ingresso un predicato I generico, lo processano e generano un qualche
predicato O in uscita.
19
Produttività
Qualità tipica del processo più che del prodotto. Essendo la produzione di
software una attività cosiddetta brain intensive (ad alta intensità di cervello)
risulta difficile da quantificare. La produttività nello sviluppo del software è
difficile da caratterizzare e misurare; tuttora, essa viene usualmente definita in
termini del numero di linee di codice prodotte per unità di tempo, per esempio
facendo riferimento ai giorni. È consuetudine utilizzare come unità di misura il
mese-uomo: un mese-uomo è il lavoro svolto da un uomo in un mese. Questa
misura può essere usata per preventivare i costi e i tempi di sviluppo e
manutenzione di un'applicazione. Un processo che porta a sviluppare un
sistema software per gestire una centrale nucleare, richiede una elevata e
minuziosa cura di molti aspetti che, invece, rischiano di essere trascurati se
l'obiettivo è quello di pensare solamente alla consegna del software. Diverso il
caso di un'applicazione che gestisce gli ordinativi e la situazione del magazzino
di un supermercato: lì non ci sono particolari difficoltà, pertanto si richiede una
elevata produttività al team di sviluppo e programmazione.
Alcune note conclusive
La rassegna appena conclusa mette in evidenza quali fattori di qualità un
processo, ma più marcatamente un prodotto, devono contentare; è altresì
evidente che questa lista (checklist) appare insufficiente per descrivere
delle applicazioni di media complessità. Per ogni dominio applicativo
l'ingegneria del software identifica una serie aggiuntiva e caratterizzante
(magari saranno solo delle specializzazioni delle suddette!) di qualità
proprie del sistema. Di certo ad alto livello di astrazione questa lista mette
in risalto gli aspetti da curare maggiormente, lasciando comunque libertà
di scegliere il grado di accuratezza di ognuna di queste in base al dominio
di applicazione.
20
3 Modelli di ciclo di vita del
software
Abbiamo osservato in precedenza che le prime applicazioni informatiche
erano caratterizzate da una scarsa attenzione ai problemi organizzativi-
gestionali del processo produttivo. Chi produceva software coincideva
spesso con l'utente dell'applicazione; non sviluppava per un cliente o per
un'azienda. Il tipo di processo di sviluppo seguito viene definito code and
fix, ovvero codifica e correggi. Questo primordiale modello di processo
produttivo è tuttora adottato per progettare piccoli software come quelli
commissionati dal titolare di un corso universitario in informatica ai suoi
allievi. Si tratta sostanzialmente di un procedimento iterativo, in cui il
software si adatta progressivamente a ciò che il suo utente-progettista
desidera.
Con il crescere della complessità e criticità delle applicazioni, nonché con il
nascere del mercato del software, questo metodo si dimostra inadatto.
Lavorare per una industria oppure per la pubblica amministrazione
obbliga l'ingegnere del software a predisporre metodi, strumenti, percorsi
di lavoro che siano sufficientemente adatti a supportare la complessità di
tali strutture. Inizia così una riflessione su come potesse essere gestito e
organizzato il processo di produzione di software.
Esistono parecchi modelli di ciclo di vita del processo: la scelta del modello
o paradigma dipende dalla natura del progetto e dell'applicazione, dai
metodi e strumenti che si vogliono utilizzare. Nei paragrafi che seguiranno
descriveremo i principali tipi di cicli di vita; prima però conviene
identificare alcune fasi classiche del processo che si ritroveranno in tutti i
modelli.
21
Analisi e specifica dei requisiti: studio del problema
Questa fase ha come obiettivo lo studio del dominio del problema e dei
requisiti dell'utenza.
Analisi e specifica di progetto: definizione della soluzione (Design).
In questa fase si studia e progetta la soluzione informatica del problema
identificato nella fase precedente.
Sviluppo
La fase di sviluppo ha come scopo la creazione del software vero e proprio
in accordo con le specifiche di progetto.
Testing
La fase di testing ha come scopo la verifica del corretto funzionamento del
software prodotto.
Deployment
La fase di deployment ha come scopo la distribuzione e la gestione del
software presso l'utenza.
Manutenzione
Con manutenzione si intende l'insieme delle attività volte a far evolvere un
prodotto software secondo l'esigenza dell'utenza. In realtà, la fase di
manutenzione è una vera e propria attività di sviluppo che quindi include
tutte le fasi discusse in precedenza.
Per qualunque modello di ciclo di vita scelto risulta determinante il
concetto di specifica. Rimandiamo alla sezione successiva la discussione sul
termine “specifica” e di cosa implica, per ora ci basta sapere che la
"specifica" viene spesso utilizzata per indicare il risultato dell'attività di
analisi (e "specifica" appunto) dei requisiti. Tale fase ha come scopo la
22
raccolta, organizzazione e razionalizzazione dei requisiti dell'utente o, in
altri termini, l'esplorazione dello spazio del problema.
Esistono parecchi modelli di ciclo di vita. È possibile classificarli secondo
quattro famiglie:
1. iterativo - con assenza di organizzazione del processo (code and fix);
2. sequenziale - modello a cascata, RAD, prototipazione usa e getta;
3. evolutivo - prototipazione evolutiva, modello a spirale, incrementale;
4. quarta generazione - generazione automatica del codice partendo
dalla specifica.
La classificazione fatta ricopre un ventaglio ampio di modelli; nel proseguo
esploriamo alcuni rappresentanti che hanno avuto maggiore attenzione.
3.1 Il modello codifica e correggi
Per sviluppare applicazioni in ambito scolastico-universitario, ad esempio i
progetti dei vari corsi di informatica, è sufficiente adottare un modello
iterativo con assenza (o quasi) di organizzazione del processo come il
modello codifica e correggi (code and fix); si tratta di un procedimento
iterativo, in cui il software si adatta progressivamente a ciò che il suo
progettista desidera. Sostanzialmente l'obiettivo è capire
approssimativamente quale sarà la risposta finale del software e di
provare ripetutamente a generare codice e correggere gli errori: se la
complessità è bassa e l'esperienza del programmatore è buona, allora
l'applicazione verrà prodotta in breve tempo. La figura del progettista-
programmatore tipicamente coincide con quella dell'utente finale.
Code and fix non concede molto all'ingegnerizzazione del processo tanto
che risulta applicato in contesti dove il numero di righe di codice da
produrre non oltrepassa le 1400 - 1500. Proprio per l'assenza
23
dell'organizzazione, esso è spesso usato da programmatori autodidatti,
coloro che non hanno alle spalle nessuna idea di cosa significhi fare
dell'analisi, progettazione, programmazione e manutenzione.
Il modello standard di code and fix è mostrato in Figura 1.
Figura 1: Diagramma che mostra il ciclo di vita organizzato secondo il
modello elementare codifica e correggi.
La prima fase è essenzialmente di codifica (code), magari preceduta da
qualche diagramma molto elementare per schematizzare la complessità del
problema ed una primordiale soluzione; successivamente si passa alla fase
di mini test che volge ad accertare se il programma funziona correttamente
e soddisfa i requisiti (quasi certamente non specificati esplicitamente in
qualche documento!). In caso contrario si ritorna a codificare per fissare
(fix) eventuali errori o disturbi. Questa attività è stimata in occupare circa
il 30% delle risorse di tempo e fatica del programmatore. L'ultimo passo
prevede l'uscita nel caso in cui il programma soddisfa i requisiti.
3.2 Il modello a cascata
Il primo modello di ciclo di vita del software strutturato ed organizzato fu
senz'altro il modello a cascata (waterfall model). Chiamato anche modello
sequenziale lineare, suggerisce un approccio sistematico e sequenziale allo
sviluppo del software che inizia al livello del sistema e procede attraverso
l'analisi, la progettazione, la codifica, il collaudo e il supporto. Tale
definizione ha il merito di porre in evidenza le diversità fra il waterfall
model e il code and fix: il principio che lo contraddistingue è la
24
sequenzialità delle fasi costituenti il processo. Ogni fase riceve in input
l'output della precedente, mentre il suo di output risulta l'input della
successiva. Lo schema rigido a cascata implica alti costi qualora risulti
necessario tornare indietro verso fasi già percorse.
Figura 2: Diagramma che mostra il ciclo di vita organizzato secondo il
modello a cascata.
La filosofia sottostante al modello a cascata si intuisce facilmente
osservando la Figura 2: le sei fasi che costituiscono il modello di ciclo di
vita sono l'una in cascata all'altra, senza ritorni all'indietro verso fasi
precedenti.
Anche storicamente, il modello a cascata ha rappresentato un autentico
punto di partenza nel tentativo di fornire delle aree di riferimento di
indagine e degli strumenti necessari per investigarle. Fornisce un'ampia
copertura del processo produttivo fin dall'inizio con l'istituzionalizzazione
dello studio di fattibilità, per concludersi con integrazione e test di sistema.
Studio di fattibilità
Analisi e specifica dei
requisiti
Progettazione
Integrazione e test di
sistema
Programmazione e test di
unità
Manutenzione