O problema
Não importa se seu background é Agil, Iterativo, Waterfall ou Tradicional. Uma coisa é certa e todos concordamos: Requisitos excelentes combinados a uma arquitetura perfeitamente executada é uma ótima fórmula para o sucesso. Inicialmente, a fórmula parece ser simples. E é! O problema está em sua execução. Como saber se estamos exagerando nos requisitos e no design? Em outras palavras: quão profundos (ou superficiais) os requisitos devem ser para serem o bastante para um encaixe perfeito entre negócio e tecnologia?
A quantidade certa de cada ingrediente nesta fórmula tem assombrado a comunidade de desenvolvimento de software desde os tempos do COBOL até os dias de Internet/Cloud/.Net/Java/Ruby/Python/PHP de hoje. Esse mistério precisa ser desvendado!
Uma solução
Uma solução para este dilema pode ser encontrado em metodologias ágeis. Se fizer esta pergunta para um “agilista” a resposta será, na maioria dos casos: evite BDUF (Big Design Up Front). Faz sentido. Uma das características de requisitos é que eles tem a tendência de mudar. Portanto, se você demorar demais definido seus requisitos e arquitetura, tão logo você esteja pronto para iniciar a codificação, adivinhe o que acontece? Os danandos dos requisitos decidem mudar!
Bem… então temos um bom começo! Evitar BDUF! Mas esta é uma abordagem restritiva, não prescritiva. É ótimo saber o que NÃO fazer. Mas o que DEVEMOS fazer? Bem… mais uma vez os “agilistas” dirão: TDD é o caminho, irmão: vá e comece pelos testes. Novamente, uma grade diretiva, dessa vez bem prescritiva… mas completa? Sinto-me na obrigação de responder: não. Infelizmente, saber que os testes devem ser escritos antes da implementação em si é parte do “caminho para a perfeição”. TDD é fantástico: concordo com todas as minhas forças. Basicamente força o desenvolvedor a escrever código utilizando componentes desacoplados. Se a arquitetura seguir boas práticas comprovadas, design patterns e bom e velho bom senso, melhor ainda. Porém, uma última pergunta perdura: O QUE deve-se testar?
Vejo algumas mãos levantadas na audiência? Ah, sim. O senhor, por favor pode falar:
- Bem, Daniel, é claro! A resposta está nos requisitos. O desenvolvedor deve ler os requisitos, entender a necessidade de negócio e desenhar os testes de acordo com os requisitos.
Muto bem! Excelente sugestão. Mas resta um porém na seguinte combinação de palavras: “entender a necessidade de negócio”. Desenvolvedores são, geralmente, um grupo de indivíduos cartesianos. Vivemos em um mundo de zeros e uns, “Trues” e “Falses”, “ifs” e “elses”. Requisitos de negócio precisam identificar claramente a necessidade do cliente, mas se não forem escritos muito cuidadosamente, a ambiguidade se prolifera e o resultado vai acabar parecendo com o antigo, mas ainda muito verdadeiro desenho do “balanço na árvore”.
Ah, e mais um detalhe: e a rastreabilidade? Qual frase dos paragráfos da especificação clássica de requisitos é rastreável ao código que precisa ser revisado sempre que algo muda? Difícil, não é?
A solução
Mutio bem: diversas abordagens para definir requistos não ambíguos, verificáveis, atingíveis e específicos tem sido o objeto de muitos artigos, metodologias e frameworks. De agora em diante, vou focar em uma metodologia/framework que tem funcionado impressionantemente bem na minha experiência: Behavior Driven Development (ou BDD). O BDD tenta diminuir a distância entre os analistas de requisitos e desenvolvedores especificando uma “linguagem” bem definida. Esta “linguagem” é, ao mesmo tempo, natural e específica. É claramente entendível por stakeholders técnicos e de negócio e descrevem o comportamenteo de um sistema. Por exemplo:
Funcionalidade: Pedidos
De modo a comprar um item
Como um cliente
Eu quer ser capaz de fazer pedidos
Cenário: Adicionar um item ao carrinho de compras
Dado que eu tenha selecionado um item
E eu tenha informado a sua quantidade
Quando eu pressionar o botão "adicionar ao carrinho"
Então o item deve ser adicionado ao carrinho
E o valor total do carrinho deve ser incrementado da quantidade do item multiplicada pelo seu valor
O texto certamente parece ser não ambíguo, verificável, atingível e específico, não é?
E se cada uma destas linhas do cenário se transformasse em um passo específico em um test case N/J/x/Unit, a partir do qual arquitetura e código pudessem ser derivados, a-lá TDD? Não seria fantástico? Este e exatamente o objetivo do BDD.
Próximos passos
Acho que isto já é o bastante para justificar um par de artigos no futuro (próximo) que irá clarificar e exemplificar ainda mais o BDD. Como meu background é em .Net, vou fornecer exemplos em C# usando uma implementação muito bacana de BDD específica de .Net baseada no Cucumber: o Specflow, um projeto open source patrocinado pela TechTalk.