RDS Kata

In questo post mostrerò la mia discutibilissima soluzione all’RDS Kata proposto sul blog di SI-Agile, il vivace gruppo che raccoglie gli agilisti della Svizzera Italiana. Il codice è presente in questo file zip, spero a breve di creare un progetto su Google Code per ulteriori sviluppi.

Funzioni di utilità

Partiamo subito con la prima sequenza di test.
Leggendo tutti i requisiti del Kata, ho pensato fosse necessario avere in primo luogo una funzione che centrasse le stringhe secondo le specifiche. Ho pertanto creato dei test per un metodo statico center da inserire nella mitica classe di utilità StringUtils, che non può mancare in qualsiasi progetto Java. Il primo banale test, testCenterDoesNotChangeTooLongStrings, mi è servito per disegnare l’interfaccia del metodo. Per scrivere i test successivi mi è sorta la necessità di avere una funzione blanks, che, guarda caso, mi è poi tornata utile anche nel codice di produzione. Ho deciso di non scrivere un test specifico per blanks, avendo fiducia che, una volta creata correttamente la funzione stringOf, la sua specializzazione che creasse stringhe di spazi fosse banale.
Uso qui volutamente il termine di funzione, in quanto questi metodi hanno la proprietà di trasparenza referenziale, ovvero restituiscono sempre gli stessi valori a fronte dei medesimi ingressi, indipendentemente da un qualsiasi concetto di “stato” del sistema; inoltre non hanno alcun effetto collaterale. Se ci fosse la possibilità di utilizzare i metodi statici come parametri di altre funzioni… ;-)
Concludendo le divagazioni, vorrei solo annotare che, per migliorare la leggibilità del codice e ridurre le duplicazioni, ho fatto un po’ di refactoring sui test estraendo il metodo assertCenterReturnsAStringOfFixedLength.

Le classi principali

Sono poi passato al disegno principale della mini applicazione tramite i test di RDSGeneratorTest che ho cercato di rendere indipendenti dal numero di caratteri del display.
Leggendo le specifiche del Kata ho cercato di elaborare una metafora: le varie parti da mostrare sul display (autore, data, titolo) sono gruppi distinti di parole, ovvero delle frasi. Ho quindi stilato i test di RDSSentenceTest, facendo anche in questo caso attenzione a rendermi indipendente dalla lunghezza del display. La prima stesura della classe RDSSentence, che comunque supera tutti i test, è stata la seguente:

 
public class RDSSentence {
 
  private final String sentence;
  private final int displaySize;
 
  public RDSSentence(String sentence, int displaySize) {
    this.sentence = sentence;
    this.displaySize = displaySize;
  }
 
  public String[] tokens() {
    if ("".equals(sentence.trim())) {
      return new String[]{};
    }
 
    String[] tokens = sentence.trim().split("\\s+");
    if (tokens.length == 0) {
      return new String[]{};
    }
 
    Collection<String> result = new ArrayList<String>();
    StringBuffer accumulator = new StringBuffer();
    for (int i = 0; i < tokens.length; i++) {
       if (accumulator.length() + tokens[i].length() + 1 <= displaySize) {
         if (accumulator.length() > 0)  {
           accumulator.append(" ");
         }
         accumulator.append(tokens[i]);
       } else {
         if (accumulator.length() > 0) {
           result.add(accumulator.toString());
         }
         accumulator = new StringBuffer(tokens[i]);
       }
       if (i == tokens.length -1) {
         result.add(accumulator.toString());
       }
    }
 
    return result.toArray(new String[]{});
  }
 
}
 

Come potete vedere, il codice è troppo complesso, con un numero ciclomatico molto elevato. Per un buon refactoring occorreva un’altra metafora: il display che accumula parole fino ad una certa lunghezza può essere appunto visto come un accumulatore elettrico, o, se vogliamo, idraulico che, raggiunta la capienza, si svuota in un tubo di scarico. Sono nate così le classi Accumulator e StringWharehouse, che non hanno test autonomi, ma vengono esercitate indirettamente dai test di RDSSentenceTest. La classe StringWharehouse, con una leggera modifica, mi è poi stata utile per migliorare il MockRadioStation, che in un primo tempo accumulava i dati in un semplice StringBuffer.

Conclusioni

Cosa ho cercato di esercitare con questo Kata?

Sicuramente non ho raggiunto completamente i miei obiettivi, spero comunque di aver fatto un piccolo passo in questa direzione.

Lascia un commento

You must be logged in to post a comment.