Clean coder

Back to basic: TDD (4)

Continua la serie, per piccoli passi.

La storia che implementiamo oggi è la seguente:

Dato un carrello posso sapere il prezzo totale degli articoli presenti.

Da un po’ di analisi emerge che il prezzo degli articoli è una cosa che cambia spesso anche per eventuali promozioni, saldi, ecc…quindi nasce l’esigenza di un servizio che si occupa dato un articolo di restituire il prezzo corrente (se questo non emergesse subito, no prob, si potrà fare refactoring in futuro).

Come al solito partiamo da un test per ragionare un po’. Quello che voglio è che l’oggetto CartItem utilizzi un servizio per sapere il prezzo del’articolo aggiunto, detto in C#:

[Fact]
public void GetTotal_OneItem_ShouldAskToPriceListServiceTheItemPrice()
{
  var priceListService = new Mock<IPriceListService>();
  var cart = new ShoppingCart(priceListService.Object);

  cart.AddItem(99);

  priceListService.Verify(p => p.GetCurrentPriceFor(99));
}

Questo test è diverso da quelli scritti fin’ora. Prima di tutto viene usato un mock object (priceListService) invece del vero oggetto in modo da avere uno unit test nonostante le dipendenze e poi non vengono fatte asserzioni sullo stato ma sulla collaborazione tra l’oggetto CartItem e il servizio.

Questo tipo di test si chiamano test di interazione a differenza di quelli fatti fino ad ora che erano test di stato. I test d’interazione verificano che 2 o più oggetti collaborino in modo corretto chiamando i giusti metodi con i giusti parametri. Nel nostro caso vado a verificare che il metodo GetCurrentPriceFor venga chiamato con il valore 99, se ciò avviene il test passa altrimenti fallisce. Non mi interessa lo stato dell’oggetto CartItem tant’è che non faccio alcuna asserzione su di esso.

La cosa interessante è che nel test sopra sto introducendo una nuova classe della quale vado a definire la competenza e parte dell’interfaccia ma non mi occupo dell’implementazione che demando in un secondo momento.

Il test è definito quindi posso passare alla fase rossa. Per compilare aggiunto al costruttore di ShoppingCart il parametro di tipo IPriceListService, aggiungo l’interfaccia e il test è già rosso.

Il messaggio di errore mi dice che il metodo GetCurrentPriceFor non è stato chiamato correttamente, quindi l’interazione prevista tra ShoppingCart e il servizio non è avvenuta. Per farlo diventare verde aggiungo in fondo al metodo AddItem la seguente riga di codice (_priceListService è l’istanza del servizio passata a ShoppingCart):

_priceListService.GetCurrentPriceFor(itemId);

Il test d’interazione è verde ma la storia non è ancora completa, quello che chiedeva era di esporre il prezzo totale degli articoli del carrello, quindi devo esporre una proprietà che mostri il prezzo calcolato tramite il servizio. Aggiungo un test:

[Fact]
public void GetTotal_OneItem_ShouldSetTheTotalValue()
{
  var priceListService = new Mock<IPriceListService>();
  var cart = new ShoppingCart(priceListService.Object);

  priceListService.Setup(p => p.GetCurrentPriceFor(99)).Returns(100m);
  cart.AddItem(99);

  Assert.Equal(100m, _cart.Total);
}

Questo test sebbene simile al precedente torna a valutare lo stato dell’oggetto indipendentemente dalla collaborazione con il servizio. Ho aggiunto un test perché rispetto al precedente sto testando un’altra cosa sebbene nel contesto della stessa storia.

Da notare che in questo test l’oggetto priceListService funziona da Stub e non da Mock (non verifica la collaborazione ma risponde  con il valore 100 ad ogni chiamata del metodo).

Al momento il test è rosso, quindi modifico il metodo AddItem nel seguente modo:

public void AddItem(int itemId)
{
  CartItem item = _items.SingleOrDefault(i => i.Id == itemId);
  if (item != null)
    item.AddOne();
  else
    _items.Add(new CartItem(itemId));

  Total = _priceListService.GetCurrentPriceFor(itemId);
}

Come vedete ho fatto un piccolo passo, al posto di = avrei potuto scrivere direttamente un +=. Vi invito a non fare passi troppo lunghi e a cercare di soddisfare sempre solo ciò che il test richiede.

Per arrivare all’implementazione finale e completare la storia basterà aggiungere un altro test che aggiunge 2 item e che verifica che il totale sia la somma dei prezzi. Per questo vi rimando al sorgente presente sul repo per non allungare troppo questo post.

Back to basic: TDD (3)

Nei primi 2 step abbiamo introdotto una piccola funzionalità che permette di aggiungere un articolo al carrello. Continuiamo sullo stesso tema introducendo la seguente funzionalità:

Quando aggiungo 2 item uguali, deve aumentare la quantità dell’item.

Nello step 2 abbiamo gestito l’aggiunta dello stesso articolo per 2 volte oggi gestiamo la quantità e questo ci porta alla creazione di una nuova classe che rappresenta l’articolo aggiunto.
Proviamo a scrivere un test per decidere l’interfaccia che vogliamo usare e come vogliamo operare:

 [Fact]
public void AddSameItemTwice_TheItemQuantityShouldBe2()
{
  var cart = new ShoppingCart();
  cart.AddItem(new CartItem(99));
  cart.AddItem(new CartItem(99));
  Assert.Equal(2, cart.Items[0].Quantity);
}

Questa implementazione non mi piace molto perché ci costringe a sapere dell’esistenza della classe CartItem che al momento non serve se non per gestire la quantità. Inoltre è meglio non esporre pubblicamente la lista dei CartItem altrimenti si potrebbero aggiungere item senza passare dal metodo AddItem o si potrebbero fare operazioni non consentite.

Quindi modifico il test per nascondere l’esistenza di CartItem e per esporlo sotto forma di IEnumerable cosi che la collezione non sia modificabile ma sia in sola lettura.

[Fact]
public void AddSameItemTwice_TheItemQuantityShouldBe2()
{
  var cart = new ShoppingCart();
  cart.AddItem(99);
  cart.AddItem(99);
  Assert.Equal(2, cart.Items.ElementAt(0).Quantity);
}

In questo modo la creazione degli oggetti CartItem è demandato all’interno della classe ShoppingCart (che diventerà molto probabilmente l’aggregate root…ne parleremo più avanti).
Una possibile implementazione è la seguente:

public class ShoppingCart
{
  private readonly List<CartItem> _items;

  public ShoppingCart()
  {
    _items = new List<CartItem>();
  }

  public IEnumerable<CarItem> Items
  {
    get { return new ReadOnlyCollection<CartItem>(_items); }
  }

  public int ItemCount { get { return _items.Count; } }

  public void AddItem(int itemId)
  {
    CartItem item = _items.SingleOrDefault(i =&gt; i.Id == itemId);
    if (item != null)
    {
      item.Quantity++;
    }
    else
    {
      item = new CartItem(itemId);
      item.Quantity = 1;
      _items.Add(item);
    }
  }
}

public class CartItem
{
  public int Id { get; private set; }
  public int Quantity { get; set; }

  public CartItem(int id)
  {
    Id = id;
  }
}

Con questa implementazione i test diventano tutti verdi.
Dedichiamoci al refactoring che questa volta serve.
Non mi piace inoltre il fatto di dover impostare nel metodo AddItem il valore di Quantity a 1, quindi sposto la definizione della quatità sull’oggetto CartItem. Non mi piace neppure che Quantity sia esposto in scrittura, quindi aggiungo un metodo AddOne:

public void AddItem(int itemId)
{
  CartItem item = _items.SingleOrDefault(i => i.Id == itemId);
  if (item != null)
  {
    item.AddOne();
  }
  else
  {
    _items.Add(new CartItem(itemId));
  }
}

mentre la class CartItem:

public class CartItem
{
  public int Id { get; private set; }
  public int Quantity { get; private set; }

  public CartItem(int id)
  {
    Id = id;
    Quantity = 1;
  }

  public void AddOne()
  {
    Quantity++;
  }
}

Così le cose sono un po’ meglio anche se, si potrebbe provare ad eliminare l’if nel metodo AddItem, ma per ora ci tappiamo il naso e continuiamo, vediamo cosa succede.

Un mese di pomodoro

Da circa un mese in CodicePlastico abbiamo deciso di adottare la tecnica del pomodoro come strumento per misurare la durata delle nostre attività.
La sua introduzione è nata dall’esigenza di creare dei dati storici di misurazione dei tempi  di un progetto e dal tentativo di ridurre le interruzioni sia interne al team che esterne.

Cosi abbiamo deciso di provare seriamente per un mese la tecnica del pomodoro per ogni attività. La mattina, arrivati in ufficio, ognuno di noi compila il proprio elenco dei task che intende fare durante la giornata e per ogni attività stima quanti pomodori impiegherà a completarla. Quando tutti sono pronti si fa partire il pomodoro. Abbiamo deciso di utilizzare un pomodoro unico per tutto il team così da poter sfruttare le pause (sincronizzate) per eventuali richieste di informazioni o anche solo per scambiare due parole.

Com’è andato questo mese?

Continua a leggere…

Back to basic: TDD (2)

Andiamo ancora piano piano…nel post introduttivo avevo evidenziato alcuni benefici del TDD mettendo in risalto il fatto che ti obbliga a pensare e ad essere sicuro di aver capito cosa vuole il committente. Di solito alla fine di ogni test mi chiedo se la funzionalità è davvero completa e se ci sono casi limite che vanno gestiti e in tal caso aggiungo altri test per capire come comportarmi in questi casi.

Tornando al codice della puntata precedente, quello che mi viene da chiedere al product owner è : cosa succede se aggiungo lo stesso item più volte? Naturalmente se il problema è emerso in fase di analisi so già come procedere altrimenti mi fermo e chiedo delucidazioni.

[nda: ho visto che i vari siti di ecommerce si comportano in modo diverso, per alcuni il numero di item nel carrello è il numero di prodotti univoci per altri è il numero di articoli presenti.]

Continua a leggere…

Back to basic: il contesto e il primo test

Per partire con la serie di post sull’applicazione del TDD dobbiamo prima identificare un contesto che sia abbastanza semplice da capire ma anche abbastanza complesso da implementare.

Quello a cui ho pensato è un’applicazione di e-commerce, alla amazon (con molta fantasia) e vorrei partire proprio dalla gestione del carrello, credo sia capitato a tutti di fare almeno un acquisto online e quindi il dominio dovrebbe essere noto.

Alcuni disclaimer: non voglio implementare un’intera applicazione di ecommerce, e, almeno per ora, non voglio tirare in ballo la UI, frameworks, persistenza ecc….quindi sebbene le storie per essere completate necessiterebbero di tutta la filiera che va dalla UI fino al database (nel caso si decidesse di usare un db) farò delle enormi semplificazioni e mi limiterò all’implementazione del domain model. Se poi ci sarà la voglia di continuare in futuro monteremo una UI adatta alle operazioni implementate.

Iniziamo piano, a piccoli passi e la prima storia che andremo ad implementare è un semplice punto di partenza, il minimo per avere un qualcosa su cui ragionare, aggiungeremo successivamente funzionalità più avanzate.

Come utente che sta navigando sul sito posso aggiungere un articolo nel carrello

Partiamo con la scrittura del primo test:

[Fact]
public void AddItem_TheItemIsNotYetInTheBasket_ShouldAddItToTheBasket()
{
  var cart = new ShoppingCart();
  cart.AddItem(99);
  Assert.Equal(1, cart.ItemCount);
}

