The Software House Project

Un'esperienza di laboratorio informatico per la classe terza

di Marcello Missiroli

La presente esperienza di laboratorio è stata svolta all'interno di una classe del terzo anno del corso di Informatica/Abacus durante le ore di Sistemi e Telecomunicazioni; ma con opportune modifiche può essere svolta all'interno delle orse di Informatica oppure in un corso di Liceo Scientifico-Tecnologico.



Obiettivi




Descrizione dell'esperienza

L'origine di questo lavoro nasce dalla necessità di fare toccare con mano ai ragazzi gli aspetti reali del software engineering: da tempo ai ragazzi sono presentate le varie metodologie a disposizione (a cascata, a oggetti, extreme programming, ...) ma senza una esperienza pratica tutto ciò risulta essere soltanto un insieme di vuote parole. Di norma, infatti, un compito di informatica poco differisce da quello di matematica o altre materie:

I problemi legati a questo tipo di approccio sono diversi: nel lavoro di gruppo è sempre un alunno a compiere la maggior parte del lavoro, la fase di analisi e progettazione è spesso ignorata a favore della scrittura del codice, il lavoro degli altri gruppo non è quasi mai visionato da nessuno, la fase di debugging è assente, il codice è spesso mal documentato e via dicendo. In sostanza ci si concentra quasi esclusivamente sulla trasposizione dell'algoritmo in programma


La presente esperienza di laboratorio si basa su assunti per certi versi 'anomali':


Requisiti

Il punto critico dell'esperienza consiste nell'avere a disposizione un po' di ore di laboratorio, idealmente 21-27 ore, ripartite in tre blocchi per le tre fasi necessarie. Le tre fasi possono (e probabilmente devono) essere separate nel tempo.

Il laboratorio dovrà essere dotato di almeno due PC per ogni gruppo, in modo da poter far lavorare due ragazzi per gruppo in tandem.

Per ogni fase, i requisiti cambiano, poiché si procede nelle conoscenze del terzo anno; queste saranno evidenziate fase per fase.

Fase 0: Preparazione (gennaio?)

Identificare il numero di gruppi che avrete a disposizione sulla base della classe, dei PC a disposizione e dei ruoli disponibili (4). Ciò fatto, dovrete scegliere i capigruppo. La scelta va guidata basandovi sopratutto sul merito (abilità di programmazione), sul senso di responsabilità e sulla 'intelligenza sociale' di ogni studente, ma il mix preciso dipende da fattori contingenti. Nel nostro caso furono scelti sette capigruppo.

Durante una normale lezione di teoria, ai ragazzi verrà detto quanto segue:
“Nel corso delle prossime lezioni proveremo a simulare il funzionamento di una software house. Sarete divisi in team operativi di 3-4 persone, ed ogni componente avrà compiti differenziati all'interno dell'obiettivo comune. La parte algoritmica risulterà particolarmente semplice, in quanto si presume che parte del problema sia stata risolta dagli analisti della software house. Il lavoro sarà diviso in tre fasi, al termine di ciascuna delle quali vi sarà una fase di valutazione. Cosa particolarmente importante è il rispetto dei tempi, a prescindere da situazioni che sembrano sempre eccezionali (assenze di un membro di gruppo, perdita del codice, ecc..): il gruppo in questo caso è sempre responsabile nel suo complesso.”

La prima cosa da determinare è la composizione del team; ogni capogruppo dovrà scegliere, in ordine, uno dei componenti del gruppo, tenendo presente i seguenti ruoli:

  1. Programmatore logico/algoritmico

  2. Programmatore di interfaccia

  3. Documentazione e supporto (opzionale)”


Procedete quindi alla costruzione del team. Il metodo consigliato è una variante della costruzione delle squadre di calcio tra ragazzi: il primo capogruppo sceglie un membro della squadra, poi il secondo capogruppo e così via. Quando tutti i gruppi avranno due membri, procedere in ordine inverso: prima l'ultimo capogruppo (che sceglierà in pratica due elementi consecutivamente) e così via all'indietro. Al termine del processo tutti gruppi avranno tre membri. Chi resta fuori, presumibilmente i ragazzi più problematici, saranno assegnati dall'insegnante nel modo che riterrà più opportuno.


