Páginas

Wednesday, January 7, 2009

TDD em cantigas de roda - parte 1

Bem, resolvi implementar minha própria cantiga usando TDD.
Pode parecer estranho, mas é apenas uma variação do que o Falcão fez e que eu comentei no post anterior.

Vamos então começar com a cantiga, "Atirei o Pau no Gato":

Atirei o pau no ga-to-to
mas o ga-to-to
não morreu-rreu-rreu
dona chica-ca
adimirou-se-se com o berro
que o gato deu
miiiiaaaaaaauuuuuuuu.


Olhada com os olhos certos, essa cantiga infantil de aparência simples, que vem sendo ensinada de forma alterada para evitar a extinção dos gatos domésticos, pode ser uma bela fonte para análise e discussão. Possivelmente minha abordagem não será a melhor, porém essa não é a idéia. É apenas a minha expressão de como encarei as coisa no ônibus voltando para casa...

O primeiro teste:
class TestAtireiOPauNoGato(unittest.TestCase):
def test_admiracao(self):
dona_chica = DonaChica()
gato = Gato()

self.assertFalse(dona_chica.admirada)
gato.berrar()
self.assertTrue(dona_chica.admirada)


E... hmm... precisamos de uma implementação para fazer os testes passarem! Então surge o primeiro "problema". Eu já escrevi os outros testes que acredito serem pertinentes a cantiga, mas não tinha escrito nada de implementação.
E o primeiro estalo foi: "o berro do gato tem que disparar um evento e a DonaChica é listener... quando o gato berra ela admira-se".

Como fazer essa comunicação? Veja que legal, chegamos num ponto — ainda bem no início da discussão — em que podemos aplicar um padrão de projeto (design pattern), o Observer pattern. Mais uma vez deixo claro que está é minha implementação, e faço o que quiser com ela: é minha!!!

Ah, mas... ok, antes de fazer algo super bonito, que tal fazermos o teste passar?

class DonaChica(object):
admirada = False

class Gato(object):
def berrar(self):
DonaChica.admirada = True


E rodando os testes: verde!
Eu não gosto desse código, alterar um atributo de classe não faz sentido, já que só uma instância de DonaChica, no caso dona_chica, ficou admirada.
Podemos explicitar isso fazendo mais um teste.

Queremos que possam existir diversas Donas Chicas espalhadas pelo mundo, ou em diferentes cidades, ou mesmo em dimensões distintas. O mesmo vale para os gatos... nada de singletons. Logo, para possibilitar diversos "namespaces" pensei em, ao invés de criar mais uma nível de objeto, e enfiar o gato e a dona_chica lá dentro, seria interessante ter uma Vila (vamos supor que nossa Dona Chica mora em uma, e lá existe ao menos um gato). A Vila nada mais é que o gerenciador de eventos, fazendo então a junção do gato e da dona Chica em um ambiente em que um pode interagir com o outro, e outros gatos, outras donas chicas, simplesmente não afetam/ são afetados.

Então vamos adicionar a dona_chica e o gato a uma Vila e descrever o que acontece caso um gato externo berre:

    def test_admiracao_com_outro_gato(self):
dona_chica = DonaChica()
gato = Gato()
outro_gato = Gato()
vila = Vila()
vila.adicionar(dona_chica)
vila.adicionar(gato)

self.assertFalse(dona_chica.admirada)
outro_gato.berrar()
self.assertFalse(dona_chica.admirada,
"A dona Chica admirou-se com o berro de outro gato!")


E como esperávamos, vermelho nos testes!
Vamos implementar:

Mas não agora, em breve!
Hora de dormir.

No comments: