Arquivos de March, 2007

Como a filosofia de convenção ao invés de configuração do Rails enganou um novato

Há cerca de 3 meses resolvi me aventurar no mundo da linguagem Ruby, embora estivesse curioso há um bom tempo, foi mais por necessidade do que curiosidade, e como não poderia deixar de ser, utilizando o framework Rails. Só tenho a dizer o quanto a dupla Ruby+Rails me surpreende a cada dia, mas não é por isso que deixarei de utilizar Java, prefiro trabalhar com ambas as linguagens, escolhendo a que melhor convier ao projeto, prazo, custo e hospedagem, mas esta história fica pra outro post.

Como todo novato, apanhei feio no início, e é claro ainda estou tropeçando, mas o que mais me fez rir foi não ficar atento a filosofia do Rails de “convenção ao invés de configuração”, ou seja, seguir padrões de nomes de métodos, classes, estrutura de diretórios, etc. Há um “jeito” certo de se estruturar o código seguindo esta filosofia, e quando você sai dela é que sua dor de cabeça começa, é normal encontrar pessoas zangadas com erros estranhos que só acontecem por não ter seguido as regras. As pessoas ficam bravas pois estão acostumados a seguir um modo rotineiro de estruturação. Bem estas pessoas que se adaptem às coisas novas. Pessoalmente se um framework segue “convenção ao invés de configuração” já consegue me atrair logo de cara pois eu entendo isso como “me faça ter menos trabalho pra utilizar você”.

O meu erro foi ter “apenas” criado no modelo uma coluna com nome “type”. O que eu não sabia, é que para o Rails, uma coluna “type”, é reservada automaticamente para salvar o class-name do objeto na tabela, para caso você necessitar de um modelo de herança simples. Vamos supor um objeto Cachorro e outro Gato, ambas descendem do objeto Animal, mas há uma única tabela (Animal) para salvar Cachorro e Gato, a coluna “type” seria automaticamente preenchida com o class-name correspondente do objeto, para que ao consultar o registro, o Rails saiba que objeto deve criar. Óbvio que esta não era minha intenção, após ver sucessivas vezes o erro “:in `instance_eval’: compile error” e consultar a documentação, descobri o motivo.

Não posso culpar o Rails, é um padrão dele, assim como outros nomes também são reservados como created_at e id, são os chamados MagicFieldNames. Resumindo: ao trabalhar com “convenção ao invés de configuração” lembrem-se sempre de olhar quais convenções são estas, vai te prevenir muitos erros e com certeza vai aumentar em muito sua produtividade, afinal o padrão está lá pra ser seguido.

Ah sim, caso você realmente precise de uma coluna chamada type para outros fins, basta sobrescrever o seguinte método no modelo:

def self.inheritance_column
“<nome da coluna a ser utilizada ao invés de type>”
end

Pronto, agora o Rails utilizará esta coluna para salvar o class-name e a type fica livre para fazer o que melhor convier, embora eu não recomende fazer isso.

Comments

Criando um booleano de três estados

Antes de tudo este post não vai falar sobre física quântica, o objeto Boolean continua sendo aquele já conhecido por nós, mas vou falar sobre um anti-pattern que com certeza fez o Sr. Boole revirar no túmulo e que pessoalmente ainda me causa pesadelos.

Eu estava trabalhando em um módulo de um projeto, a certa altura houve necessidade de se criar uma integração com um outro módulo, nós passaríamos algumas informações, dentre elas indicar ou não se um usuário confirmou uma operação durante o processo, até aí tudo bem, combinamos que para esta confirmação seria passado um Boolean.FALSE ou Boolean.TRUE. Integração implementada e testada.

Após um mês, o mesmo pessoal desta integração me avisa que está tudo errado no conceito da confirmação do usuário, o que outro módulo esperava eram três estados diferentes: se o usuário “disse” NÃO, se o usuário “disse” SIM ou se o usuário não indicou nenhuma das duas opções anteriores… sim eu sei… não fez sentido pra mim também na época, mas acreditem fazia sentido para eles. Mas o problema, é que não houve tempo de opinarmos, o outro lado simplesmente já tinha decidido que seria enviado Boolean.TRUE, Boolean.FALSE ou NULL, caracterizando assim caríssimos, um glorioso mega anti-pattern: um Booleano de três estados. Tentei argumentar para mudarmos para um enum ou pelo menos constantes inteiras, mas não houve acordo, tivemos que aceitar o “monstrinho”, alegaram problemas de tempo para mudanças em vários lugares no módulo, o que já era um sinal de que havia coisas piores.

Lembrem-se, perder um tempo refatorando agora é um tempo ganho no futuro, ganhei várias dores de cabeça por causa desse anti-pattern.

Comments (1)