Perché operare così? Questo sistema di creazione gruppi permette ai capigruppo di esercitare una certa libertà di scelta, basata sulle preferenze personale e sulle abilità del prescelto, ma, come sul posto di lavoro, non sempre si otterrà il gruppo di lavoro che si preferisce. Come altro effetto, stimola la presa di responsabilità personale, e il 'prestigio' di essere scelto. Si faccia attenzione al 'quarto membro', ruolo piuttosto scomodo: spesso diventa un peso per il gruppo, ma in certi casi le sue funzioni possono portare ordine in un gruppo brillante ma indisciplinato – proprio come nella vita reale.


Fase 1: Primo sviluppo (febbraio?).

Prerequisiti:

I ragazzi dovranno aver appreso le basi di un linguaggio di programmazione (nel nostro caso il C, ma va bene qualsiasi linguaggio procedurale e modulare); in particolare, conoscenza delle modalità di sviluppo tramite file separati (nel caso del C, divisione in *.h e *.c). Conoscenza teorica dei vari modelli di software engineering (in particolare quello a cascata). Cososcenza (teorica) di almento un algoritmo di ordinamento.



Svolgimento:

Durante la prima ora di laboratorio, consegnare a ogni gruppo un foglio con le seguenti richieste

-----------------------------------------------------------------------------------------------------------------


Realizzare un programma che riceva in ingresso N numeri reali e li stampi in modo ordinato. Su richiesta, il programma stamperà anche l'indirizzo di memoria in cui è memorizzato.



Ruoli:

Il Capo Progetto si occuperà di

  1. Coordinare il team e relazionare periodicamente agli Analisti/Docenti

  2. Dirigere la fase di integrazione dei vari moduli

  3. Effettuare i test globali

  4. Produrre il sorgente del modulo principale, quello con il main() definitivo


Il Programmatore Logico si occupa di

  1. Concepire e realizzare l'algoritmo di ordinamento dell'array (con schema)

  2. Realizzare il modulo di calcolo

  3. Realizzare il modulo di test indipendente (non compilato nella versione finale)


Il Programmatore d'Interfaccia si occupa di

  1. Concepire l'interfaccia testuale (poi, grafica) per l'inpute dei dati

  2. Realizzare il modulo di Lettura e Stampa dei dati

  3. Realizzare il modulo di test indipendente (non compilato nella versione finale)



Richieste:

  1. Il codice deve essere compilabile sia tramite compilatore gcc (GNU/Linux) sia tramite compilatore Borland/Windows. Realizzare l'operazione tramite switch di compilazione

  2. Non è possibile utilizzare variabili globali

  3. Ogni modulo deve essere testato e in grado di compilare autonomamente in modalità test; Ciò implica un sorgente per ogni modulo, con eventuale file di intestazione


Produrre:

  1. Il codice sorgente adeguatamente commentato

  2. Eventuale Makefile

  3. Relazione sintetica (1 pagina) che descrive l'algoritmo e le soluzioni adottate; la quantità di memoria usata e altre informazioni


Consegna: 3 settimane (9 ore di laboratorio)



Punti qualificanti:



L'esecuzione del lavoro è fluita tranquillamente, forse troppo tranquillamente: molti gruppi hanno preso il lavoro sottogamba, fraintendendo la facilità dell'algoritmo con la facilità del lavoro nel suo complesso.

La consegna è avvenuta un po' a fatica: molti pensavano che la data di consegna fosse indicativa pi che prescrittiva, per cui alcuni gruppi hanno consegnato lavori parziali. Ciononostante il risultato è stato il seguente



All'epoca non avevamo approntato una griglia di valutazione – grave errore! Ex-post possiamo dire di avere utilizzato qualcosa di simile a questa:


Codice multipiattaforma: 20 punti

Codifica modulare: 20 punti

Test compilbili indipendenti: 20 punti

Codice commentato: 10 punti

Relazione: 10 punti

Interfaccia grafica: 10 punti

Consegna in ritardo: -10 punti (max 20) per ogni giorno di ritardo


In linea di massima è consigliabile avvertire i ragazzi delle modalità di correzione, sia per chiarezza, sia come stimolo.


La qualità media del software prodotto – mediamente - era non eccelsa: ecco il prodotto di due gruppi, che chiameremo gruppo GK e il gruppo GG :


//Gruppo GK (valutazione sufficiente)

#include<stdio.h>
#ifdef dos
#include<conio.h>
#endif


#include"let_cont.h"
#include"let_ele.h"
#include"ele_ord.h"

