Arquitetura sem DAO

Uma das pragas dos sistemas escritos hoje em dia é o uso abuviso e inconsciente de objetos intitulados DAO. Se perguntar ao criador do objeto DAO por quê ele precisa deste objeto no sistema ele responde que é para isolar a camada de persistência. Se isso fosse verdade o objeto implementaria o padrão Façade ou Strategy e não o padrão DAO.

O padrão DAO é importante em sistemas orientados a banco de dados. O problema é que muitos dos sistemas de hoje ainda são orientados a bancos de dados, mas os seus desenvolvedores auto-enganam-se até pensar que não são. Apareceu a moda dos sistemas orientados ao domínio. E quem não quer estar na moda ? Afinal o que está na moda sempre é mais caro…

O maior precursor dos sistemas orientados ao domínio foi o filosofia de Desenvolvimento Orientado ao Dominio (Domain Driven Development – DDD, em inglês). Nesta filosofia o desenvolvimento é guiado pelo entendimento e re-estruturação (refactoring) constante do Dominio. O resto da aplicação utiliza o dominio como uma caixa-cinzenta (ou caixa-negra da qual sabemos algumas coisas) e responsabilidade real do funcionamento é do domínio. O resto é apenas suporte para ligar as partes do sistema com o domínio.

Estamos perante uma Paralaxe de Paradigmas. Por um lado o paradigma do uso do DAO como peça importante na comunicação com banco de dados e pivot em sistemas orientados a bancos de dados. Por outro lado o paradigma da orientação ao dominio com uma riquesa inerente em cada entidade. No meio, a necessidade inerente dos sistemas de preservar seus estado entre reboots e o uso de banco de dados para persistir esses dados. A paralaxe está no seu auge quando sistemas orientados a banco de dados são encarados, explicados e vendidos como sistemas orientados ao dominio, mas onde as entidades são pobres e o dominio não passa de um nome bonito para mais uma fachada de persistência em banco de dados.

A Síndrome de DAO está instalada na mente de muitos por não conseguirem se elevar além do topo da onda da paralaxe causada pelo choque entre a orientação a banco e a orientação ao domínio. Todo o munda usa o objeto DAO, mas nenhum desses objetos é realmente uma implementação do padrão de projeto Data Acess Object já que hoje quase todos eles são implementados com base num DomainStorage (personificado pelo Hibernate ou por uma implementação do JPA).

A separação de responsabilidade do domínio e do mecanismo de persistência é uma necessidade se você não quer implementar mecanismos de persistência cada vez que faz um sistema. Para isso nasceu o padrão DomainStore. Mas mesmo assim as pessoas insistem em encapsulá-lo em um DAO. Me ultrapassa a compreensão de por quê alguem faz isto. A única conclusão que posso tirar é que a pessoa não é consciente do mal que está fazendo.

Tendo em atenção que – com base no que vinculado na imprensa e blogs por ai fora – o paradigma da orientação ao dominio não é entendido no seu cerne sendo confundido com os principios da filosofia do Desenvolvimento Orientado ao Domínio. Parece-me que cabe esclarecer como é a arquitetura de um sistema em que não se criam objetos DAO, nem seja orientado a banco de dados.

Claro que, se o seu sistema é orientado a banco de dados esta arquitetura não se aplica.

Anúncios