Continua a leggere…

Back to Basic: TDD

Nonostante parlo di TDD da anni, e alcuni cominciano anche ad annoiarsi, ancora oggi mi rendo conto che è una pratica che non è molto utilizzata e apprezzata come meriterebbe, molti ne parlano, ma pochi la usano.

Sicuramente la sua difficoltà principale è nell’imparare a farlo con profitto, e in quella sensazione che all’inizio sia come programmare con il freno tirato, sai esattamente dove vuoi arrivare ma il fatto di dover scrivere i test rallenta le operazioni. Se siete in questo stato dovete fare ancora un po’ di strada, quel “sapere esattamente dove arrivare” è probabilmente sbagliato e il TDD dovrebbe servire a scoprire dove realmente dovete arrivare.

In questo post voglio riassumere quello che secondo me il TDD insegna.

Continua a leggere…

Perchè UGIALT.net ha chiuso?

Sabato 21 gennaio si è tenuta l’ultima ugialt.net conference, ultima nel senso che non ce ne saranno altre. Basta. Finito. Chiuso.

C’è un filo di dispiacere come per ogni cosa che finisce ma io, Simone e Claudio crediamo che sia stata la cosa più naturale da fare.

UgiALT.net è nata nel 2008, ricordo che nella prima conf eravamo circa una dozzina, Simone ci spiegava il nuovo ASP.NET MVC e Antonio ci parlava di metriche del codice, pochi ma molto attivi e con interessanti discussioni.

Continua a leggere…

Posted in .NET, C# | 6 comments

Professionisti del web: ecco cosa abbiamo fatto noi

Il post sui pagamenti ha fatto un po’ di rumore ed era quello che volevo, i pensieri che ho raccontato sono il sunto di mesi di osservazioni e di situazioni che sono peggiorate col tempo. Verso la fine dello scorso anno abbiamo preso alcuni provvedimenti che vorrei condividere con voi a partire dai contratti.

La prima cosa che abbiamo fatto è stato contattare un avvocato per formalizzare i nostri contratti. Sono più di 5 anni che lavoro come freelance/imprenditore e i miei rapporti con i clienti sono sempre stati regolati da offerte scritte di nostro pugno che spesso non venivano neppure firmate dal cliente. Quindi si basava tutto sulla parola di gentiluomini…e oggi ce ne sono pochi. A ottobre abbiamo contattato un avvocato per capire se c’erano margini di miglioramento. Ci ha ribaltato! Abbiamo fatto 2 o 3 incontri, gli abbiamo spiegato il tipo di attività che facciamo e i problemi ai quali andiamo incontro. Nel giro di poche settimane ci ha preparato una serie di documentazione che ad ogni offerta va allegata a quella che noi chiamiamo documento tecnico. Sono parecchie pagine, condizioni generali, particolari, clausole, ecc…scritte in legalese, e che il cliente deve firmare e mandarci via fax (no email, l’email, purtroppo in italia non ha valore legale) per accettare il tutto. Se anche voi volete rivolgervi ad un avvocato (cosa che consiglio) assicuratevi che abbia un minimo di competenza nel settore informatico altrimenti non sarà facile spiegare cosa fate e cosa vendete.

Continua a leggere…

Posted in Personal | 3 comments

Professionisti del web…ribellatevi!

Il 2011 è stato un anno particolare: la crisi, la situazione europea, il cambio di governo in Italia hanno mosso le coscienze dei cittadini che sembrano aver iniziato un percorso verso l’acquisizione di un nuovo senso civico (io ci voglio credere :-) )