#define max 100
int main()
{
        float ele[100];
        int i,j,N;
        N=lettcontr(0,100);
        let_ele(ele,N);
        eleord(ele,N);
        printf("\n\t\tElenco ordinato :\n");
        for(i=0;i<N;i++){
        printf("\n\t\t %5.4f  ",ele[i]);
        for(j=0;j<100000000;j++){}         }
#ifdef dos 
getch();
#endif
}

---------------------------------------------------------
//gruppo GG: valutazione gravemente insufficiente

#include<stdio.h>

#include"ordine.h"

#define MAX 1000


void main()

{

int dim,i;

float A[MAX];

visual();

dim=letdim(dim);

letvalo(A[]);

ordine(A[],dim);

stampa(A[]);

}


Per la cronaca, i voti assegnati a questa fase sono stati un 9, un 8 , un 6, due 5, un 4 e un 3. I voti in linea di massima rispettavano le abilità di programmazione del capogruppo, che aveva scelto di delegare poco o nulla agli altri membri del gruppo; ha fatto eccezione un caso in cui il capogruppo, non particolarmente esperto in programmazione, si è affidato alle abilità dei suoi compagni.

Da questi dati, si ritiene opportuno fornire qualche informazione in più al gruppo di lavoro: per esempio, si potrebbe fornire (sotto forma di indicazione, non di obbligo) i prototipi delle funzioni da utilizzare.



Fase 2: Debugging esterno (marzo/aprile?).

Prerequisiti:

Avere svolto un lavoro teorico di spiegazione e classificazione di errori. Uso di un debugger (Borland, gdb, ddd o kdb) in modalità step-by-step. Definizione di test di unità e creazione di batterie di test.

Svolgimento:

Dopo un po' di riposo, il problema viene ripresentato agli alunni, anche se in termini un po' diversi. Ai gruppi viene assegnato un nuovo compito:



La dirigenza della vostra ditta, dopo due settimane di lavoro, ha riassegnato il vostro team sul progetto di un altro team. Il vostro compito è quello di valutare e controllare il il codice prodotto dall'altro gruppo.

Richieste:

  1. Produrre uno o più fogli elettronici che rechino le seguenti indicazioni per ogni file del progetto:

Dovrà essere possibile calcolare il tempo totale necessario per la correzione


  1. Una relazione complessiva che valuti l'aderenza del progetto alle specifiche precedentemente consegnate. In particolare, la dirigenza ha rilevato la carenza in questi campi:

  1. Applicare modifiche al codice in modo che


Consegna: 3 settimane (9 ore di laboratorio)


      1. Richieste:

      1. Consegnare la relazione, il foglio elettronico e tutti i files del progetto modificato in un unico file (g)zippato con il nome <nomecapogruppo>.tgz o .zip




Sarà compito dei docenti assegnare ad ogni gruppo il gruppo da monitorare: in linea di massima il principio è quello del 'testa-coda': i gruppi migliori devono revisionare i gruppi peggiori (in modo da sfruttare le loro potenzialità) e viceversa (in modo da scontrarsi con una migliore impostazione del lavoro e un metodo di lavoro più produttivo). Probabilmente è un approccio che sarebbe applicato nel mondo reale, ma che non occorre applicare in modo rigido: è più importante che ogni gruppo affronti problemi impostati in modo radicalmente diverso dal proprio.


Una delle cose più interessante del lavoro è che ha dato la possibilità ai ragazzi di applicare in prima persona le tecniche elementari di debugging per scoprire l'errore; molti hanno aggiunto qualche commento al codice che ne era privo solo per capire cosa stesse succedendo (nonostante la facilità dell'algoritmo, alcuni programmi erano estremamente contorti, specie nella interfaccia utente).


I prodotti dei gruppi sono risultati estremamente variabili, per tipologia e qualità


Ecco qualche esempio:


Gruppo GG


File dei progressi:

Inf_prog.xls/Aggornamento software house < 24/03/07<< Giliberti Giada

Relaz.txt/Relazione complessiva< 24/03/07<< Giliberti Giada

Corretto/Cartella con file corretti< 24/03/07<< Giliberti Giada

Originale/Cartella on file originali< 24/03/07<< Giliberti Giada

Inf_prog.xls/Aggiornamento file< 12/04/07<< Giliberti Giada

Compilazione programma in Linux< 14/04/07<< Giliberti Giada

