Você já ouviu falar em Desenvolvimento Orientado a Testes (ou TDD)? Já escreveu testes antes do código? Esta é a primera parte de uma série onde aplicaremos as idéias de TDD num exemplo prático, desenvolvendo um clássico jogo de tabuleiro que não depende da sorte, mas sim da estratégia: Combate.



Introdução

Conforme eu adiantei no último post, começaremos hoje um exemplo de aplicação de TDD num exemplo prático. Essa idéia começou quando um colega de trabalho, Rodrigo (mais conhecido como RBP ou simplesmente R), sugeriu fazermos uma rápida sessão de Programação Pareada, para que eu mostrasse na prática como programar os testes antes do código. Desde então, discutimos alguns problemas simples, porém interessantes (e por que não divertidos?), que poderíamos utilizar no nosso exemplo, chegando ao clássico jogo de tabuleiro Combate.



Seguindo o exemplo de Ron Jeffries de ensinar TDD através de exemplos (desenvolvendo um programa para calcular o total de pontos em uma partida de boliche), começaremos hoje falando sobre os princípios de TDD e sobre as regras do Combate. Ainda na linha experimental e educativa dessa série de posts, vou aproveitar os conhecimentos do RBP e aprenderei um pouco de Python. Ainda não sabemos quantos posts serão necessários e nem se estamos sendo ambiciosos demais, porém nossa idéia é mostrar o crescimento incremental da aplicação, podendo até se transformar em algo “jogável” (com interface gráfica e funcionando em rede).



Regras do jogo: TDD – Test Driven Development

O Desenvolvimento Orientado a Testes é uma técnica para programadores (e não para testadores), cujo objetivo é a melhoria contínua do design. Essa técnica é fortemente baseada em testes automatizados, que são escritos antes do código, influenciando e orientando o design e a divisão das responsabilidades entre as classes do sistema. Dessa forma sua aplicação evolui em passos pequenos construindo apenas o design necessário para atender aos requisitos atuais do sistema. Como efeito colateral, você acaba desenvolvendo uma bateria de testes automatizados que pode ser executada a qualquer momento e que funciona como uma rede de proteção na hora em que as mudanças começarem a aparecer (e elas irão aparecer).



Quando desenvolvo com TDD, me vejo muito mais preocupado com decisões de design do que quando utilizo uma abordagem diferente para codificação. Ao escrever os testes do ponto de vista de um cliente da classe em questão, as preocupações com encapsulamento, divisão de responsabilidade e colaboração entre as classes se fazer muito mais presentes. Além disso, ao contrário do que possa parecer, desenvolver os testes junto com o código traz um aumento na produtividade, pois evita desperdícios futuros com depuração, reduz riscos durante a integração e melhora o design geral da aplicação, investindo somente o necessário um pouco antes e um pouco depois da implementação (evitando generalizações desnecessárias).



O Densenvolvimento Orientado a Testes impõe um ritmo constante e incremental baseado em passos pequenos. O passo inicial é pensar um pouco sobre o que será desenvolvido e elaborar uma pequena lista dos testes que serão implementados. O ritmo de TDD pode ser resumido num ciclo de iterações com os seguintes passos principais:

  1. Vermelho – Escreva um teste que falha (execute-o e veja falhar, para garantir que estará implementando algo relevante)
  2. Verde – Rapidamente, faça o teste passar (Escreva apenas o código necessário para que o teste passe, lembre-se: não se preocupe com o que você não vai precisar)
  3. Refatore – Refatore para eliminar duplicação e aumentar a expressividade do código. Evolua em direção ao design simples, reduzindo o acoplamento e aumentando a coesão.

Por fim, algumas recomendações: nunca escreva mais de um teste por vez e nunca refatore no vermelho.



Regras do Jogo: Combate

Combate (ou Stratego) é um jogo de estratégia, jogado num tabuleiro de 10×10 entre 2 jogadores, cada um com 40 peças representando os oficiais de um exército (e suas respectivas patentes). As peças são posicionadas de qualquer forma nas primeiras 4 fileiras de cada jogador, de forma que o adversário não saiba distinguir o valor de cada peça. O objetivo do jogo é capturar a bandeira do adversário ou deixá-lo com tão poucas peças que não possa se mover no tabuleiro.



Cada jogador move uma peça no seu turno (tanto na horizontal quanto na vertical). Todas as peças, com exceção dos soldados, só podem se mover 1 quadrado por vez. Se uma peça é movida para um espaço ocupado pelo adversário, suas patentes são reveladas e a mais fraca é removida do tabuleiro. Em caso de empate, ambas as peças são removidas. O valor numérico determina o vencedor na maioria dos casos, porém existem peças especiais: as bombas (não se movem e eliminam qualquer outra peça, exceto o cabo-armeiro), a bandeira (não se move) e o espião (a única peça que vence quando ataca o marechal, porém perde para qualquer peça que o atacar, incluindo o próprio marechal).



