Fork me on GitHub

Viagens, opiniões e afins

by Andre Fonseca


Python Decorators

A um bom tempo atrás (dezembro de 2009) escrevi um artigo sobre “decorators” em Python. O texto foi inspirado num post no blog do pessoal da Artima( mais precisamente do Bruce Eckel) que falava sobre o assunto.

De lá para cá, apareceram mais artigos e o uso de decorators ganhou bastante força em bibliotecas, frameworks, etc. Diante disso, e de diversos pedidos que recebo, resolvi re-visitar o assunto.

No wiki do Python, a definição de decorator, é de uma forma que temos para alterar um comportamento de um função ou métodos dentro de um código. Seria como se pudéssemos adicionar ou até alterar a lógica sem sermos muitos intrusivos.

Um bom exemplo seria o decorator classmethod. Veja abaixo:

class OlaMundo(object):

    def metodo1(self):
        print "Ola Mundo"

Na classe acima, para usarmos o método “metodo1″, precisamos de uma instância de OlaMundo.

olaMundo = OlaMundo()
olaMundo.metodo1()
OlaMundo.metodo1(olaMundo)

Para transformar o metodo1 ou escrever um metodo2 que pertença a classe e não a uma instância, você tem que fazer:

class OlaMundo(object):

    def metodo1(self):
        print "Ola Mundo"

metodo1 = classmethod(metodo1)

Já o decorator, como uma macro em C, tornar o código mais legível e faz essa “mágica” para a gente:

class OlaMundo(object):
    @classmethod
    def metodo1(self):
        print "Ola Mundo"

O que são os Decorators e como funciona:

Os decorators do Python são como macros ( já disse isso) que quanto o interpretador os encontra os substitui por um estrutura que foi definida. No caso do classmethod ele “substitui” pela a chamada original.

Claro que a definição acima é simplista, mas ajuda a entender.

Nos aprofundando mais, ele é semelhante ao with do Python. Ele é uma classe que no seu init recebe o objeto a qual foi associado e um método call (ele é um Callable). Esse método call é chamado e ai você pode fazer algo.

class MeuDecorador(object):
   
    def __init__(self, function):
        self.f = function
   
    def __call__(self):
        print "Ola Mundo"
@MeuDecorador
def funcao():
    print "algo assim"

funcao()

O código acima mostra bem (execute-o) como funciona um decorator. No meu caso, eu simplesmente coloquei um print. Mas no método eu posso abrir um conexão, colocar um log, medir tempo, colocar numa, fila, emitir um sinal, adicionar o método como callback numa evento, etc.

Para que servem e por que usar:

Decorators não trazem nenhum grande novidade a linguagem (está desde a versão 2.2 se não me engano), mas alteram e melhoram a sintaxe de nossos códigos facilitando a compreensão do que está acontecendo ali.

Referência.
[1] http://wiki.python.org/moin/PythonDecorators
[2] http://www.tocadoelfo.com.br/2009/10/python-decorators-uma-introducao.html
[3] http://devlog.waltercruz.com/python_decorators
[4] http://www.ibm.com/developerworks/linux/library/l-cpdecor/index.html
[5] http://wiki.python.org/moin/PythonDecoratorLibrary

Published by Andre, on outubro 25th, 2011 at 8:38 am. Filled under: atualidades,django,python Tags: , , , No Comments

Usando growl com python e ferramenta de autotest

A um certo tempo atrás trabalhava com Ruby, mais precisamente, desenvolvia utilizando o framework Rails. Dentro desse eco-sistema, existia uma “ferramenta” que sou apaixonado: Autotest (zentest).

Essa ferramenta fica monitorando seus arquivos ruby e caso faça qualquer alteração ele executa os testes (spec) do projeto. Isso é realmente uma “mão na roda” pois, para quem curte TDD, você fica o tempo todo monitorando as alterações no seu código e vai evoluindo bem.

Atualmente mudei de time e passei a trabalhar em projetos com django/python. Logo, comecei a procurar dentro desse novo ambiente, uma ferramenta similar que me permitisse fazer a mesma coisa. Vi que o pessoal do Dojo usa uma ferramente desenvolvido pelo Flávio Amieiro. O tempo foi passando e não encontrei nenhuma que me agradasse ao ponto do autotest (facilidade de uso e instalação).

