Abbiamo stimato il costo del nostro progetto, ricevuto l‘ok e allocato il budget. Ora il progetto è partito, e ci troviamo alle prese con la pianificazione giornaliera e settimanale.
La gestione delle stime, nel corso di un progetto di sviluppo presenta caratteristiche diverse dalla valutazione preventiva dei costi, svolta nelle fasi iniziali. Le domande ricorrenti sono: “Quando finirà?” oppure “Quando sarà pronta questa feature?”. In un processo di sviluppo iterativo, le stime vanno di pari passo con la pianificazione e la negoziazione dei requisiti chiave con il cliente. Una tecnica utile per la gestione delle stime in corso d’opera, è quella degli Story Points, proveniente da ambienti “agili” quali XP e Scrum, ma i cui principi sono validi ed applicabili anche in processi RUP-Like.
Il contesto
Nei precedenti articoli abbiamo trattato il metodo degli Use Case Points (“Use Case Points. I parte” MokaByte 123 e “Use Case Points. II parte“, MokaByte 125) per la stima iniziale del costo del progetto. Diligentemente, abbiamo fatto i nostri conti, documentato i motivi delle nostre scelte e presentato il risultato al boss. Il boss, ovviamente, non l’ha presa particolarmente bene: avrebbe preferito sentirsi dire che metà del progetto era già stata implementata per hobby nei ritagli di tempo (non si sa mai, i programmatori sono gente strana) e che bastava agganciare questo e quello e cambiare il colore delle icone. Invece, abbiamo spiegato il perche’ delle nostre valutazioni e mostrato che si trattava del costo complessivo del progetto, comprensivo di bug fixing, installazione, project management, etc. Il boss ha sbottato “Insomma, non possono volerci 2 anni-uomo per questo progetto!”, ma noi non abbiamo calato le braghe e, guardandolo fisso negli occhi, gli abbiamo risposto tendendogli la mano “Scommettiamo?”.
Ora siamo in ballo. Il progetto è partito. Il consumo di caffeina e pizza si è impennato, mentre l’aria si fa più densa per l’acre odore di ascella dei colleghi, e tutti si danno un gran daffare a cercare dei calendari dove poter cerchiare in rosso le date significative.
Chi fa le stime?
Che fare delle stime iniziali di cui siamo così orgogliosi? Probabilmente, la cosa migliore è metterle in un cassetto, riguardarle ogni tanto se i conti non tornano, ma in fondo si tratta di informazioni che non hanno molto valore, durante le fasi di sviluppo. Si tratta di stime aggregate, che servono per calcolare il costo complessivo, mentre ora abbiamo bisogno di numeri che ci permettano di gestire la pianificazione di tutti i giorni e di stabilire il tempo necessario alla realizzazione di una determinata funzionalità. L’altro problema è che le stime iniziali sono state effettuate in presenza di un gran numero di incognite; ora invece la prima cosa da fare è ridurre i margini di incertezza.
Figura 1 – L’area di interesse degli Story Points
Il modo migliore per farlo è rivolgersi ai massimi esperti: gli sviluppatori. Solo chi sviluppa è in grado di sapere che la tecnologia X è in grado di farci risparmiare qualcosa sui tempi di sviluppo, o che a sviluppare la query Y ci vorranno 3 giorni. Imporre le stime fatte da altri agli sviluppatori è la strada più rapida per ritrovarsi con codice scritto in fretta, non testato e men che meno commentato. In altre parole stiamo alimentando la voce “Bug Fixing”.
Se l’incertezza è ancora troppo elevata, ad esempio perche’ stiamo sperimentando nuove tecnologie, è il momento di affrontare le zone grigie. Una soluzione è quella di effettuare un’operazione di esplorazione tecnologica (il cosiddetto spike [3], in terminologia XP) alla quale riservare un tempo finito. Uno sviluppatore potrà quindi dedicare un giorno a fare delle verifiche su una determinata tecnologia, con l’obiettivo di portare risposte che permettano di ridurre l’incertezza tecnologia nelle stime. In altri casi si può ricorrere al parere di uno specialista, non dimenticando che il valore che ci interessa è la stima effettuata da chi dovrà compiere materialmente il lavoro.
In questa fase, la componente “tecnica” assume maggior importanza: vengono compiute delle scelte che impattano i tempi e le modalità di realizzazione. Per la definizione di un piano di lavoro non è più possibile accontentarsi di una valutazione a grana grossa, ma siamo interessati al tempo necessario all’implementazione di una specifica funzionalità. Solo in questo modo infatti potremo giungere ad una pianificazione sufficientemente buona delle iterazioni.
Gestiamo correttamente le informazioni
Abbiamo stabilito un punto fermo: le stime di sviluppo sono responsabilità degli sviluppatori; vediamo come mettere in pratica questo punto fermo.
Boss: “Quanto tempo ti ci vuole per fare questo caso d’uso?”
Sviluppatore: “Ad occhio, … direi un paio di giorni”
Boss: “Ok, allora dico al cliente che per domani è pronto. Grazie”
(porta che si chiude)
Sviluppatore (guardando le lancette dell’orologio, sulle 16:30): “…”
È evidente che la semplice delega delle operazioni di stima agli sviluppatori non è sufficiente, da sola, a garantire una corretta gestione del risultato. Spesso le parole non bastano a definire il corretto significato di una domanda e di una risposta, per quanto semplice. Nel nostro esempio, lo sviluppatore percepisce la domanda “Quanto tempo ti ci vuole per fare questo caso d’uso?” come “Tu, che hai commesso l’errore di alzare lo sguardo al momento sbagliato, in quanto tempo riesci a consegnarmi qualcosa di decente per questo use case?”. Talvolta, la semplice richiesta di un parere sui tempi è interpretato come un’elargizione di stima rispetto al tradizionale “hai 2 giorni di tempo per consegnarmi questa roba!” ed è ricambiata con irragionevole ottimismo.
L’innocente risposta “Ad occhio, … direi un paio di giorni” per lo sviluppatore significa: “potrei sbagliarmi perche’ prima che tu entrassi stavamo commentando la partita di ieri sera e non ho capito neanche esattamente bene a quale caso d’uso tu ti riferisca, comunque se tutto va per il verso giusto e mi concedi una stanza vuota che mi garantisca di non essere interrotto da te e dai colleghi, e misuri il tempo effettivo come nelle partite di basket, dovrei – ripeto, dovrei – riuscire a farcela entro la mattina del terzo giorno da quando comincio.”
Mentre un microfono piazzato nella mente del boss potrebbe captare distintamente questi pensieri “Non ce la farà mai, ci casca sempre, ormai non c’è nemmeno più gusto…”.
Purtroppo, entrambe le parti si sono accordate su una menzogna. Lo sviluppatore mente, perche’ non è in grado di controllare le condizioni al contorno, anzi, spesso ne è vittima. Il boss mente perche’ trasforma una stima espressa in giornate ideali, in una scadenza che è la proiezione di una stima in un universo ideale. Un sogno al quadrato: un po’ come credere che i cerchi nel grano siano le sgommate della slitta di Babbo Natale.
Pensiero laterale
Fare in modo che tutti siano più sinceri e onesti è una strategia ammirevole, ma forse un po’ troppo ambiziosa. Più sensato fare propria la considerazione del Dr. House: “tutti mentono”, e farne tesoro. Come? Cambiando l’unità di misura, sulla quale – in effetti – non c’era accordo (lo sviluppatore parla implicitamente di giornate ideali, mentre il boss le tratta come giornate di calendario), trasformandola da giorni (o giorni uomo) in qualcosa di più impalpabile. Mike Cohn [1] suggerisce l’uso degli Story Points come unità di misura da associare alle User Stories.
Le User Stories rappresentano un’alternativa ai casi d’uso tipica dei processi di sviluppo agili. Come i casi d’uso rappresentano un modo per scomporre un sistema in unità implementative. Da un punto di vista formale sono invece piuttosto differenti: non si tratta di un documento basato su un template, ma in genere di cartoncini su cui è scritta poco più che una frase, che fungerà da promemoria e andrà chiarita e approfondita con il cliente immediatamente prima di passare allo sviluppo.
Figura 2 – Esempi di User Stories: le informazioni sono suffcienti a individuare la feature da sviluppare, ma richiedono un chiarimento
Benche‘ le user stories siano qualcosa di diverso dai casi d’uso utilizzati come unità di misura nei precedenti articoli, dal punto di vista delle stime le differenze non rappresentano un ostacolo insormontabile. Inoltre condividono con i casi d’uso il fatto di rappresentare una scomposizione completa del sistema da implementare. rappresentano comunque una scomposizione del sistema in unità implementative indipendenti. In generale, i principi che andremo ad illustrare possono essere applicati anche ai casi d’uso. Ciò che veramente conta è la presenza di iterazioni ben definite, che possano fungere da punti di misura del software prodotto.
Story Points
Cosa intendiamo per Story Points? Intendiamo una valutazione discreta e relativa della complessità di implementazione di una User Story. Discreta, nel senso che ad ogni User Story (o Use Case) assegnamo un valore intero della nostra unità di misura. Supponendo di avere a che fare con lo sviluppo di un semplice sistema di noleggio (videocassette, DVD o videogiochi), dovremo ottenere qualcosa del tipo:
Tabella 1 – Story points
L’informazione contenuta nella tabella non corrisponde quindi al tempo necessario alla scrittura di un singolo caso d’uso, ma alla complessità relativa di un caso d’uso rispetto agli altri. Stimando con i colleghi i differenti casi d’uso possiamo ad esempio valutare che B è più complesso di A perche’ necessita di schermate aggiuntive, per cui se 3 è il numero di story points associato ad A è ragionevole supporre che me ne servano altrettanti per sviluppare B, mentre C è effettuato su una sola schermata, quindi il tempo necessario all’implementazione sarà minore, rispetto ad A. Il caso più semplice è il rinnovo della tessera (F), in cui presumibilmente andremo a modificare solo la data di scadenza, mentre il riepilogo giornaliero è a detta di tutti il più complesso, perche’ richiede stampe specifiche che andranno raffinate con il cliente. In tutto, un totale di 19 story points.
Questo meccanismo ha alcuni vantaggi evidenti:
- Separa la valutazione della complessità del caso d’uso da implementare dalle condizioni esterne: non quantifico ancora quale sarà il tempo necessario a sviluppare la mia story.
- Rappresenta una valutazione comparata, tra differenti casi d’uso che generalmente risulta più precisa di una stima assoluta. In generale è più facile dire “Mario è più alto di Gianni”, rispetto a “Mario è alto 173 cm” specialmente se non ha nessun termine di paragone vicino (un fenomeno noto in Francia come “effetto Carla Bruni”).
- Permette di evitare la “personalizzazione” delle stime (cioè la differenza nelle stime tra gli sviluppatori veloci e quelli più lenti).
Altro punto importante: le stime sono effettuate dall’intero gruppo di sviluppo. Se questo è molto grande, si può procedere ad una divisione in sottogruppi, considerando come ottimale un gruppo di 5-6 persone. A prima vista questo approccio può sembrare una perdita di tempo rispetto ad assegnare le stime ad un singolo programmatore esperto, tuttavia:
- La necessità di accordarsi su una stima comune permette, anzi, ci obbliga a mettere in luce le contraddizioni tra le opinioni dei componenti del gruppo. Gli sviluppatori possono sovrastimare le aree che non conoscono, ma qualcuno più esperto può indirizzarli nella direzione giusta, evitando di perdere tempo. Stime troppo basse possono invece tralasciare determinate porzioni (i test, il popolamento del DB, etc.) e in questo caso i colleghi possono aiutare ad aggiungere le parti mancanti. In altre parole, la stima condivisa aiuta a chiarire in anticipo dei punti dubbi e può essere considerata come un’attività di design.
- I membri del team sono diversi tra loro per esperienza, capacità, specializzazione, etc. Le stime dello specialista possono non risultare valide se a svolgere il compito non è lo specialista. Una valutazione relativa ed impersonale risulta più affidabile.
Planning poker
Il principale rischio che si corre nel caso di una stima “collegiale” è quello della “riunione fiume”. È bene che la riunione sia adeguatamente “moderata” per evitare che risulti in una perdita di tempo, ad esempio assegnando un tempo massimo alla discussione di ciascun caso d’uso.
Greening formalizza i suggerimenti per la corretta gestione di questa fase nel cosiddetto “planning poker” strutturando le operazioni di stima come una virtuale partita a carte.
Tutti i partecipanti alle operazioni di stima hanno a disposizione un set di carte, con i valori
1,2,3,5,8,(13),(20)
corrispondenti ai primi numeri della sequenza di Fibonacci (il classico esercizio sulla ricorsione, ai tempi dell’università), sia pure arrotondando il 21 a un più pratico 20. Ad ogni giro viene selezionata una User Story e stimata indipendentemente (a carte coperte) da ciascun partecipante. Si girano le carte. In caso di valutazioni discordanti si giustificano rapidamente le proprie stime: quindi si procede a una nuova valutazione. La stima su cui si concorda rappresenta la stima ufficiale. A parte il rischio di farsi beccare dal boss seduti attorno ad un tavolo con 5 carte in mano (ma potete provare la versione online su http://www.planningpoker.com), questo meccanismo presenta alcune caratteristiche interessanti:
- Stimola la discussione sull’implementazione della story, e quindi una valutazione fine delle attività effettivamente da fare. Uno sviluppatore potrebbe, ad esempio. sottostimare una funzionalità perche’ non considera la necessità di modificare il database sottostante e di migrare i dati già esistenti.
- La valutazione a carte coperte permette di evitare che chi parla per primo parli per tutti. Il dissenso è utile, perche’ permette a ciascuno di effettuare una propria valutazione indipendente dal giudizio degli altri, e quindi in definitiva un’analisi più approfondita.
- Ogni “giro” può essere limitato nel tempo. Ad esempio mettendo un tempo massimo di 2 minuti per la valutazione di una singola storia, se la discussione diventa lunga e sterile, si può votare a maggioranza oppure pianificare un’attività di esplorazione.
- La scelta di un insieme finito di valori, su cui concentrare le nostre scelte serve a limitare i tempi di stima ed a mantenere coerente l’insieme delle stime.
L’unità di misura
La scelta dell’unità di misura può essere considerata, per certi versi, un problema secondario: gli Story Points sono un valore decisamente maneggevole e hanno il vantaggio di essere una misura completamente slegata dal calendario. In alcuni casi, però, la loro impalpabilità può complicare la loro introduzione a favore di un’unità di misura meno evanescente. I giorni ideali hanno lo svantaggio di essere scambiati più facilmente per giorni (con tutte le pressioni psicologiche che ne possono derivare), rispetto agli Story Points, e sono più facilmente soggetti a variazioni con l’avanzamento del progetto (mentre vedremo che la misurazione in Story Points richiede meno manutenzione). D’altra parte la contrapposizione tra giorni ideali e giorni reali può servire a mettere in evidenza la presenza di qualche problema ambientale sottovalutato. In generale, la raccomandazione è quella di utilizzare gli Story Points salvo in casi disperati.
Ok, ma quanto ci vuole ad implementare il caso d’uso A?
Se state cercando di spiegare questo meccanismo al vostro boss, dopo qualche minuto comincerete a notare sul suo volto gli inconfondibili segni di impazienza e di agitazione (narici dilatate, mascella serrata, sguardo alla frenetica ricerca di un’arma), come se pensasse che lo stiate prendendo in giro (in effetti, vi odia ancora per quella storia della scommessa, e voi inavvertitamente gli avete parlato di Poker durante le ore lavorative). Quando finalmente uscirà la domanda “Ok, ma quanto ci vuole ad implementare il caso d’uso A?” con sguardo innocente e sincero la vostra risposta sarà “Non lo sappiamo …” (schiumetta bianca che esce dalla bocca del boss) “… ma possiamo provare a indovinare!”
Una volta completata la valutazione dei pesi relativi dei differenti casi d’uso sarà infatti necessario dare una stima abbozzata del tempo necessario all’implementazione del nostro caso d’uso. O, meglio, sarà necessario effettuare un primo tentativo di valutazione di quanti story points possono essere implementati nell’unità di tempo, dal gruppo di sviluppo. Come unità di tempo intendiamo la durata di un’iterazione di sviluppo: generalmente si tratta di 1, 2 o 4 settimane, in maniera dipendente dal processo di sviluppo adottato. Adottare come parametro l’intero gruppo di sviluppo permette di gestire più flessibilmente i carichi di lavoro, e di avere una gestione più realistica degli avanzamenti (oltre che di ridurre il tempo perso in micro management da parte di chi gestisce il progetto). In fin dei conti, per consegnare il progetto è importante che le funzionalità siano implementate, e bene. La verifica della produttività individuale può essere interessante, ma risulta sistematicamente distorta se le metriche non tengono conto delle dinamiche di gruppo. [11]
Considerando nota la durata di un’interazione, ipotizziamo che il gruppo di sviluppo sia in grado di implementare 6 Story Points per iterazione. 6 rappresenta quindi la velocity ipotetica del nostro gruppo. Scegliamo quindi le funzionalità da implementare nella prima iterazione, sulla base della priorità, facendo in modo che la somma risulti <= 6. È bene notare che il valore ipotetico della velocity si applica solo ed unicamente alla prima iterazione. È possibile che il valore ipotizzato si discosti fortemente dalla realtà, ma abbiamo limitato il tempo di validità del valore ipotetico.
Tabella 2 – Story points e iterazioni
Ripartiamo quindi le story sulle iterazioni. La prima iterazione va “abbastanza liscia” 3+3=6. Per la seconda c’è qualche problema in più: ci fa comodo tenere unite Noleggio e Restituzione, ma l’Iscrizione è più pesante e porta il peso a 7. Per il momento va bene così, dobbiamo ancora confermare la velocity, ma prendiamo nota.
Al termine dell’iterazione, si verifica quali funzionalità siano state completate. Completate davvero, non “pronte al 90%”. Quindi si sommano gli Story Points corrispondenti solo ai casi d’uso completati. Non sono ammessi conteggi parziali. Il risultato è la velocity effettiva del nostro gruppo di sviluppo.
Questa potrebbe essere una brutta notizia: su 2 Story da 3 punti ciascuno, ne abbiamo completata solo una, e la nostra velocity effettiva risulta 3 invece che 6. Dovremo adeguare la pianificazione al risultato sperimentale appena ottenuto: schedulando (Severgnini [6] potrebbe uccidermi per questo) meno funzionalità per la prossima iterazione, ripianificando, negoziando con il cliente e così via.
È bene non cedere alla tentazione di allungare le iterazioni, sulla spinta dal “mi manca solo un attimo per finire anche questa”. Le iterazioni devono avere durata fissa: spetterà a noi cercare di fare aumentare la velocity (senza barare). Stando alle nostre informazioni, non abbiamo speranze di completare E nella seconda iterazione, mentre per C e D siamo ancora ottimisti, per cui continuiamo a pianificarli nella seconda iterazione. È inoltre evidente che avremo bisogno di una quarta iterazione. Possiamo fare presente la cosa fin da ora e concordare le necessarie contromisure.
Al termine della seconda iterazione, siamo riusciti a completare B, C, e D. La velocity osservata per la seconda iterazione sarebbe quindi di 7. Un incremento del 130% è poco credibile (ed infatti sappiamo che è originato in buona parte da qualcosa rimasto indietro dall’operazione precedente). Per rimediare a questo soprendente effetto è sufficiente utilizzare il valore medio della velocity osservata.
Figura 3 – L’andamento della velocity osservata, con la stabilizzazione progressiva della velocity media
Un parametro adattivo
La velocity è un valore misurato sperimentalmente, quindi risulta molto più vicino alla realtà delle nostre speculazioni o dichiarazioni di intenti. In effetti, il valore più accurato è la media delle velocity tenute dal gruppo nelle iterazioni precedenti. Come tutte le medie, tende a variare notevolmente nelle prime misurazioni, per poi stabilizzarsi. Con la stabilizzazione del valore, si ridurrà progressivamente anche lo scostamento tra il valore previsto e il valore osservato, aumentando la precisione delle nostre stime man mano che le verifiche sperimentali le ancorano alla realtà. Questo fenomeno di riduzione del margine di errore viene anche definito “riduzione del cono di incertezza” [12].
L’effetto forse più interessante della separazione della velocity dalle stime della complessità è che il meccanismo corregge automaticamente gli errori sistematici di stima: sia quelli “di processo” (p.e. sottostimare i test o le operazioni di integrazione) sia quelli “ambientali” quali le telefonate impreviste, le attività non considerate, e in generale tutto ciò che rende il “giorno reale” diverso dal “giorno ideale”.
La durata delle iterazioni può influire nelle valutazioni iniziali: iterazioni “corte” (p.e.: 1 settimana) rendono più probabile il mancato completamento (“per un soffio”) di uno o più casi d’uso, specialmente nelle prime iterazioni. Quindi anche una velocity zero può essere un risultato imbarazzante ma veritiero. La misurazione successiva arriva comunque abbastanza rapidamente, per cui se il problema è “piccolo” l’uso della velocity media la compensa abbastanza in fretta. Iterazioni più lunghe (p.e.: 4 settimane) possono portare a una maggiore precisione nella prima misurazione, ma questa viene comunque fatta più tardi: se il problema è piccolo la velocity sarebbe già stata “corretta”, se il problema è grosso lo abbiamo individuato più tardi.
Col passare del tempo, il gruppo avrà maggior dimestichezza con le tecnologie utilizzate e sarà in grado di sviluppare in tempi più rapidi, a parità di complessità della funzionalità da implementare. Questa variazione si rifletterà in un aumento della velocity misurata sperimentalmente, mentre non dovrebbe impattare la stima individuale per le funzionalità. In generale, è bene verificare le stime delle funzionalità prima di passare all’implementazione, ma la modifica degli story points corrispondenti va effettuata solo se cambia la complessità relativa agli altri (per esempio, abbiamo verificato che i casi d’uso con le stampe sono più complessi del previsto , oppure abbiamo introdotto un framework che ha semplificato alcune operazioni).
Conclusioni
Stime e pianificazioni sono elementi chiave della gestione dei progetti software. Il meccanismo degli story points permette una gestione basata su parametri sperimentali che separa la valutazione della complessità delle funzionalità da implementare dalla misura del tempo necessario all’implementazione da parte del gruppo di sviluppo e permette una valutazione meno personalizzata e più aderente alla realtà dello stato di avanzamento del progetto.
Riferimenti
[1] Mike Cohn, “Agile Estimating and Planning” Prentice Hall
[2] Mike Cohn, “User Stories Applied”, Prentice Hall
[3] Planning Poker
http://www.planningpoker.com/
[4] S. Rossini, Pratiche di sviluppo del software – V parte: Spike Solution, MokaByte 93, Febbraio 2005
https://www.mokabyte.it/2005/02/software_dev-5.htm
[5] S. Rossini, Processi e metodologie di sviluppo – II parte: le metodologie agili
https://www.mokabyte.it/2004/05/metod-2.htm
[6] B. Severgnini, “L’italiano. Lezioni semiserie”, Rizzoli
[7] K. Schwaber, M. Beedle, “Agile Software Development with SCRUM”, Prentice Hall
[8] K. Beck, “Extreme Programming Explained”, Addison Wesley
[9] K. Beck, M. Fowler, “Planning Extreme Programming” Addison Wesley
[10] J. Spolski, “Evidence Based Scheduling”
http://www.joelonsoftware.com/items/2007/10/26.html
[11] J. Spolski, “The Econ 101 Management Method”
http://www.joelonsoftware.com/items/2006/08/09.html
[12] S. McConnell, “Software Estimation, Demystifying the black art”, Microsoft Press