Introduzione
In questo terzo articolo della serie dedicata alla realizzazione di storie utente, presentiamo una serie di tecniche che possiamo utilizzare per scomporre le storie grandi in storie più piccole. Abbiamo già illustrato l’importanza di avere storie utente di dimensione ridotta, e ribadiremo il concetto nel corso dell’articolo.
Quanto riportato di seguito prende spunto da un articolo pubblicato qualche anno fa sul blog di AgileForAll [1], ad opera di Richard Lawrence, in cui venivano “sistematizzati” alcuni pattern utili al processo di suddivisione delle storie utente.
Il tema è piuttosto importante ed è stato affrontato in svariati articoli [2] [3], con tagli diversi ma spesso concordanti su alcuni principi fondamentali a dimostrazione del ruolo cruciale che la suddivisione delle storie riveste nella pratica dei team che adottino processi Agile.
In questi anni, poi, con il collega Stefano Leli [4] di Agile Reloaded, abbiamo realizzato un workshop con il quale — in un contesto di sperimentazione e divertimento tipico delle attività di Serious Gaming — facciamo provare tali tecniche di splitting (“suddivisione”) delle storie che riassumiamo appunto in questo articolo.
Il paradigma INVEST, ancora
Scrivere una buona storia utente è un mestiere tutt’altro che semplice. Una user story deve avere una serie di caratteristiche che ne esprimano il valore per l’utente finale ma anche la fattibilità per il team di sviluppo.
Il pattern che spesso viene citato è l’ormai noto INVEST, le cui iniziali esprimono i principi fondamentali ai quali una buona storia utente dovrebbe ispirarsi. Per chi non avesse mai sentito questa sigla o volesse comunque ripassarla, di seguito è riportata una breve sintesi del significato delle singole parti.
I – Independent
Le storie dovrebbero essere indipendenti in modo che sia possibile modificarne l’ordinamento nel backlog secondo le indicazioni del PO e i suggerimenti del dev team.
N – Negotiable
Durante la pianificazione dello sprint, dev team e PO discutono su cosa mettere in lavorazione. Questa discussione è più efficace se le due parti possono negoziare contenuti e modalità di lavoro, pur nel rispetto delle reciproche responsabilità.
V – Valuable
Ogni storia inserita in lavorazione deve portare valore al prodotto che si sta componendo, ossia deve soddisfare uno o più bisogni di business dell’utente.
E – Estimatable
Le storie devono essere scritte in modo che il dev team possa valutarne l’effort: obiettivo, implicazioni, criteri di accettazione devono poter essere sitimati.
S – Small
Le storie devono essere sufficientemente piccole in modo che la lavorazione non richieda più di qualche giorno per il loro completamento. Se si stima la velocità in punti, le storie utente non dovrebbero superare 1/4 o 1/5 della velocity di sprint.
T – Testable
Ogni storia deve essere presentata in modo che sia dimostrabile a fine sprint e che il risultato soddisfi le richieste del Product Owner. I criteri di accettazione sono molto importanti.
Spezzare le storie
In questo articolo ci concentreremo sulla S di Small, ossia sul come realizzare storie che siano “piccole a sufficienza” affinché possano essere messe in lavorazione in modo ottimale. Nel corso degli anni sono stati messi a punto una serie di schemi utili per suddividere le storie utente,
(splitting patterns) che presenteremo in questo articolo.
Una domanda che spesso viene fatta da chi inizia a occuparsi di raffinamento delle user stories e di splitting è capire quanto piccola debba essere una storia utente, ossia quando sia il caso di applicare un pattern di scomposizione.
La regola del confronto col punteggio di sprint è una buona regola: se si stima la velocità in punti, le storie non dovrebbero superare 1/4 – 1/5 della velocity di sprint. Va anche detto che la grandezza non dovrebbe essere l’unica metrica da prendere in esame, come emergerà dal contenuto e dalla descrizione dei vari pattern che seguono.
Di seguito sono riportati una serie di pattern applicabili in diversi contesti per la scomposizione di una storia grande in diverse più piccole. I vari schemi non sono mutualmente esclusivi, ma anzi possono essere utilizzati in contemporanea sulla stessa storia, così come si possono applicare iterativamente anche sulle storie frutto delle scomposizioni.
Workflow Steps
Spesso capita che una storia rappresenti un intero workflow di un qualche processo. In questo caso, per scomporre la storia, un modo potrebbe essere quello di identificare i vari passi di tale flusso di lavoro e scrivere una storia per ognuno di essi.
Dato che questa soluzione va a discapito della indipendenza delle storie, si cerchi per quando possibile, di creare storie che abbiano comunque un valore in modo che l’utente trovi utile e importante effettuare anche solo uno degli step del processo; per esempio inserire il codice di sicurezza della carta di credito durante un pagamento online non è sufficiente per completare il pagamento, ma è comunque un’operazione importante perché garantisce la sicurezza della transazione.
Storia
Come viaggiatore vorrei poter comprare online un libro in modo da riceverlo a casa automaticamente.
Variante
Vorrei potermi autenticare con le mie credenziali per poi poter comprare.
Variante
Vorrei poter cercare un libro per poterlo aggiungere al carrello della spesa.
Business Rules
Alcune storie mappano processi il cui completamento viene descritto tramite una serie di regole di business. In questo caso si potrebbe pensare di scrivere tante storie, una per ogni business rule.
Storia
Come utente vorrei poter acquistare gli oggetti nel carrello in modo da poterli ricevere a casa.
Variante
Come negoziante vorrei invalidare il carrello se non finalizzato entro 15 min.
Variante
Come negoziante vorrei rifiutare gli ordini provenienti dall’estero.
Tracer Bullet
Ci sono storie che sono difficili da dividere. In questi casi una soluzione potrebbe essere quella di dividere la storia in tante microfunzionalità end–to–end. In questo caso si potrebbe prendere l’interfaccia grafica come guida per “affettare” le storie.
Un errore da evitare in questo caso è quello di seguire una scomposizione orizzontale, seguendo l’organizzazione architetturale — una storia per la parte di front end, una per la logica di business, una per lo strato di persistenza — dato che in questo caso nessuna di queste storie rilascia valore se non in congiunzione con le altre e quindi anche il test e la verifica sono particolarmente difficili.
Data Types
Ci sono storie che contemplano diverse tipologie di dati. Per scomporre la storia si potrebbe provare prima a crearne una che gestisca un primo set di dati e poi procedere con le altre.
Storia
Come utente vorrei poter ricercare i libri presenti a scaffale in modo da visualizzarli.
Variante
Vorrei ricercare per ISBN.
Variante
Vorrei ricercare per autore.
Data Formats
Analogamente al caso precedente, potrebbe essere necessario gestire diversi formati di dati. Anche in questo caso si potrebbe prima procedere a realizzare una storia che gestisca un formato di dato, magari il più semplice, e poi passare a implementare gli altri.
Storia
Come utente vorrei poter scaricare la lista dei miei acquisti per utilizzarli offline.
Variante
Come utente vorrei poter esportare questa lista in formato PDF per poi stamparli.
Variante
Come utente vorrei poter esportare in formato Excel per aggregare dati.
I/O Channels
Se la storia utente prevede più canali o flussi di comunicazione, si potrebbe provare a dividere la storia in modo da gestire alcuni canali prima e aggiungere gli altri in seguito tramite altre storie.
Storia
Come lettore vorrei poter comprare online un libro per poterlo ricevere comodamente a casa.
Variante
Vorrei poterlo comprare tramite sito web.
Variante
Vorrei poterlo comprare tramite smartphone.
Operations
Nel caso la storia preveda più operazioni (p.e.: CRUD), si potrebbe pensare di dividere tali operazioni in altrettante singole storie.
Storia
Come negoziante vorrei poter variare i prodotti presenti a catalogo per gestire il mio negozio online.
Variante
Come negoziante vorrei poter aggiungere un nuovo libro nel catalogo online.
Variante
Come negoziante vorrei poter rimuovere dal catalogo un libro non più in vendita.
Major Effort
A volte una parte della storia rappresenta la maggior parte dell’effort. Per evitare di portarsi in lavorazione tutto il “malloppo”, un buon modo per ridurre il peso della storia potrebbe essere quello di frazionarla in modo da lasciare la parte più corposa all’interno della storia principale e spostare il resto in altre storie meno grandi.
Storia
Come utente vorrei poter pagare il conto con carta di credito per ricevere subito la merce.
Variante
Vorrei poter scegliere altri circuiti bancari di pagamento.
Variante
Vorrei poter pagare con PayPal.
Simple/Complex
Quando la storia risulta essere molto grande, è ricca di aspetti complicati, il suggerimento è quello di iniziare dalla parte più facile, inserendo la parte più semplice in una storia apposita, rimandando la complessità in storie successive. La ragione alla base di questo pattern è che rilasciare la prima parte (semplice) della storia, si potrebbero comunque ricavare informazioni utili per il completamento delle altre, più complesse.
Storia
Come utente vorrei dei metodi di ricerca per poter trovare un testo all’interno di uno dei libri presenti nel catalogo online.
Variante
Vorrei cercare tramite una ricerca semplice.
Variante
Vorrei cercare tramite l’utilizzo di espressioni regolari.
Gradual Interface
Nel caso la storia contempli un’interfaccia complessa, si potrebbe pensare di realizzarne una versione più semplice che possa essere più rapida da implementare, per poi aggiungere complessità alla GUI tramite altre piccole storie.
Storia
Come utente voglio poter visualizzare l’offerta del giorno in modo da poter scegliere cosa comprare a sconto.
Variante
Vorrei vederlo su una pagina web minimale.
Variante
Vorrei vederlo su una pagina web completa di tutte le componenti grafiche del portale.
Variante
Vorrei vederlo su una pagina web responsive su mobile.
Roles/Personas
Se la storia utente contempla più ruoli, si può pensare di rivederla in modo da scomporre il comportamento in funzione del ruolo preso in considerazione.
Storia
Come utente del sistema vorrei poter gestire le ferie in modo da coordinare i vari impegni e allocazioni.
Variante
Come utente di amministrazione vorrei poter disporre di una visione d’insieme delle ferie di tutti i dipendenti per poter coordinare il calendario estivo.
Variante
Come dipendente vorrei richiedere un periodo di ferie autonomamente per potermi organizzare senza dover attendere.
Variante
Come dirigente vorrei approvare le ferie dei miei collaboratori per gestire le presenze.
Configurations
Nel caso la storia utente preveda più configurazioni, si potrebbe pensare di spezzarla in tante sotto-storie in modo da gestire le differenti casistiche. Per configurazione si può intendere un particolare setting (p.e.: lingua) o una determinata modalità di interazione (p.e.: GUI semplificata o massimamente dettagliata).
Scenarios
Una tecnica comunemente applicata nella scrittura dei requisiti tramite il formato degli use case, è quella di identificare i vari scenari e di trattarli in modo differente. Per esempio, tipicamente si approccia prima di tutto lo scenario di successo principale, poi i secondari e infine quelli di errore. In questo caso si potrebbe pensare di scrivere una storia per ognuno dei vari scenari, in modo da dar vita a tante storie, una per ogni casistica.
Storia
Come utente vorrei autenticarmi nel mio account del negozio online per poter consultare lo stato dei miei ordini.
Variante
Vorrei poter recuperare la password se non la ricordo.
Variante
Vorrei poter accedere al sistema tramite autenticazione di Facebook.
Enhance NFR
Se , oltre alla parte di business, la storia contiene dei requisiti non funzionali (NFR, Non Functional Requirements), si potrebbe pensare di estrapolarli in una nuova storia (tecnica) in modo da semplificare la realizzazione della parte di business.
Storia
Come cliente vorrei poter disporre di una interfaccia semplificata per poter acquistare più rapidamente.
Variante senza NFR
Vorrei poter effettuare un ordine.
Variante con aggiunta di NFR
Ogni acquisto dovrebbe essere completato con 5 click.
Variante con aggiunta di NFR
Le pagine relative all’acquisto dovrebbero rispondere entro 1 secondo.
Knowledge Difference
Nel caso in cui alcune parti della storia siano più chiare al team rispetto ad altre, si può dividere la storia in modo da dare precedenza alle parti meglio note e solo in un secondo momento affrontare quelle che hanno bisogno di un maggior studio, o feedback dal campo.
Acceptance Criteria
Questa è una delle tecniche più usate, forse la più usata: nel caso la storia abbia molti criteri di accettazione, un modo molto semplice per semplificare la realizzazione è quello di “staccarne” uno o più di uno e di inserirli in apposite storie dette, in questo caso, “di completamento”.
Storia
Come utente vorrei accedere al mio account per poter consultare lo storico dei miei acquisti.
Variante
Vorrei che l’account sia bloccato dopo tre tentativi errati.
Variante
Vorrei che l’accesso sia negato se è trascorso più di un mese dall’ultimo.
Spike
A volte capita che il team non abbia idea di come procedere per realizzare la storia utente; c’è certamente la convinzione che la storia sia grossa ma, non avendo suggerimenti su come realizzarla, è difficile capire come scomporla o quale pattern applicare.
In questo caso, una soluzione limite potrebbe essere quella di isolare una piccola parte della storia complessiva — solo alcune funzionalità o requisiti — e provare a fare uno spike per chiarire i principali dubbi. Uno spike è un piccolo prototipo per verificare la fattibilità della storia.
Storia
Come utente vorrei poter pagare il conto con Paypal per non dover fornire la mia carta di credito.
Spike 1
Investigare le API di Paypal.
Spike 2
Creare un piccolo esempio di pagamento tramite Paypal.
Uno schema riassuntivo
Abbiamo fornito nei paragrafi precedenti un elenco dei numerosi pattern che è possibile utilizzare per lo story splitting quando sia ncessario spezzare le user stories per ottenere storie più piccole da questa scomposizone.
Nella figura 2 è riportato uno schema che può aiutare nel processo di applicazione dei vari pattern.
Conclusioni
In questo articolo abbiamo presentato una serie di pattern che possono risultare utili per affrontare nel modo migliore il difficile compito della scomposizione di storie utente in storie più piccole. Come detto, i diversi pattern non sono mutualmente esclusivi, ma si prestano ad essere usati anche in combinazione.
Ottenere storie piccole non è sempre semplice — e in qualche caso risulta impegnativo — ma è la chiave per preparare al meglio il lavoro di sviluppo: con gli strumenti concettuali giusti, e un po’ di esperienza, anche questa operazione può essere affrontata in maniera tranquilla.