Foi quando encontrei o Peon, desenvolvido pelo Bernardo Heynemann. O Peon é uma ferramenta que é fácil de instalar (pip install ou baixa e executa make install) e fácil de usar basta:

peon make test -d tests

O comando acima é para quando alguém alterar algum arquivo .py no diretório tests ele irá executar o comando make test. Se você apenas chamar o peon, ele irá executar o nosetests para toda mudança em qualquer arquivo python do projeto.

Além disso, ele tem uma integração com a notificação do linux, permitindo em caso de falhar algum teste – por exemplo, ele te avisar. Entretanto, como eu uso o Mac OS, queria poder ter esse mesmos avisos com o Growl.

Pesquisando encontrei uma forma de fazer isso.

Existe uma biblioteca python (py-Growl) que faz essa integração ( semelhante ao pynotify da libnotify do linux). Abaixo um código mostrando como fazer. A explicação é bem simples:

try:
    import Growl
except ImportError:
     return

path_image = abspath(join(dirname(__file__), image))
icon = {'applicationIcon': Growl.Image.imageFromPath(path_image)}

growl = Growl.GrowlNotifier(app_name, [app_name], **icon)
growl.register()
growl.notify(app_name, title, message)

Primeiro você cria um notifier, informando o nome da app (ela será usada para identificar quem está mandando algo para o Growl. Isso é importante), lista de tipos de mensagem que serão enviadas e um dicionário com ícones.

Depois você registra seu notifier e usa o método notify, passando o nome da app que você informou na criação do objeto, um título (um dos tipos que você informou) e a mensagem. E pronto!

Esse código já está no fork que eu fiz do Peon e vou fazer um pull request em breve. Fica a dica de usar o Peon e o Growl. Fica muito maneiro.

Published by Andre, on outubro 20th, 2011 at 1:43 pm. Filled under: atualidades,python Tags: , , , , No Comments

Jasmine BDD: Instalando e escrevendo primeiro teste

Para os que ficaram interessados devido aos posts anteriores em usar o Jasmine BDD para fazer (até começar a fazer) seus testes, esse será o primeiro de uma série de artigos que tentaram explicar o como usar, como escrever seus testes e coisas mais avançadas como assíncrono e stub.

Primeira coisa é que caso não esteja familiarizado em escrever testes ou está começando a programar, antes de mais nada aprender os conceitos básicos e procure um Dojo mais próximo de você. Independente de ser testes em javascript ou qualquer outra linguagem, escrever testes é uma forma de pensar e filosofia que deve ser aprendida. Senão, você ficará perdido, sem saber por onde começar e além disso, não conseguirá colher os benefícios que isso trará para seu produto.

Avisos paroquiais feitos vamos ao que interessa.

Antes de escrever a sua primeira linha de qualquer coisa é preciso que instale as coisas. Nesse momento, seguiremos do jeito mais simples e hard, sem uso de ferramentas, linhas de comando, etc. Vamos nos ater ao básico e mais simples.

O Jasmine BDD é uma biblioteca Javascript. (.js). Ele roda dentro de uma página com alguma markup que permite que ele coloque na tela a saída do resultado da tela. Sendo assim, acesso o site do produto (clique aqui). Na página principal escolhe a opção de standalone. (voce pode ir direto para esse link).

Ao descompactar o arquivo verá uma estrutura de arquivos e pastas, praticamente pronta para uso. Para rodar os testes basta carregar o SpecRunner.html no seu browser preferido.  Suas specs(js com testes). Devem ficar dentro da pasta spec (vejo o exemplo que vem junto). É costume chamar o nome do arquivo com o nome do que irá testar seguido de Spec.

 

Para incluir um novo teste ou um novo arquivo de dependencia (tipo jquery ou mootools) bastar colocar a chamada no SpecRunner.html

 

<html>
<head>
  <title>Jasmine Test Runner</title>
  <link rel="stylesheet" type="text/css" href="lib/jasmine-1.0.2/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-1.0.2/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-1.0.2/jasmine-html.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script>

</head>
<body>