Inf_prog.xls/Aggiornamento file< 14/04/07<< Giliberti Giada

Compilazione programma in Windows< 15/04/07<< Giliberti Giada

Inf_prog.xls/Aggiornamento file< 15/04/07<< Giliberti Giada

Relaz.txt/Aggiornamento file< 15/04/07<< Giliberti Giada

Relaz.txt/Ultimo aggionamento del file< 16/04/07<< Giliberti Giada

Guaitoli_00/Consegna della cartella< 16/04/07<< Giliberti Giada




Gruppo GK




Gruppo GC



relazione sul progetto in correzione

a: prof. missiroli, prof. capone

ogg.: relazione progetto in correzione



valutazione complessiva del progetto



Valutando il progetto che ci è stato cosegnato si sono potuti rilevare vari errori sintattici e di interfaccia ma complessivamente nulla che poteva compromettere seriamente il funzionamento del programma.

Il suddetto progetto è stato testato e quindi compilato sotto il sistema operativo “Linux” e man mano che il compilatore “gcc” (GNU) rilevava eventuali errori e/o inprecisioni nella scrittura del codice, si sono corrette e le si sono riporate nel foglio elettronico denominato “CORREZIONE”, consegnato insieme ai file corretti.

Inoltre bisogna sottolineare che nel materiale creato dal gruppo che ha come leader Bui Vittorio, non si è trovato nessun modulo di test che fosse compilabile separatamente.

I cosiddetti file di intestazione o (header file) erano quasi tutti corretti, e con questo si intende dire che per le funzioni in cui essi potevano servire sono stati messi, a parte in quella denominata “LeggiArr.c” che faceva riferimento ad un file header che non era mai stato creato e che quindi si è provveduto subito a fare, riportando poi sempre l’errore nel rispettivo foglio elettronivo sopra elencato.

Per quanto riguarda i file di codice invece, la loro suddivisione è sensata sia dal punto di vista logico, che dal punto di vista più materiale, ossia per quanto riguarda i relativi collegamenti di ogni file alle relative librerie ed eventualmente all’header file.

Si è infine realizzato un “makefile” che permetta la compilazione nei modi richiesti da parte del foglio che ci è stato consegnato.





Anche in questo caso non abbiamo fornito in anticipo i criteri di valutazione che potrebbero essere riassunti come segue.



Relazione e documentazione: 20 punti

Qualità del codice corretto: 15 punti

Aderenza del codice corretto alle specifiche originarie: 30

Moduli test indipendenti: 15

Funzionalità del codice corretto: 10

Correttivi (qualità codice originario, batteria di test): 20 punti

Consegna in ritardo: -10 punti (max 20) per ogni giorno di ritardo



I risultati sono stati in generale soddisfacenti, anche se solo un paio di gruppi hanno effettivamente consegnato codice funzionante e un gruppo non ha consegnato per rivalità interne e reiterate assenze. I livelli di documentazione erano accettabili, anche perché ogni gruppo si è 'inventato' il proprio stile di documentazione, non esistendo una modulista definita.