23 opiniões sobre “Arquitetura sem DAO”

  1. Muito Legal Cara! Seria muito bom se você pudesse fazer um post com exemplos práticos em código Java disso tudo para que possamos entender com maior clareza. Abraço

  2. Estou preparando um artigo com mais ênfase no codigo, mas é difícil encontrar uma aplicação fictícia que exercite todos os aspectos, já que se o domínio for muito pequeno não se vai notar a vantagem. Sugestões?
    Contudo, a arquitetura pode ser usada em qualquer sistema que você faça. E por muito que eu exemplifique o passo final sempre terá que ser dados por vocês.

    Como nota de apoio fique ligado no MiddleHeaven que terá uma estrutura de arquitetura orientada ao domínio “out-of-the-box”. Assim você pode usar nas suas aplicações sem muito esforço.

  3. Sérgio, você coloca EntityManagers, Connections, Sessions, e etc espalhados pelos seus objetos de negócio?

  4. Não, os objetos de conexão, Session/EntityManagers (domainStore) não ficam nos objetos de negocio. Conexão não fica em lado nenhum, chamo do DataSource quando preciso e dou close no fim (na realidade o domainstore é que mexe com isso). O acesso ao domianstore (save,delete, query) fica no repositório. A criação de criterios tb fica no repositório.

  5. Hum, mas o repository seria considerado um conceito de negócio, certo? Você liga objetos específicos da sua implementação de persistência nos seus objetos de negócio?

    Eu acho que o problema do DAO não é a pattern em si e sim criar seus DAOs duma forma que fique lógica de persistência nos seus objetos de negócio.

  6. O repositório não é um conceito de negocio, é um objeto do domínio. Ou seja, o seu cliente não vai lhe dizer “ah! aqui trabalhamos com repositórios” , ele vai dizer “ah! aqui temos produtos que vendemos para clientes” e você vai codificar Produto, Venda e Cliente. Mas como a informação tem que ser procurada depois vc cria repositórios para fazer essas procura. Lembre-se que o repositório é principalmente um objeto que sabe encontrar objetos de entidade.A persistência é um bônus. Eu ligo meu Produto, Venda, Cliente com os Repositórios do domínio. Nenhum deles sabe da existência do banco de dados, conexões, transações, etc… Não ha lógica de persistência nos objetos do domínio. O que ha é lógica de procura. É bem diferente. Por exemplo, um pedido

    public class Pedido{

    public List items(){
    return Dominio.repositorioDe(Item.class).encontraTodosDoPedido(this);
    }
    }

    Esta regra nunca vai mudar porque é a tradução da relação entre Pedido e seus Itens. O como o repositório irá procurar pelos itens , instanciar, fazer cache, etc.. não importa nem para o objeto Pedido nem para quem chama pedido.items()

  7. public class Pedido{

    public List items(){
    return Dominio.repositorioDe(Item.class).encontraTodosDoPedido(this);
    }
    }

    Poderia ser:

    public class Pedido{

    public List items(){
    return pedidoDAO.encontraTodosDoPedido(this);
    }
    }

    Sem problema algum. Ainda estou usando corretamente a pattern DAO.

  8. Não, não está. Esse é o ponto. Porque, ao contrário do repositório, o DAO é um serviço da camada de persistência e não da de domínio, você está misturando camadas. Aí você está colocando detalhes da implementação de persistência nas suas classes de entidade, coisa que não acontece com o respositório.

    Claro, que, provavelmente isso que você está chamando de DAO é na realidade um repositório o que nos leva ao que eu disse inicialmente. Cuidado com a Síndrome de DAO

  9. Cara, que detalhe da implementação de persistência eu estou colocando?
    Esse DAO é uma Interface. O máximo que eu estou expondo é que eu uso DAO para persistência. Talvez seja uma exposição indesejada, mas não acho que vejo grandes problemas nisso. Acredito que a abstração da persistencia já é suficiente.

    Talvez se o eu buscasse meus objetos de outras fontes além do DAO faria sentido. Mas aí quem sabe valeria a pena colocar isso dentro do DAO.

  10. O problema não é que o DAO é ou não um interface. É onde essa interface está. Está na camada de persistencia. Vc vai dar import da camada de persistencia em todas as entidades do seu dominio. Enquanto que se usar reposiotrio ( que não é uma intercace e está na camada de dominio) não terá esse problema.

    Por outro lado num sistema orientado ao domino não ha DAO. Ou seja, se vc quer fazer um

    public List items(){
    return pedidoDAO.encontraTodosDoPedido(this);
    }

    isso significa logo que o seu sistema é (ou pretende ser) orientado ao domínio. O que significa que não deveria existir sequer um DAO no seu codigo. Se existe, das suas uma 1) vc está dando o nome de DAO ao repositorio (Sindrome de DAO) ou 2) vc tem realmente um sistema orientado a banco de dados. Neste caso tentar usar aquele tipo de codigo é forma sofisticada de active record o que acabará sendo um empecilho a longo prazo.

    Veja como vir, não tem como defender o uso de DAO dentro de um Entidade.

    A diferença pode ser singela e imperceptível à primeira vista mas tanto na prática como na teoria é uma enorme diferença. Diferença que sente quando o sistema precisa ser alterado.

  11. Sérgio,

    Não estou gostando do seu rótulo “Sistema Orientado a Banco de Dados” só por que o sistema usa DAO. Não faz sentido algum, DAO tem haver com persistência e não banco de dados (lógico que em praticamente 100% você tem banco de dados, mas eu já – mais de uma vez – fiz DAOs que não acessavam banco de dados).

    Já que não vamos colocar referência a uma interface DAO nos meus objetos de domínio, vamos usar repositorio, que não é uma interface, segundo o que você disse, certo? Então temos as seguintes alternativas:

    1) O repositório vai encapsular um DAO.
    2) O repositório vai ter referência a uma implementação de persistência.

    As duas alternativas não são boas… Na alternativa 1 você cria uma camada que não vai agregar muita coisa á arquitetura do seu projeto e na 2 você vai acoplar seu sistema a uma implementação de persistencia, já que não vai ter nenhuma interface abstraindo a implementação de persistencia.

  12. Vou arriscar e me meter nesse assunto, Sergio, por favor me corrija se eu estiver errado.
    Por definição o DAO não conhece o domínio, DAO não sabe que existe um Pedido, um item, um cliente. O DAO não sabe como funciona um Pedido, o DAO somente sabe como acessar dados seja ele em um SGDB, em um xml, em um arquivo texto, em um sistema de bancos replicados. O Rep é inteligente para conhecer o domínio entender oq ele esta requerendo e traduzir isso para o DAO, e vice versa.
    Apesar de eu usar delphi tenho um Rep e dentro faço chamadas SQL direto para banco de dados via meu drive dbExpress, como sei q não vou mudar esse drive nunca nem perdi tempo criando uma interface DAO. Assim como em Java posso ter dentro do Rep acesso via drive JDBC e não deixaria de ser um DAO, estou correto nessa afirmação?
    Fica aqui minha tentativa de explicação.
    Espero não estar sendo cético na minha colocação apenas quero somar para esse debate, desculpe se estou ofendendo alguém, pois ultimamente as pessoas andam mto ofendidas não sabendo mais debater ou discutir nada.

    Sergio um grade abraço

  13. Rubem, vc acha que o repositório não vai agregar nada. Tlv porque não o usou ainda, vc acha isso. O Repositorio atual como façade para a perssitencia do ponto de vista do dominio. Isso é muito poderoso. Vc pode alterar completamente a persistencia que não vai mudar uma virgula no sistema. Isto é muito util em sistema criados iterativamente. O acesso ao banco é a ultima coisa que vc cria (e não a primeira como um sistema orientado a dados). Por exemplo, meus sistemas sempre têm a dobradinha Usuário-Perfil Os usuários têm cadastro, mas os perfils são fixos. Então o repositorio de perfils é fixo. Todos os objetos Perfil existem apenas na memoria e o repositorio garante que não ha copias. Como são objetos imutáveis isso é um simplificação enorme. Outro exemplo é a famaosa lista de estados. Vc tem uma tabela para isso ? muita gente tem. Com o repositorio vc não precisa. Simplesmente tem uma lista (Map) na memória e pronto.
    Vc poderá pensar que o DAO pode fazer o mesmo. Mas tecnicamente não pode. Um objeto chamado DAO que lesse da memória não seria um DAO. O DAO é um serviço de persistência. Como o Guilherme disse, ele não sabe nada sobre o que o dado é. Por isso ele não pode assumir coisas sobre os dados. O repositório pode.

    O repositório é livre de encapsular uma chamada a DAO ou não. Se ele realmente precisar ele pode. Mas ele pode simplesmente invocar o JDBC diretamente, o Hibernate ou qualquer outra tecnologia que ele quiser. às vezes, entidades diferentes podem ser lidar de lugares diferentes e isso pode levar a usar tecnologias diferentes. O fato dele usar tecnologias de persistência não o torna um DAO porque o objetivo dele não ter ser reaproveitavel. Se a persistência mudar é porque o Repositorio a mudou, enquando que um DAO é um objeto plugável que simplesmente é substituido por outro (outro, não o mesmo) que tem a mesma interface mas implementação diferente. É esta caracteristica plugável do DAO que o torna util para acesso a sistema legados porque no futuro esses sistema serão substituidos e o DAO com eles. Neste caso o DAO é um objeto da camada de integração. Acontece que a integração é via banco de dados. Ele não é realmente um objeto da camada de persistencia per-se.
    Em um sistema que não comunica com sistema legados via banco o DAO é inútil. AI vc quer algo para esconder o JDBC e até usar SQL diferente conforme o banco, mas tudo isso é agnostico. Não depende do sistema. É ai que entra o DomainStore. Mas tanto o DomainStore , como o JBDC , XML , DAO, etc são tecnologias para preservar os dados. O sistema não necessariamente precisa preservar os dados em formas exteriores ( exemplo dos estados) e a responsabilidade de mediar isso é do Repositório.

    O repositório e o DAO têm responsabilidades diferentes.Essa é uma razão muito forte. Não é um simples questão estética.
    Como exemplo, pode dar uma olhada no basecode do middleHeaven o pacote storage cria um DomainStore agnóstico (correntemente para memoria, jdbc, xml e space4j ) baseado no modelo do domínio, e o pacote domain contem os repositorios. Este código ainda está em construção mas já dá para ver a separação de responsabilidades.

  14. Talvez o proprio nome DAO possa estar gerando tal confusão ou não, veja q para o dominio quem acessa os dados de um obj é o Rep. e para o Rep(apesar de fazer parte do dominio) quem faz ou poderia fazer o acesso dos obj seria o DAO. Talvez por definição do nome DAO entende-se que o DAO faz o acesso dos dados do obj no proprio dominio e isso nao pode ocorrer pela definição do papel do DAO.
    Na verdade nao sei pq, mas realmente essa questão do DAO gera confusão, culpa da Sun que colocou no doc do hibernate definições equivocadas e de foruns que borbardeiam com post de como generalizar o DAO, como única saída.
    Porem faltam pessoas no Brasil que conseguem clarear as coisas como o Sergio, depois o papel do Rep fica claro a gente pensa “como nao pensamos nisso antes”.

  15. Ao meu ver, DAO tem haver com obter e manipular objetos – acredito que repositorio tem haver com isso também. Não sei se seria proibido fazer um DAO que acessa objetos em memória. Mas não tem nada no DAO que obrigue ter apenas implementações que acessam bancos de dados relacionais – o objetivo é abstrair isso!

    Agora pare com esse termo “sistema orientado a banco de dados” para determinar arquiteturas que utilizam DAO. Não tem sentido algum, já que eu não acoplo a minha aplicação com banco de dados utilizando DAO.

    Pelo jeito eu estou utilizando DAO da mesma forma que você utiliza um repository.

    []’s

    Rubem

  16. Em um sistema orientado a dominio o dominio vem primeiro. As entidades, os serviços e os reposiotorios. Os serviços são chamados da aplicação. O respositorio chama um DomainStore (repare que o domain store conhece a estrutura do dominio na forma de metadados). É um sistema guiado por eventos que advém dos serviços.

    Em um sistema orientado a dados os dados vêm primeiro. Normalmente na forma de Transfer Objects (TO). Esses dados são puxados por serviços que são chamados por outros serviços num cadeia até ao UI. No save a aplicação chama um Transaction Script que executa um monte de logicas e chama os DAOs para persistir e/ou fazer mais pesquisas intermédias. É um sistema pull-push.

    São arquiteturas diferentes. Metodologia diferentes. Conceitos e padrões de objetos com responsabilidades diferentes.

    Em um sistema orientado a dados os DAO sao fortemente acoplados aos dados e fracamente à tecnologia de persistência. Num sistema oriendato a dominio os DAO são fracamente acoplados com os dados e a tencologia de persistencia. Ou seja, os DAO são agnosticos, funcionam em qualquer sistema. são reaproveitáveis. É essa a diferença. Seus DAOs são reaproveitáveis entre sistemas de dominio diferente ? Se sim, então são realmente agnosticos e uteis e o seus sistema, mesmo sem repositorio é orientado do dominio. DAOS assim evoluem naturalmente para o uso direto de um DomainStore como o Hibernate. Se não , os seus DAO são acoplados , suas entidades acopladas a eles. Eles são específicos demais e seu sistema é orientado aos dados.

    Como falei, a diferença é sutil

  17. Rubem, pelo que acredito, o DAO tem haver com manipular dados na forma bruta. Manipular obj tem haver com o Rep.
    Concordo q DAO nao esta ligado somente a SGDB, por isso que ele é uma interface de acesso a dados brutos. Acho q seu DAO assume responsabilidade do Rep, se isso esta errado, nao sei, porem por definição agredito q sim esta errado, porem ate q ponto e custo beneficio vale a pena alterar isso tb nao sei. Porem vejo q nessa implementação se perde flexibilidade em mudanças futuras, eu tb ja fiz esse tipo de confusao em sistemas anterios. Quando eu digo confusão nao quero estar lhe ofendendo por favor apenas de algum modo definir esse tipo de “erro”.

  18. Sergio, sistema orientado a dominio e sistemas orientados a dados é outro assunto q gera confusão acredito eu, visto pelas longas discusões no GUJ. Ainda mais metendo o TO no meio.
    Visto seu ultimo post, vc acredita que, a insistência pelo DAO tem mais haver pela nao diferenciação de um sistema orientado a dominio e orientado a dados, ou pela síndrome do DAO.
    Pergunto isso pois todos falam mto sobre DDD, e continuam a abortar coisas como o proprio DAO dentro do dominio. isso me aprece uma evolução meio capenga, ou seja, me parece que as tecnologias nem sao absorvidas e ja estamos trocando por outra, ficando resquícios mau entendidos.
    Talvez seja pertinente a abertura de uma nova discussão sobre sistema orientado a dominio e sistemas orientados a dados, visto que em fóruns como o GUJ é impossível falar sobre isso.

  19. Sérgio, você agora esta fazendo uma bagunça enorme com os seus argumentos. Falou tanto sobre sistemas orientados a dados e a dominio. Falou sobre TO 🙂
    Pelo que eu entendi, segundo sua lógica, usar DAO nos objetos de negócio = sistema oriendado a dados. O que não é verdade. Não achei nenhuma definição formal de sistema orientado a dado e sistema orientado a dominio, mas eu suspeito que você esteja abusando do termo. Suponho que quando você fala de sistemas orientado a dados são aqueles sistemas cheios de VO\TO\DTO manipulados por Services\EBJs da vida.
    Pelo visto a questão é nomenclatura, ou o que eu acho que é responsabilidade do DAO e o que você acha que é responsabilidade para DAO.

    Uma coisa é você fazer dos seus objetos VOs burros, outra é você fazer um domínio de verdade e dos seus POJOs chamar um DAO para obter outros objetos ou alterar o estado dos objetos.

    Realmente, o nome “DATA” Access Object não ajuda muito, mas como eu disse, você esta usando repository do mesmo jeito que eu uso DAO.

  20. Não, sistema orientado a dados não significa DAO nos objetos de negocio. Não, sistemas orientados a dados não se medem pelos padrões usados. Portanto, não tem equivalência com TO ou EJB. Aliás EJB é uma tecnologia orientada a domínio. O fato de você chamar o DAO nos objetos de negocio não os torna espertos. Eles continuam burros. Domínio não significa interligar os objetos conforme as suas relações. Leia o meu novo post Dados vs Dominio para entender melhor as diferenças.
    Se vc usa o DAO do mesmo jeito que se usa o repositório em um sistema orientado a domínio, então isso significa que vc está usando o DAO da forma errada! Você está infectado com o Sindrome de DAO. Infelizmente não ha nada mais que eu posso fazer por si enquanto não enxergar isso. Desejo-lhe as melhoras.

  21. A discussão até que estava boa, infelizmente apelou para atacar a pessoa e não o argumento. Paro por aqui.

  22. Você ainda não entendeu o sarcasmo do Sindrome de DAO e achou que o estou atacando ( o que é um outro sintoma, como pode ler no post original). Eu estava tentando ajudá-lo. Já expliquei o que está errado com a sua forma de usar o DAO. Já lhe expliquei as alternativas. Se vc resiste à mudança as únicas conclusões possíveis são que : a) vc não quer mudar , b) vc não sabe que precisa mudar c) vc não consegue mudar. Todas estas opções são sinais de que vc está infectado com o Sindrome de DAO. Isto não é um insulto, é uma constatação. É como dizer que vc tem gripe. Não é um insulto. E a opção de se curar é sua. Por isso eu disse que enquanto vc não enxergar que está doente, não ha nada a fazer. O médico não pode ajudar o paciente que não sabe (ou nega ) que está doente.

Deixe uma Resposta

Please log in using one of these methods to post your comment:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão /  Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão /  Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão /  Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão /  Alterar )

Connecting to %s