Il nostro processo di valutazione di un candidato, per essere assunto nel team agile in azienda, comprende una mezz'ora di pair programming (il cosidetto pomodoro).
E' una pratica molto utile, che consiglio vivamente, e permette di capire molto più a fondo le reali capacità di uno sviluppatore. Anche perchè alla fine della fiera, scriverà codice e quindi perchè non valutare come lo scrive?
Riporto qui la dinamica di una sessione di pair la quale ha fatto emergere un aspetto importate, ma spesso trascurato del TDD. Abbiamo scelto come esercizio da sviluppare in TDD Back to the CheckOut.
Ovviamente in un pomodoro è molto difficile da terminare e non è lo scopo del pair. E' molto più utile capire l'approccio seguito e i test che vengono scritti.
Brevemente: l'esercizio consiste nel calcolare il totale di prodotti scannerizzati con il codice a barre. Ogni prodotto ha un suo prezzo e può avere offerte speciali (tipo se ne compri tre 100$ piuttosto di 120$)
Un esempio di listino prezzi:
- Prodotto A 50$. Offerta: 3 A per 120
- Prodotto B 30$. Nessuna offerta
La seguente sequenza: A, A, B, A produce il totale di 150.
Al candidato ho chiesto di scrivere il test più semplice che gli venisse in mente ed il risultato è il seguente:
@Test
public void shouldScanAnItem() {
CheckOut checkOut = new CheckOut();
Item item = new Item("A");
Catalogue catalogue = new Catalogue();
catalogue.add(10, item);
checkOut.scan(item);
assertEquals(1, checkOut.scannedItems());
assertEquals(10, checkOut.total());
}
Il codice è scritto in Java, ma è facilmente comprensibile anche a chi conosce altri linguaggi.
Nel test c'è un errore evidente su cui ritornerò dopo e il candidato non ha visto. Allora gli ho chiesto di scrivere il minor codice possibile affinchè il test passasse ed il risultato è stato:
public class CheckOut {
public int total() {
return 10;
}
public int scannedItems() {
return 1;
}
public void scan(Item item) {
}
}
Il test passa, nonostante l'errore e la discutibile scelta di design del metodo, secondo me non necessario, scannedItems.
Per chi non l'avesse notato la classe Catalogue non è usata.
Tutto questo per dire che se il candidato avesse effettivamente scritto il test più semplice questo errore sarebbe venuto fuori.
Vediamo il primo test che avrei scritto:
@Test
public void theTotalIsZeroWhenNoItemsScanned() throws Exception {
CheckOut checkOut = new CheckOut();
assertEquals(0, checkOut.scannedItems());
assertEquals(0, checkOut.total());
}
A questo punto l'implementazione con il totale fisso dopo la scrittura del secondo test non sarebbe stata sufficiente.
La conclusione di questo post è per dire di non sottovalutare l'importanza del primo test, anche se appare banale, perchè nel design incrementale evita errori che farebbero perdere molto più tempo della scrittura di un test lungo tre righe.