<script type="text/javascript">
  jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
  jasmine.getEnv().execute();
</script>

</body>
</html>

 
Só com isso, você já tem o seu framework de teste funcionando perfeitamente em sua máquina.

Seu arquivo de teste é composto por, basicamente, dois blocos – um dentro do outro. Num bloco você descreve ou define o contexto. Ele é definido pelo método describe. Assim todo teste jasmine deve começar por:

describe("contexto", function(){
//Aqui dentro as expectativas
});

&nbps;

Assim como o Rspec, no qual o Jasmine se inspirou, a idéia não é simplesmente pensar em testes unitários e sim criar expectativas, coisa que tem mais a ver com o BDD.

Assim se continuar nossos testes ficarão assim:

describe("contexto", function(){
  it("deve ser true", function(){
    expect(true).toBeTruthy();
  });
});

 

Pronto taí o seu primeiro teste com jasmine escrito. Onde, o it define o ponto de teste dentro daquele contexto. Ele contém uma frase que será exiba na execução do teste no HTMl e facilita o entendimento do objeto do teste. Os asserts são feitos usando um método expect que define oque será auditado e em seguida o que espera de resultado.

Ficamos por aqui. No próximo post, vou falar sobre os matcher e vamos avançar mais sobre jasmine.

Published by Andre, on outubro 2nd, 2011 at 8:00 pm. Filled under: atualidades,TDD Tags: , , , 1 Comment

Respondendo uma pergunta sobre TDD

No post que anterior, no qual falei sobre TDD, recebi um comentário perguntando dentro de algumas situações se O TDD se encaixava ou não.  Como a dúvida é recorrente e o tema é bastante controverso, resolvi, ao invés de responder o comentário dele, escrever um post.

A primeira coisa, em minha opinião, que tem que ficar clara, que TDD é um metodologia de desenvolvimento e não de projeto. Usamos TDD para gerar código melhor e com isso aumentar a qualidade do que estamos fazendo.  Testar antes não é garantia de zero bugs, mas ajuda a construir uma solução melhor pensada, simples, concisa,  e, sim, com testes automatizados que irão evitar muitos bugs.

TDD é uma forma de trabalho que se encaixa em qualquer modelo de equipe/projeto.  Se o seu time está em algo mais ágil ou waterfall, não faz a mínima diferença. Sem o seu time, irá entregar complexidade, pontos por caso de uso ou pontos de função isso também não faz diferença.  Pois, como já disse, TDD é um filosofia de desenvolvimento e não de gestão.

Ela trabalha em cima de ciclos pequenos onde a gente escreve o teste com a necessidade; após escrevemos o código para atender a necessidade e fazer o teste passar e por fim revistamos a solução para melhorá-la buscando princípios de Clean Code ( SOLID).  Se no final desse ciclo temos uma história entrega (por exemplo uso de quadros – Kanban, etc) ou se temos um ponto de função, observe que não faz diferença.  O que pode acontecer, no caso de pf é que deverá prever isso ( eu acho – nunca trabalhei com pontos de função).

Uma boa dica é que procure um DOJO (acesse o site do DojoRio) e veja na prática isso acontecer e como ela não tem relação com a gestão.

Se quer entender mais sobre TDD leia o livro do Kent Beck. Existe uma infinidade de outros livros sobre tão bons, mas acredito que seja legal começar pelo início. Depois a medida que for se sentindo mais confortável …

Assim, sem mais rodeios vamos a resposta a pergunta que me fizeram:

1. Posso usar TDD com um projeto que me exija entregar 4 a 40Pf ou qualquer outra coisas?

SIM ! Se acha que estou exagerando, procure o Alex Gomes da SEA Tecnologias. Seu maior cliente é o governo federal.  Existem outros exemplos como por exemplo

2. Código legado ?

Sim dá para usar TDD. Para te ajudar recomendo a leitura do livro Working Effectively with Legacy Code do Michael Feathers. Ele é uma excelente forma de ver como você pode testar o seu código legado.

Por fim espero ter te ajudado. E caso tenham dúvidas podem comentar que irei responder.

 

Published by Andre, on setembro 28th, 2011 at 9:40 am. Filled under: atualidades,codigo,TDD Tags: , , , No Comments