Tag Archives: baby steps

Cuidado com seus baby steps!

TDD sugere que o programador ande sempre em passos de bebê (os famosos baby steps): ele deve escrever testes sempre para a menor funcionalidade possível, escrever o código mais simples que faça o teste passar e fazer sempre apenas uma refatoração por vez.

Às vezes vejo pessoas interpretando errado o “escrever o código mais simples que faça o teste passar”. Na opinião delas, um if a mais é o código mais simples que ela pode escrever. E de repente, você tem um código cheio de if, praticamente ilegível, e só a partir daí é que começam as refatorações.

A ideia de escrever o código mais simples é justamente fazer com que o programador evite criar complexidade desnecessária. E na minha opinião, evitar na verdade complexidade de design (sabe aquela história de você criar uma façade que chama uma factory que cria um strategy que invoca um command, e por aí vai? Ou criar uma classe acoplada com outras 10 porque você acha que ela vai precisar?).
Se você for implementar uma soma (péssimo exemplo?), e escrever:

public class CalculadoraTest {
  @Test
  public void DoisMaisDoisEhQuatro() {
    assertEquals(4, new Calculadora().soma(2,2));
  }
}

public class Calculadora {
  public int soma(int a, int b) {
    return 2;
  }
}

E logo em seguida…

public class CalculadoraTest {
  ...

  @Test
  public void TresMaisDoisEhCinco() {
    assertEquals(5, new Calculadora().soma(3,2));
  }
}

public class Calculadora {
  public int soma(int a, int b) {
    if(a==3) return 5;
    return 2;
  }
}

E depois…

public class CalculadoraTest {
  ...

  @Test
  public void QuatroMaisDoisEhSeis() {
    assertEquals(6, new Calculadora().soma(4,2));
  }
}

public class Calculadora {
  public int soma(int a, int b) {
    if(a==3) return 5;
    if(a==4) return 6;
    return 2;
  }
}

para só então chegar no código:

public class Calculadora {
  public int soma(int a, int b) {
    return a + b;
  }
}

… você não entendeu muito bem o objetivo de escrever o código mais simples que faça o teste passar!

No livro do Kent Beck [1], ele mostra o exemplo da classe Money, e ele faz os passos mais simples que fazem o teste passar. Passos realmente simplórios, parecidos com os do exemplo acima, que qualquer programador poderia considerar desnecessários. Mas logo em seguida, ele faz a seguinte afirmação: “Se eu faço assim o tempo todo? Claro que não. Mas eu fico feliz em saber que poderia fazer!”.

Ou seja, TDD não é fazer baby steps o tempo todo, e sim poder fazer baby steps quando necessário! Se você está escrevendo algum trecho de código complicado, você pode andar mais devagar; agora, se está escrevendo algum trecho de código simples, e você está confiante sobre isso, você pode dar um passo maior!

Um exemplo que me agrada muito em um outro artigo do Beck [2] é o exemplo de uma classe que lida com tabelas de mortalidade, ou seja, ela deve calcular valores de acordo com a idade de uma pessoa. Uma classe que poderia ser escrita naturalmente da seguinte maneira:

public class MortalityTable {
  public MortalityTable(Person person) {
    // ...
  }

  public Table calculate() {
    // usa Person aqui para calcular a tabela
  }
}

E ele mostra que, ao usar TDD para gerar essa classe, ele percebeu que (i) gerar uma entidade Person era complicado e (ii) a classe MortalityTable só precisava realmente da idade da pessoa para fazer o cálculo. Então, ele refatorou:

public class MortalityTable {
  public MortalityTable(int age) {
    // ...
  }

  public Table calculate() {
    // usa apenas a idade para calcular a tabela
  }
}

Ou seja, passar a idade para a classe MortalityTable era o jeito mais simples que ele tinha para resolver o problema! Isso sim é escrever o código mais simples que faz o teste passar! Perceberam a diferença?

Para terminar o post, gostaria de parafrasear o Jason Gorman: If “doing the simplest thing” tends to lead to lots of IF’s or Switch statements, it’s possible you’ve misunderstood TDD.

Referências

[1] Beck, K. Test-Driven Development: By Example. Addison-Wesley Professional, 2002.
[2] Beck, K. Aim, Fire. IEEE Software Volume 18 Issue 5, September 2001.