A quantidade de peças de cada jogador, em ordem de patente (da mais forte para a mais fraca), é:

Rank Peça Qtd Observação
10 Marechal 1  
09 General 1  
08 Coronel 2  
07 Major 3  
06 Capitão 4  
05 Tenente 4  
04 Sargento 4  
03 Cabo-Armeiro 5 Pode desarmar bombas
02 Soldado 8 Pode andar mais de um espaço por vez (como uma torre no xadrez)
S Espião 1 Vence quando ataca o Marechal, porém perde para qualquer peça que o atacar, incluindo o próprio Marechal
F Bandeira 1 Não se move
B Bomba 6 Não se move e elimina qualquer outra peça, exceto o Cabo-Armeiro

No ISF (International Stratego Federation) você encontra as regras oficiais do jogo.

A seguir…

No próximo post, iniciaremos a implementação da engine do jogo. Nossa idéia é desenvolver o jogo de forma incremental, então pensamos nos seguintes passos (lembrem-se, um plano não é um comprometimento sobre o que irá acontecer. Mudanças são bem-vindas!):

  1. Regras de ataque e de movimentação
  2. Controle do estado do jogo e das rodadas
  3. Gerenciar posicionamento inicial das peças
  4. Desenvolver uma interface textual
  5. Desenvolver uma interface gráfica
  6. Cliente/Servidor para jogar em rede

Post to Twitter

April 24th, 2006Design Incremental em XP

Nesse post falaremos um pouco sobre alguns dos mitos relacionados ao design em XP e sobre a nova abordagem de Kent Beck para garantir a qualidade e a simplicidade do design de um sistema.



Na primeira edição do livro Extreme Programming Explained, Kent Beck propôs 3 práticas que estavam diretamente relacionadas ao design do sistema: Design Simples, Refatoração e Metáfora. Dessas três, a última é a que mais gerou confusão nos praticantes de XP, sendo uma das menos utilizadas na prática. Com relação às outras duas, já ouvi diversas críticas e dúvidas:

Algumas dessas dúvidas estão relacionadas à forma como elas foram apresentadas na primeira edição, enquanto outras se baseiam numa interpretação errônea da prática no contexto de XP. A resposta para essas perguntas está melhor estruturada numa nova prática da segunda edição do livro: o Design Incremental. Invista no design do sistema um pouco a cada dia e se esforce para que o design seja excelente para resolver as necessidades atuais do sistema.

  • Quando?: Ao contrário de pensar pouco ou nunca pensar no design, a estratégia de XP é pensar sempre no design.
  • Como?: Faça mudanças em passos seguros e pequenos. A disciplina que facilita a evolução constante do design em XP é a refatoração, que melhora a qualidade do código sem alterar o comportamento do sistema.
  • Onde?: A heurística mais simples e eficaz é eliminar código duplicado. Adicionar uma feature num único lugar é muito mais simples e rápido do que ter que mexer em código espalhado por diversas classes.
  • Por quê?: Um design simples é mais comunicativo e mais fácil de ser entendido e alterado. Se o objetivo de XP é manter o custo da mudança constante, a facilidade de alterar o design a qualquer momento é fundamental.

Os novos critérios propostos por Kent Beck para avaliar a simplicidade são, em ordem de prioridade:

  1. Apropriado para o público-alvo: O código deve ser facilmente entendido pelas pessoas que vão trabalhar com ele.
  2. Comunicativo: Todas as idéias e intenções devem estar presentes no código, facilitando o entendimento do time e de um futuro leitor.
  3. Fatorado: A existência de código duplicado dificulta as alterações e o entendimento.
  4. Mínimo: Cumprindo as três restrições acima, um sistema deve ter o menor número de elementos possível. Menos classes implicam em menos código para testar, documentar e comunicar.

Para auxiliar o entendimento dos critérios de XP para avaliar e produzir código de qualidade, uma outra prática – que a princípio não parece ter relação direta com o design – se mostra muito importante: o Desenvolvimento Orientado a Testes (TDD – Test Driven Development). Ela será o tema dos próximos posts e, ao contrário do que possa parecer, está tão relacionada à produção de testes automatizados quanto à produção de código mais simples, comunicativo, fatorado e mínimo.

Post to Twitter


© 2007-2009 Danilo Sato | Powered by Wordpress

Page optimized by WP Minify WordPress Plugin