30 de abril de 2011

Total control over your models

Every single web2py application that uses database, has its own models dir.

This directory is particularly important due to some characteristics:
  1. models directory files ares executed in alphabetical order;
  2. Your application's database tables definitions stay in it;
  3. Objects defined by these files become available on your app's global scope. They can be accessed by controllers and views.
I warn you to pay attention to the first one: files are executed in alphabetical order.

Some newbies have dificulties with that, and tend to think this is strange. I did it, until I concluded this is the most intuitive way to things work. It gives me freedom to organize my app.

However, to avoid some mistakes this way can bring to your app, we need to adopt a clear and fool proof convetion to name models files.

I use this simple and efficient structure:
  1. models/0_db.py
  2. models/1_menu.py
  3. models/5_models.py
  4. models/5_validators.py
I rename the automatically created db.py file to 0_db.py. So, I guarantee all basic definitions are executed before anything else. The DAL object, who provides all data access funcionalities, is created in this script.

I also rename menu.py to 1_menu.py forcing all menu definitions to be executed after DAL object instantiation.

With these modified names, I'm sure that all the code I'll develop will be executed after the scaffolding app web2py generated to me.

From that point I write models/5_models.py with my table definitions. Nothing but db.define_table() commands.

Validators are written in models/5_validators.py. But, why separated from model definitions? First, because web2py recommends you don't mix validators with  db.define_table(). Second, because at this point I'm certain all tables are already created and all cross references between them will work with no need to adjust definition sequences. Sometimes it messes my scripts.

When I have many tables, I can separate them in various scripts, i.e, 5_models_accounts.py, 5_models_finances.py, etc. And, the same way, their validators.

Here, your creativity can fly, but remeber some principles:
Explicit is better than implicit.
Simple is better than complex.
Flat is better than nested.
Readabilty counts.
In the face of ambiguity, refuse the temptation to guess.

27 de abril de 2011

Controle total sobre seus models

Toda aplicação web2py que usa banco de dados tem um diretório chamado models.

Esse diretório é particularmente importante devido a alguns fatores:
  1. Os arquivos do diretório models são executados em ordem alfabética;
  2. É ali que ficam as definições das tabelas dos bancos de dados de sua aplicação;
  3. Os objetos definidos por esses arquivos ficam disponíveis com escopo global na aplicação. Ou seja, podem ser acessados pelos controladores e pelas views.
Talvez a caracterísitica que mais exija atenção, é a primeira: execução em ordem alfabética.

Algumas pessoas iniciantes têm certa dificuldade com isso e acham meio estranho esse comportamento. Eu também achava, até concluir que esse é o jeito mais intuitivo para tudo funcionar.

Entretanto, para evitar alguns inconvenientes que esse funcionamento pode trazer, precisamos adotar uma nomenclatura clara e o mais simples possível para organizar nossos scripts dentro do diretório models.

Eu adoto a seguinte estrutura básica:
  1. models/0_db.py
  2. models/1_menu.py
  3. models/5_models.py
  4. models/5_validators.py
Em quê isso ajuda?

Eu renomeio o db.py gerado automaticamente pelo web2py para 0_db.py. Assim, garanto que todas as definições básicas são executadas antes de qualquer coisa. O objeto DAL, que fornece toda a funcionalidade de acesso a dados, é criado nesse script.

Também renomeio o menu.py para 1_menu.py fazendo com que as definições de menu sejam executadas depois da instanciação do objeto DAL.

Com esses nomes modificados, garanto que o esqueleto gerado automaticamente pelo web2py vai ser executado antes das partes que eu vou desenvolver depois.

A partir daí, escrevo o models/5_models.py com todas as definições de tabelas. Vale ressaltar que eu deixo dentro desse arquivo apenas os db.define_table().

Para escrever os validadores, eu crio o models/5_validators.py. Mas por que separado? Primeiro, porque o web2py recomenda que você não coloque os validadores dentro do db.define_table(). Segundo, porque nesse ponto eu tenho certeza de que todas as tabelas já foram definidas. Assim, garanto que qualquer referência cruzada entre elas funcione sem precisar alterar a ordem de criação delas. Às vezes isso desorganiza o script de criação das tabelas.

Se eu tiver muitas tabelas, nada me impede de dividir a definição delas em vários scripts, por módulos, por exemplo: 5_models_estoque.py, 5_models_financeiro.py, etc. E, da mesma forma, os validadores.

Aqui, sua criatividade é quem manda, mas lembre-se de alguns princípios:
Explícito é melhor do que implícito.
Simples é melhor do que complexo.
Linear é melhor do que encadeado.
A legibilidade conta.
Quando encontrar a ambiguidade, recuse a tentação de adivinhar.