Recebi uma pergunta interessante sobre arquietura esses dias. A pergunta era se deve ser possível trocar o método de acesso a dados de um repositório (repositório do DDD) sem influenciar a interface desse repositório. Ou seja, se posso, por exemplo, trocar de Entity Framework (EF) para NHibernate (NH) para Datasets e commands, sem afetar meu repositório.
Oras, teoricamente isso deve ser possível certo? Afinal de contas, onde ficariam o encapsulamento se não fosse? Ah, o mundo perfeito…
Infelizmente, no mundo real, não é assim que as coisas funcionam. A técnica e o framework de acesso a dados que você escolhe influenciam diretamente todo o resto da aplicação. Se eu optar por utilizar EF, por exemplo, minhas entidades herdarão obrigatoriamente de “EntityObject” e implementaria automaticamente “IEntityWithChangeTracker”, “IEntityWithKey” e “IEntityWithRelationships”. Já se usar NHibernate posso trabalhar com POCOs. NH não suporta nativamente o uso de LINQ (ainda), EF suporta. Entidades do EF são mais difíceis de testar, POCOs são bem mais fáceis, o que influenciaria todos os meus testes unitários da camada de domínio, que nada (supostamente) teria que ter a ver com os repositórios (que ficam no meio do caminho entre domínio e infra-estrutura). Tudo isso, e muito mais, influenciaria a maneira com que a aplicação seria modelada e trabalharia com as entidades.
Há ainda momentos em que, simplesmente por ajudar muito, vazamos conceitos do framework de acesso a dados para além do repositório, como ao passar uma Expression a um repositório (algo que funcionaria bem com EF por suportar LINQ), ou um objeto para realizar Query By Example no NH. Nos dois casos, trocar o framework daria uma bruta dor de cabeça se não alterássemos a interface do repositório.
Há ainda um conceito muito importante, que se eu encerrasse o post por aqui muita gente tomaria como óbvio e nem pensaria: o conceito de identidade nas entidades de domínio normalmente é expressado por um identificador, como um campo “Id”, do tipo inteiro, que nada tem a ver com o objeto em questão. É como se eu identificasse um cliente por um “número de cliente” que é algo totalmente aleatório e nada tem a ver com o cliente, e não pelo seu CPF, que é algo real. Pois bem, esse conceito é uma herança da primary key de bancos de dados relacionais. Se utilizássemos bancos de dados orientados a objeto, esse “Id” não precisaria existir, e métodos como “EncontrarClientePor(int id)” também não existiriam. você teria no seu lugar um método mais significativo para o domínio, como “EncontrarClientePor(CPF cpf)”, ou “EncontrarClientePor(Telefone tel)”. Viram como a abordagem de armazenamento de dados influencia a assinatura dos repositórios e toda a aplicação?
Ah, o mundo perfeito…
Giovanni Bassi
Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.