1 de maio de 2013

Fazer com que uma função seja membro de uma instância

Neste post eu uso o Web2py como exemplo, mas a ideia de atribuir uma função dinamicamente a uma instância de classe é genérica e eu peguei da Python Decorator Library, que trata só de decorators.

Diferente do Django, não é necessário criar classes para definir modelos, no Web2py. Uma desvantagem é que não existe a figura dos managers, como no Django. Assim, fica ruim associar métodos às tabelas, que é o objetivo dos managers.

Obsservação: Se você não conhece, os managers normalmente fazem operações que tratam com coleções (mais de um registro) das tabelas. O slide sobre Model Managers do Effective Django é mais didático que eu e a documentação oficial é muito boa.

Voltando ao Web2py, não definimos os modelos como classes mas, uma vez criado, um modelo é uma instância de gluon.dal.Table. Isso nos permite fazer umas brincadeiras legais, usando monkey patching e decorators.

A forma mais comum de associar funções a tabelas, no Web2py, é assim:
def so_ativos():
    return db(db.minha_tabela.ativo == True).select()

db.minha_tabela.so_ativos = so_ativos

Como fica meio esquisito, muita gente acaba nem fazendo isso e as funções que realizam operações comuns nas tabelas proliferam pela aplicação. De fato, esse modo é estranho porque eu tenho uma função realmente externa, lidando com a tabela. Ela é um intruso. Não usa self. Está fora da instância. Feio.

Um jeito muito mais interessante, é fazer com que uma função seja parte do objeto Table. A ideia é:
  1. Criar uma função, que recebe self naturalmente;
  2. Fazer com que essa função seja chamada pela classe como se fosse parte nativa do objeto Table, com o self como 1º argumento.

O código abaixo permite fazer isso:
O segredo está no decorator @make_member_of. É ele quem faz a mágica de colocar seu método dentro da instância de Table, conforme vemos abaixo:
Essa é uma forma de deixar seu projeto Web2py mais organizado, colocandos os métodos dentro do seu model, mas também pode ser usada para criar mais abstração em classes já existentes, sem a necessidade de herança.

Fica a dica.

Eu sou Vinicius Assef, um programador do século passado que gosta de Python, pratica Lean Development e acredita em Deus. Você pode me contactar por email ou twitter.

Um comentário:

  1. Cria uma entrada para isso no web2pyslices, com certeza é uma ótima dica!

    ResponderExcluir

Marcadores