21 de outubro de 2011

Reusar queries usadas com frequência

No capítulo sobre DAL do livro de Web2py, existe uma seção chamada "Query, Sets, Rows".

Ela explica como usar o objeto Query de uma forma bem resumida e não explora todo o poder que ele tem.

Vamos ver alguns exemplos de como otimizar sua aplicação, encurtar seu código e praticar o princípio DRY (don't repeat yourself).

Consultas, ou queries, usadas com frequência (p.ex, filtragem comum por datas):
db.define_table('show',
    Field('name', 'string'),
    Field('seen_on', 'datetime'))

rows1 = db((db.show.seen_on.month()==my_month) & \
            (db.show.seen_on.year()==my_year)) \
            .select(orderby='name')
print rows1

Agora, se você quiser fazer a mesma query, mas filtrar também por nome:
rows2 = db((db.show.seen_on.month()==my_month) & \
            (db.show.seen_on.year()==my_year) &\
            (db.show.name.like('Mary %')) \
            .select(orderby='name')
print rows2

Viu? A parte que filtra por data está duplicada. Organize isso de um jeito melhor fazendo assim:
db.define_table('show',
    Field('name', 'string'),
    Field('seen_on', 'datetime'))

db.show.my_filter = lambda m, y: db.show.seen_on.month()==m & \
                                  db.show.seen_on.year()==y

rows1 = db((db.show.my_filter(my_month, my_year)) \
            .select(orderby='name')
print rows1
 
rows2 = db((db.show.my_filter(my_month, my_year) & \
            (db.show.name.like('Mary %')) \
            .select(orderby='name')
print rows2

"Adicionando" os filtros aos seus objetos table, você os coloca num contexto e eles estarão disponíveis em qualquer lugar da sua aplicação, assim como os outros métodos e propriedades.

Aconselho que você faça o mesmo com seus joins.

É natural que esse pequeno exemplo não mostre todos os benefícios dessa técnica, mas pense em alguns casos comuns:
a) Queries usadas com frequência: ficam padronizadas;
b) Queries longas e complexas: não deixam mais seu código bagunçado, e tornam-se mais fáceis de ler;
c) Joins: ficam otimizados e padronizados.

À medida que sua aplicação e sua equipe aumenta, você pode perceber melhor esses benefícios.

E você, tem alguma sugestão para melhorar? Colabore nos comentários.

3 comentários:

  1. Uma opção também é o uso de queries dinâmicas:

    http://showmethecode.tumblr.com/post/9583103076/web2pydaldynamicqueries

    ResponderExcluir
  2. Boa ideia, Bruno. Ajuda bastante.

    Apesar de eu tender mais para o modo explícito mesmo.

    Eu usaria o reduce() para queries com filtros opcionais.

    ResponderExcluir