Da più fonti però si capisce che le cose non vanno benissimo, alcuni fatti.

  • Ha fatto scalpore, ma non abbastanza, la notizia del suicidio dell’imprenditore veneto che non riusciva a riscuotere i crediti per 200k euro.
  • Si è parlato molto su twitter di questo post in cui noi italiani siamo dipinti come eroi perché riusciamo a sopportare ritardi enormi nei pagamenti, e nonostante questo ce la facciamo (ma non sempre come abbiamo visto).
  • Cris ieri su twitter ha scritto: “sono indeciso se cambiare la mia mission in “banca”, visto che sto continuando ad anticipare lavoro (quindi soldi) ai miei clienti. #shit
  • In CodicePlastico abbiamo chiuso un buon 2011 dal punto di vista del fatturato ma circa il 40% lo dobbiamo ancora incassare.

A me tutto questo fa molto incazzare, il nostro lavoro è principalmente di tipo intellettuale, fortunatamente non dobbiamo investire soldi in macchinari costosi ma questo non vuol dire che non c’è un’investimento alle spalle. Per poter fare una consulenza su ASP.NET MVC devo passare giornate a studiare, provare, formarmi, tutto tempo che *investo* per poi potermi vendere come consulente alle aziende che ne hanno bisogno. E siccome il mio cliente ottiene valore immediato dalla mia consulenza, io voglio essere pagato immediatamente.

Il proposito per il 2012 che io faccio, ma che vorrei che tutti i professionisti del web facciano, è quello di non concedere termini di pagamento lunghi e lasciar perdere i clienti che vogliono pagare a più di 30 giorni. Io nelle prossime settimane, abbandonerò alcuni clienti che seppur validi, hanno tempi di pagamento a 60 o 120 giorni. Lo faccio per me stesso e invito anche voi a farlo, e più siamo ad imporci più la qualità del nostro lavoro può migliorare.

Per chi non è ancora convinto di quello che ho scritto lo invito a guardare questo video dal titolo esemplare: Fuck you, pay me.

Lascio infine un paio di link sempre sul tema pagamenti, ritardi e pigrizia di Francesco Fullone: uno e due.

Le cose possono cambiare.

Uno sguardo sul mio 2011 da programmatore

Come ogni anno questo è un periodo di bilanci sull’anno trascorso e di propositi per quello nuovo. Oggi sono andato a rileggermi la lista dei todo che a fine 2010 avevo scritto per il nuovo anno e posso dire con orgoglio che ho fatto quasi tutto quello che mi ero ripromesso di fare.

La lista conteneva MongoDb, un nuovo linguaggio di programmazione e partecipare ad un progetto open source.

MongoDb l’ho usato in un paio di piccoli progetti uno in C# e uno in RubyOnRails, in entrambi i casi ho amato la sua immediatezza e libertà nello schema dei dati, devo ancora capire e ragionare su come va modellato l’uso delle collezioni, degli embedded documents e delle relazioni, sono agli inizi, lo strumento è molto promettente (soprattutto in ottica DDD) ma come per tutti i db no-sql vanno affrontati i problemi derivanti da una mentalità relazionale.

Il nuovo linguaggio di programmazione è Ruby, ho scritto parecchio su questo tema, ho fatto un paio di progetti durante l’anno. Ruby è un linguaggio stupendo, di una semplicità elegante, sintetico ma leggibile, e poi c’è la community di Ruby che è attivissima, sforna gemme alla velocità della luce e realizza cose veramente interessanti. Non conosco ancora Ruby come vorrei, anche qui i miei legami con i linguaggi statici rallentano il salto verso il vero potere di ruby che sta nella metaprogrammazione.

Sul progetto OpenSource ci sto ancora lavorando, da un lato è nato conf-oo il sito usato per la ugialt.net che è disponibile su github, è molto prototipale, ha alcune buone idee ma ci si deve lavorare, è nato in fretta in queste ultime settimane vedremo di fare refactoring appena prendiamo fiato. Poi c’è un altro progetto in porto che però è ancora top-secret.

Questi sono stati i 3 todo “consegnati” a fine anno, ora è tempo di pensare al 2012.

Posted in Personal | No comments

Next Page »