Un dato piuttosto sconcertante è che un solo gruppo ha prodotto i moduli di test indipendenti (l'idea era di avere un main() compilabile separatamente che testasse un singolo modulo) e nessun gruppo ha prodotto batterie di test, nonostante le spiegazioni teoriche. Molti si sono giustificati con problemi di tempo, ma la facilità del compito fa piuttosto supporre che la cosa sia stata deliberatamente ignorata.


Fase 3: Conclusione del progetto (maggio)


Prerequisiti:

Conoscenza approfondita degli algoritmi di ordinamento. Avere affrontato un pacchetto di interfaccia grafica (grafica elementare borland, pacchetto semigrafico ncurses, o equivalenti). Opzionalmente: un pacchetto di documentazione automatica come doxygen o jdoc.




La dirigenza delle vostra ditta vi ha nuovamente assegnato il lavoro originale, seppur con qualche lieve differenza. I tempi stringono, per cui questa volta occorre produrre il risultato finale: la data di consegna è già stata contrattata con il contraente, e un solo giorno di ritardo comporterà la perdita della commessa.

Purtroppo, la dirigenza della ditta vi chiede di inserire due nuovi punti; uno importante dal punto di vista tecnico, l'altro dal punto di vista del marketing.

Richieste:

  1. Riprendere il codice originale, ma aggiungere un secondo metodo di ordinamento; l'utente dovrà poter scegliere il metodo al momento del lancio.

  2. Migliorare l'interfaccia utente in modo da


Produrre:

  1. Il codice sorgente adeguatamente commentato

  2. Una docu mentazione tecnica separata che spieghi ogni singola funzione del programma

  3. Il Makefile (dovrà essere possibile il test di ogni singola unità)

  4. Un file denominato README che descrive all'utente le istruzioni del programma.


Consegna: 3 settimane (9 ore di laboratorio)





Come si vede, questa volta le funzionalità del progetto hanno un ruolo più decisivo: in questa fase il programma DEVE risultare funzionate, costi quel che costi. Entrano in gioco fattori importanti come il refactoring e le modifiche richieste dal cliente.



L'idea era che, con tutto il lavoro di preparazione e documentazione, questa fase risultasse più semplice. In realtà le cose non sono andate proprio così: poché si era già verso la fine dell'anno (maggio), buona parte degli studenti si erano concentrati sul recupero di alcune materie, altri studenti si erano ritirati. È stato quindi necessario riorganizzare i gruppi (da sette a sei) e ridistribuire i ruoli, cosa che non sempre è stata gradita – ma anche questo potrebbe succedere nella 'vita reale'! Il termine di consegna, su richiesta collettiva della classe, è stato spostato di una settimana in avanti (per un totale di 12 ore di laboratorio).

Forse il questa fase la 'necessità' di consegna è stata sentita un po' troppo, dato che per raggungere il risultato le gerarchie all'interno del gruppo sono saltate e le redini sono state prese da chi era più esperto dal punto di vista di programmazione: i risultati rispecchiano, anche se non sempre, queste caratteristiche.



I criteri di valutazione possono essere riassunti come segue:.

Documentazione e README: 20 punti

Qualità dell'interfaccia utente: 20 punti

Aderenza alle specifiche: 10

Moduli test indipendenti: 10

Funzionalità: 40

Consegna in ritardo: -20 punti (max 40) per ogni giorno di ritardo



I risultati conclusivi sono stati un 9, un 8, due 6 (sarebbe stati migliori, ma consegnati in ritardo), un 5 e un 4,5.

La qualità media del codice era decisamente migliorata, anche se i commenti, ancora, erano decisamente pochi (o nulli come in questo caso):

Gruppo LS

# include<stdio.h>
#ifdef DOS
# include<conio.h>
#endif
#include"leggi.h"
#include"scrivi.h"
#include"bubblesort.h"
#include"insertionsort.h"
#define MAXDIM 100

int main(void){
  int A[MAXDIM],dim,scelta;

  do{
    printf("Inserisci la dimensione dell'array: ");
    scanf("%d",&dim);
  }while(dim<1||dim>MAXDIM);

do{
  printf("Inserisci il tipo di ordinamento: ");
  printf("1- bubblesort");
  printf("2- insertionsort");
  scanf("%d",&scelta);
}while(scelta<1||scelta>2);

  leggi(A,dim);
if(scelta==1)  bubblesort(A,dim);
  else  insertionsort(A,dim);
  scrivi(A,dim);


#ifdef DOS
 getch();
#endif
return 1;
}

Conclusioni e prospettive

L'esperienza nel complesso è risultata stimolante tanto per noi docenti quanto per gli alunni, che si sono trovati ad affrontare sia situazioni simile a quelle che avveranno sul mondo del lavoro, tanto sul piano tecnico quanto su quello sociale.

Contiamo di ripetere l'esperienza anche l'anno venturo, introducendo alcuni correttivi come indicato nel testo.

Sarebbe bello fare qualcosa di simile anche durante il corso del quarto e quinto anno, introducendo nuove metodologie (es: l'extreme programming) e nuovi strumenti tecnici (javadoc, oppure CVS). La la grande quantità di argomenti da affrontare nel corso del 4° anno e la loro difficoltà ci fanno pensare che la cosa, al momento, non sia realistica.

Ci auguriamo che questo testo possa essere di stimolo al vostro lavoro.



prof. Marcello Missiroli (ITIS Leonardo da Vinci, Carpi)



Con l'aiuto di

prof. Sergio Capone (ITP)

Gli alunni della classe III° Ai 2006-07



In allegato troverete tutti i lavori prodotti dagli studenti nelle varie fasi.