Porque Objeto e Persistencia não combina?

Estou com algumas dúvidas, parecem meio idiotas mas por favor.
-Para que eu preciso persistir(salvar, atualizar…) um objeto em um banco de dados relacional?
-Em que momento isso deve acontecer?
-Porque isso não é nada natural em uma modelagem de negócio OO?
-Como fazer isso de forma elegante?
-E porque não utilizar isso http://www.guj.com.br/posts/list/55382.java

[quote=ptrecenti]Estou com algumas dúvidas, parecem meio idiotas mas por favor.
-Para que eu preciso persistir(salvar, atualizar…) um objeto em um banco de dados relacional?
[/quote]

Você não precisa persistir um objeto em um banco relacional, só o estado dele. Agora, se você quer saber o porquê você deveria usar um banco de dados relacional para persistir o estado de um objeto, existe uma listinha de motivos para isso (além, óbvio, de sistemas legados):
:arrow: todos os objetos do seu sistema cabem dentro do espaço máximo de memória alocado pela sua JVM (2Gb para uma JVM em plataforma 32-bits)?
:arrow: você acredita de verdade que serialização é um meio viável de persistência a longo prazo?
:arrow: como você lida com objetos duplicados que não deveriam existir? como você lida com concorrência? e distribuição/particionamento destes objetos através de várias aplicações?

Se você não quer se preocupar muito com estes aspectos, então você usa um banco de dados relacional. Pode usar um banco de dados XML também, se você quiser. Ou um banco de dados hierárquico.

A partir do momento em que você decidir que seu objeto deve deixar de ser transiente e passar a ser persistente. Isso depende muito da sua aplicação, não existe regra para isso.

Não é natural porque isso é uma falha da “metáfora” sobre orientação a objetos. Toda metáfora computacional falha em algum ponto (aliás, eu aprendi isso na meu curso sobre Human-Computer Interaction na faculdade), e a metáfora de OO não seria diferente. Ou você costuma ver objetos do mundo real sendo “persistidos” por aí?

Defina o que é “elegante”. Usar

// exemplo com JPA
entityManager.persist(obj);

não é elegante o bastante para você? Se você acha que elegância tem a ver com a quantidade de linhas que você usa para realizar uma tarefa (neste caso persistência), acho que o exemplo acima resolve seu problema. Se você acha que isso tem a ver com semântica (meu objeto deve ser persistido por si só ou alguém deve persisti-lo?), é tudo questão de projetar isso de acordo com sua vontade.


public class MeuObjeto {

   // um monte de coisa inútil

   public void persist() {
        entityManager.persist(this);
   }

}

[quote=ptrecenti]
-E porque não utilizar isso http://www.guj.com.br/posts/list/55382.java[/quote]

Dependendo do seu cenário, você pode até pensar em usar DB4O ou alguma outra solução de persistência de estado de objetos de baixa escala. Agora, eu não arriscaria usar DB4O/Prevayler/[coloque aqui o nome do seu sistema de persistência baseado em objetos em memória favorito] em um sistema que precise lidar com uma quantidade de dados maior do que minha JVM pode comportar.

Persistência é uma característica inerente aos objetos. Infelizmente, como o Daniel falou, os idiomas atuais de bancos de dados e de persistência ainda não criaram um mecanismo que corresponda totalmente ao idioma da OO.

Fazer:
entityManager.persist(obj);

Pode parecer elegante, mas a implementação interna do DAO é geralmente traumática. Primeiro porque muitas vezes para persistir o estado do objeto, precisamos persistir também a parte privada do objeto. Nesse caso, ou teremos que publicar um get e set, o que a princípio não o faríamos, ou teríamos que recorrer a reflexão (ou uma framework, que certamente irá usar algo parecido) o que realmente não é nada fácil e gera um código particularmente rebuscado. Ou seja, ambas as alternativas não são suficiente elegantes.

Você ainda pode fazer o objeto persistir a si mesmo. Me parece mais correto, se considerar o idioma da OO, uma vez que persistir no tempo é uma característica intrinseca a todos os objetos. Entretanto, a complexidade de se converter objetos para os bancos de dados atuais ainda é grande, o que gera uma classe tão pouco coesa que, no final das contas, justifica a criação do DAO.

Agora, alguns comentários:

  1. A persistência não precisa ser no formato relacional. Aqui, temos alguns objetos que são persistidos em XML, scripts e outras formas, adequadas a cada aplicação;
  2. Existem desenvolvimentos de bancos de dados orientados a objetos, embora nenhum tenha vingado com tanta força quanto os atuais relacionais. Vale lembrar que a tecnologia relacional é antiga e, portanto, madura.
  3. Muitas vezes é necessário comunicar com sistemas legados, relacionais. Nesse caso, seremos obrigados a nos comunicar com bancos de dados relacionais de um jeito ou de outro.
  4. Existe também o investimento em software de banco de dados legado, feito por administrador, que muitas vezes irão querer mante-lo. É o bom e velho caso do dono da empresa que comprou por um preço altíssimo um Oracle e não está disposto a mudar para um banco não relacional.
  5. Formas serializadas “brutas” são boas para sistemas com pouca manutenção. É o caso de jogos de computadores, por exemplo. Isso porque, quando sua classe muda, a forma serializada perde o valor ou passa a ser difícil de manter.

Deêm uma olhada na discução http://www.guj.com.br/posts/list/55382.java, onde eu exponho as idéias de estou falando.
Acredito que o único problema e o maior problema é o suporte da JVM as atividades de concorrência entre os objetos, o trabalho de sincronização entre as chamadas a um objeto deve ser controlado pela JVM e não no braço.

Quando me refiro a elegância quero dizer que na modelagem os rastros de “persistência” não devem existir, não nem mais nem menos códigos simplesmente não existe.

Quanto ao problema de sistemas legal, os objetos devem dar suporte a este tipo de integração, mas sou mais receptivo a uma abordagem de serviços, não de trabalho braçal.