Mostrando postagens com marcador baby steps. Mostrar todas as postagens
Mostrando postagens com marcador baby steps. Mostrar todas as postagens

quinta-feira, 2 de outubro de 2008

Passos de bebê

Na lista de discussão do núcleo de pesquisa de que faço parte, surgiu uma polêmica a respeito do uso da técnica de passos de bebê. Resumindo a história, alguém estranhou os passos minúsculos preconizados pela literatura de TDD. Por exemplo, em se tendo apenas o teste (em Java):

Template template = new Template("#{tecnica-agil} é legal!");
template.set("tecnica-agil", "TDD");
assertEquals("TDD é legal!", template.parse());


a implementação seria necessariamente

...
public String parse()
{
return "TDD é legal!";
}
...


Bom, vamos à minha visão da coisa toda: a técnica de "passos de bebê" serve para evitar complexidade desnecessária, como generalização prematura e overengineering. O tamanho do passo - o que parece ser o centro da polêmica - deve ser baseado no bom senso e no quanto é confortável para o desenvolvedor. Se um desenvolvedor ou par se sente confortável em utilizar a técnica de modo mais ortodoxo, ótimo. Se não, é uma questão de ajuste fino. Eu, por exemplo, normalmente utilizo passos um pouco (mas não muito) maiores, exceto quando o domínio é pouco conhecido.

Os passos de bebê estão diretamente ligados a Test-Driven Development. Em TDD, a implementação deve ser unicamente aquela suficiente para passar nos testes, e nada mais. Deste modo, os passos de bebê não estão na implementação, mas na elaboração dos testes. Caso se queira que os passos sejam maiores, basta aumentar a granularidade dos testes unitários. Escrever um teste apenas para, por exemplo, uma entrada "N" e implementar uma solução genérica para o alfabeto inteiro é algo que contraria diretamente os princípios do agilismo (ou seja, da engenharia de software moderna), é implementar a solução para um problema ainda não formulado. Do ponto de vista da programação, os testes unitários são a especificação de requisitos. Assim, uma solução geral para o alfabeto inteiro com um teste só para "N" recairia em uma das duas situações: (1) ou há implementação desnecessária, ou seja, desperdício e complexidade inútil ou (2) o conjunto de testes é deficiente, o que mostra requisitos mal formulados e pode ter consequências ruins como bugs de regressão.

A questão é que a implementação tem que ser a coisa mais simples (sem ser simplória, já dizia Einstein) que possa passar nos testes (e uma cascata de if-elses é tosqueira, não simplicidade). Se você consegue ter uma função que passa nos testes com um mero return "n", o problema está em um conjunto fraco de testes. A implementação está correta, pois cumpre os requisitos (testes unitários) de modo claro, simples, rápido e manutenível.

Toda e qualquer prática ágil deve estar ancorada em princípios e valores. No caso em questão, o valor é a já citada simplicidade, traduzida nos lemas KISS e YAGNI. Os passos de bebê asseguram que o software terá apenas a complexidade necessária e nada mais.