DORM – Delphi ORM

November 22, 2011
Tags: , ,

Há pouco tempo tomei conhecimento que o projeto DORM [1] (Delphi ORM), de autoria do Daniele Teti [2] se tornou público, rapidamente baixei o projeto para poder experimentar, e aqui vão minhas opiniões.

Não pretendo entrar em questões como o que é um ORM, sua utilidade, etc.

De cara o que me chamou atenção no DORM é que a proposta do framework é que ele não interfere na modelagem dos seus objetos. Ou seja, seus objetos de negócio não precisam herdar/implementar nenhuma classe/interface em especial, os atributos não precisam ser published, os atributos são de tipos primitivos da linguagem, etc. Em resumo, uma classe como a abaixo pode ser persistida sem problemas:

type
  TCliente = class
  private
    FId: Integer;
    FNome: String;
  public
    property Id: Integer read FId write FId;
    property Nome: String read FNome write FNome;
  end;

Um outro ponto positivo que encontrei é que ele faz uma clara distinção entre bases de dados para desenvolvimento, testes e produção, sendo que você especifica isso no momento de criar a sessão. Normalmente é simples selecionar bancos diferentes para cada situação (desenvolvimento/testes/produção), então o DORM não trouxe nada de outro mundo, mas o fato de isto já vir embutido no framework é algo muito positivo. Digo isso não por poupar o desenvolvedor de algum trabalho extra, mas por incentiva-lo a trabalhar desta forma.

Uma coisa que senti falta é mapeamento por CoC. Ou seja, para o exemplo que eu dei acima, seria interessante que, sem eu ter fazer nenhum mapeamento, o framework já assumisse que a tabela se chama CLIENTE, e os campos ID e NOME. E para casos em que se deseja sair do padrão, aí sim eu poderia recorrer ao mapeamento manual.

O mapeamento, bem como a configuração de conexão com os bancos, é feita em um arquivo externo em formato JSON. Não investiguei mais a fundo, mas me parece ser possível montar a configuração em memória (montando uma string em JSON) e utilizar isso ao criar a sessão, assim não seria necessario manter um arquivo externo com estes dados.

O mapeamento não é documentado, mas olhando os exemplos que acompanham o projeto foi facil ver como eu devia proceder com as minhas classes.

Alias, documentação é um ponto fraco do projeto, mas não me preocupo muito com isso. Não é que documentação não seja importante, mas uma boa suíte de testes automatizados já quebram um galho quando eu preciso aprender alguma coisa sobre o uso do framework, e de qualquer forma eu prefiro que o autor gaste seu tempo escrevendo código do que documentos :)

Outra coisa que seria legal de ter é mapeamento por atributos. Seria muito interessante se fosse possível mapear as classes com algo mais ou menos assim:

type
  [Table('CLIENTE')]
  TCliente = class
  private
    [PrimaryKey]
    [Column('ID')]
    FId: Integer;
    [Column('NOME')]
    FNome: String;
  public
    property Id: Integer read FId write FId;
    property Nome: String read FNome write FNome;
  end;

Isso, aliado ao CoC, reduziria bastante o esforço para mapear as classes.

O projeto conta com uma aparentemente razoavel cobertura de testes automatizados, o que sem dúvida é um ponto importante, pois mostra a maturidade do autor, e nos dá segurança para confiar no código.

Apesar de eu mesmo ainda não ter usado, sei que o projeto suporta associações, inclusive de coleções. A respeito de coleções, a versão no trunk exige o uso da classe TdormCollection para coleções, mas já existe um branch em desenvolvimento para permitir o uso de qualquer coleção através de duck-typing [3], ou seja, qualquer objeto que possua métodos como Add() e afins, poderá ser utilizado.

Lazy loading também é suportado, mas não de forma transparente como em frameworks mais modernos como por exemplo o Hibernate. Existem uma série de limitações que dificultam/impossibilitam a implementação de lazy loading de forma transparente no Delphi, mas isso não vem ao caso.

Criei algumas entradas no issue tracker do projeto a respeito de alguns dos pontos levantados aqui neste post. Para quem tiver interesse, sugiro ir lá e sinalizar o issue ou mesmo contribuir com algum patch.

  1. http://code.google.com/p/delphi-orm/issues/detail?id=5 Convention over Configuration (CoC)
  2. http://code.google.com/p/delphi-orm/issues/detail?id=6 Mapeamento por atributos
  3. http://code.google.com/p/delphi-orm/issues/detail?id=8 Travamento otimista através de versionamento de registros

Estou tentando contato com o autor há alguns dias, mas ele não me responde nem por e-mail nem nos issues que lancei no projeto. Eu gostaria de contribuir implementando algumas das solicitações que eu lancei, mas antes preciso saber se o autor concorda com as mesmas e aceitaria contribuições de terceiros. Havendo qualquer retorno, eu atualizo o post aqui.

Update – 23/11/2011
Recebi alguns retornos do Daniele Teti, ele aceitou minhas sugestões e me colocou como commiter para que eu possa ir trabalhando nelas, enquanto ele se foca no core do framework.

Infelizmente meu tempo é limitado, já que o Emballo [4] toma boa parte dele, mas dentro das possibilidades pretendo dar minha contribuição ao projeto. Se alguem mais quiser contribuir, é só se manifestar lá no site do projeto.

[1] http://code.google.com/p/delphi-orm/
[2] http://www.danieleteti.it/
[3] http://en.wikipedia.org/wiki/Duck_typing
[4] http://code.google.com/p/emballo

8 Responses to “DORM – Delphi ORM”

  1. Olá Magno, vi que você perguntou sobre o TMS Aurelius no seu Twitter. É uma framework ORM da TMS Software. Aqui vai um link sobre ele: http://www.tmssoftware.com/site/blog.asp?post=208. Você estará na Delphi conference?

  2. Wagner… Bem que eu imaginei, rsrs, mas na época não consegui encontrar nada nem no site da TMS (não devo ter procurado direito), daí a dúvida.

    Infelizmente não vou estar no Delphi Conference :(

    Pode indicar algum local onde consigo mais informações sobre este framework?

    Você tem relação com o seu desenvolvimento?

  3. Magno, sim, o TMS Aurelius está totalmente sob minha responsabilidade. Podemos trocar mais detalhes por e-mail, mande um e-mail pra TMS perguntando do Aurelius, o e-mail virá pra mim e aí conversamos, pode ser?

  4. Algum problema específico referente a implementação de lazy loading no Delphi?

  5. Problema nenhum, tanto que o DORM mesmo implementa.
    A dificuldade é implementar de forma que fique transparente, ou seja, você declara algo assim:

    type
      TCustomer = class
      public
        property City: TCity read FCity write FCity;
      end;
    

    E o objeto TCity associado só vai ser carregado do banco quando a propriedade City for referenciada, e de forma que isto não precise estar explicitamente implementado na classe TCustomer

  6. Wagner,
    Com certeza… Pode esperar meu contato :)

  7. Magno, o TMS Aurelius já foi lançado: http://www.tmssoftware.com/site/aurelius.asp

  8. Já baixei e instalei o trial… Post sobre o Aurelius indo para o forno agora :)

Leave a Reply

Spam protection by WP Captcha-Free