Atenção: esse artigo tem dois vídeos complementares.
Clique e assista o primeiro!
Clique e assista o segundo!
Esse artigo mostra como unir duas excelentes tecnologias para a criação de uma arquitetura desacoplada para aplicações de negócio. É o ORM NHibernate usado para a persistência e acesso a dados e o WCF (Windows Communication Foundation), usado para a criação de uma camada de Serviços Web.
Para que serve
O NHibernate é uma excelente ferramenta de ORM, que oferece centenas de recursos para o mapeamento entre modelos feitos com a orientação a objetos, e os Bancos de Dados Relacionais. O WCF é a plataforma da Microsoft voltada para a comunicação, e o principal pilar do .NET para a criação da aplicações SOA (Service Oriented Applications).
Em que situação o tema é útil
As técnicas mostradas neste artigo são de grande utilidade para quem busca boas práticas no uso em conjunto das tecnologias NHibernate e WCF. Além disso, serão abordadas práticas do DDD (Domain Driven Design), para a construção de um modelo de Domínio, totalmente isolado dos aspectos de infraestrutura dessa aplicação.
NHibernate com WCF
O WCF, Windows Communication Foundation é uma excelente tecnologia para criar aplicações SOA (Service Oriented Applications). Com ele é possível isolar todo o Domínio e infraestrutura de uma aplicação em um Servidor, oferecendo serviços para as camadas de apresentação. E para a criação de aplicações com o que há de melhor na orientação a objetos, nada melhor de que um ORM robusto e eficiente, e é aí que entra o NHibernate. Esse artigo mostra como unir essas duas tecnologias para criar aplicações com uma arquitetura totalmente desacoplada.
Em desenvolvimento de software, há muito tempo se fala em arquitetura em camadas e desacoplamento. A primeira ideia que se tem sobre essa questão é separar o software em: Dados, Lógica e Apresentação. Essas foram por muito tempo as clássicas “partes” de uma aplicação separada em camadas.
Com o advento da orientação a objetos esse conceito mudou drasticamente. Uma das principais características da orientação a objetos é que uma classe, diferente de uma Tabela de um banco de dados, pode representar dados e comportamentos. Isso por si só já vai de encontro com a ideia primordial de separação de camadas. Além disso, a orientação a objetos não substituiu os bancos de dados relacionais, trazendo um complicador adicional para analistas e programadores: como construir aplicações orientadas a objetos que conversem com bancos de dados relacionais.
A questão é que criar uma aplicação separada em camadas se tornou um trabalho muito mais complexo do que era antes. Agora a preocupação envolve diferentes aspectos e não mais somente dados, lógica e apresentação. Soma-se a isso a atual necessidade que existe em se criar aplicações para Web, ou aplicações que sejam compatíveis com uma forma de comunicação através da Internet. Isso traz mais uma preocupação que deve se ter na hora de planejar as camadas de uma aplicação.
É em cima desse cenário que se baseia este artigo. Aqui será demonstrado como criar uma aplicação em camadas, usando padrões avançados da orientação a objetos para a modelagem de aplicações, conhecidos pela sigla DDD (Domain Driven Design). Para que seja possível utilizar um banco de dados relacional, será utilizada a famosa ferramenta de ORM (Mapeamento Objeto Relacional) chamada NHibernate.
Por fim será demonstrado como é possível associar ao cenário a melhor solução para comunicação via Web que existe na plataforma .NET Framework, o WCF (Windows Communication Foundation). Unir esses padrões e tecnologias em uma aplicação não é fácil, e existem várias precauções que devem ser tomadas para evitar um dos principais males no desenvolvimento de software, o acoplamento.
Separar aplicações em camadas é simples, o difícil é garantir um alto grau de independência dessas partes, para que se um dia for necessário, seja fácil substituí-las. Esse é o grande objetivo e um dos benefícios de se criar uma arquitetura em camadas. Entre outros pode-se citar o alto grau de reutilização, a fácil manutenção durante o ciclo de vida da aplicação, e a capacidade de distribuir fisicamente as camadas das aplicações em diferentes servidores.
Domain Driven Design (DDD)
DDD é uma dessas siglas que aparecem na área de tecnologia e que muita gente fica sem saber exatamente o que é. DDD é Domain-Driven Design, um termo que se tornou muito famoso depois da publicação do livro Domain-Driven Design: Tackling Complexity in the Heart of Software, de autoria de Eric Evans e publicado pela editora Addison-Wesley.
Domain-Driven Design, como o próprio nome diz é uma forma de se construir software orientando toda a atenção para o Domínio da aplicação. O domínio da aplicação é o contexto em que o software irá trabalhar. Se for o desenvolvimento de um software para controle de uma farmácia, todos os processos que envolvem o funcionamento da farmácia fazem parte do domínio.
O domínio da aplicação deve ser expresso e modelado através de uma linguagem ubíqua (Ubiquitous Language). Onde os termos usados têm de ser comuns e conhecidos por todos envolvidos, principalmente aqueles que mais entendem do domínio, os Domains Experts.
Um dos pontos fundamentais do DDD está na modelagem do domínio. E quando se pretende aplicar DDD, é neste ponto onde se encontram as mudanças mais concretas. Se antes (sem o DDD) era comum começar as aplicações modelando um banco de dados, com o DDD é preciso começar modelando um domínio. Um domínio é muito mais do que uma simples estrutura de dados, nele estarão todas as regras de negócio que determinam o comportamento que a aplicação deverá ter.
Sendo assim a modelagem de um domínio é muito mais complexa, e impossível de se fazer simplesmente através de um banco de dados. Para modelar um domínio é necessário utilizar recursos da orientação a objetos, e é por isso que em plataformas como .NET Framework e Java é possível aplicar os conceitos do DDD. Na orientação a objetos é possível modelar as classes contendo não só uma estrutura de dados, mas também modelando comportamentos em métodos.
Enquanto na modelagem de um banco de dados relacional, criam-se tabelas e relacionamentos, no DDD é necessário lidar com: entidades, objetos de valor, associações, agregações, factories, serviços e repositórios (essas são as mais simples, existem outras implementações mais específicas).
Entidades estão para o DDD assim como as tabelas estão para os bancos de dados. Objetos que possuam algum tipo de identidade devem ser modelados como entidades. Como exemplo, no domínio de uma farmácia pode-se ter o “Remédio” como uma entidade, já que é necessário que cada remédio tenha um identificador único.
Objetos que não precisam de uma identidade, e que não mudam de valor no domínio, são geralmente modelados como objetos de valor. No .NET os objetos de valor são comumente criados como ENUMs. Um possível exemplo poderia ser as “Categorias de Remédios”, que possuem valores fixos e não têm identidade. Porém isso depende muito da situação e natureza do domínio.
Entidades e objetos de valor podem se relacionar entre si através de associações, que são facilmente modeladas na orientação a objetos. Objetos que conceitualmente possuem uma ligação mais íntima, ainda podem ser agrupados em agregações. É o clássico exemplo das entidades Pedido e Itens do Pedido, que podem formar uma agregação. Neste exemplo a entidade Pedido é considerada a agregação raiz, ou Aggregation Root.
Entidades, objetos de valor, associações e agregações formam uma estrutura de dados e de comportamento muito elaborada. Mesmo assim há situações onde determinados comportamentos do domínio precisam ser modelados em outros tipos de objetos.
Factories é um ótimo exemplo. Algumas entidades, ou mesmo uma agregação de entidades, precisam de Factories para serem criadas. Isso acontece quando a entidade é muito complexa para se “auto-criar” em um simples construtor.
Outros comportamentos, geralmente regras de negócio mais complexas que envolvem várias entidades, também precisam de um outro tipo de objeto para serem modelados. São os Serviços, ou Domain Services. Não se deve confundir com serviços implementados em WCF ou WebService, aqui se trata de um objeto de domínio que encapsula determinada regra de negócio.
E por fim existe um objeto que é responsável pelo armazenamento e recuperação dos dados do domínio. São os repositórios. Uma das regras fundamentais do DDD é que o domínio não deve depender de nenhuma tecnologia de infraestrutura, isso inclui o Banco de Dados e mecanismos de persistência.
Sendo assim, os repositórios são criados no domínio como simples interfaces, sem nenhuma implementação nos métodos. Na camada de infraestrutura da aplicação é que serão implementadas essas interfaces, isolando qualquer mecanismo de persistência e banco de dados do domínio.
No DDD existem quatro camadas em que a aplicação é modelada. A já citada camada de domínio, que é o coração da aplicação e não deve ter dependência nenhuma com as outras camadas. A camada de infraestrutura onde comumente está um banco de dados e os mecanismos de persistência. Uma camada de aplicação e uma camada de interface de usuário.
A forma como o DDD propõe essas camadas dá margem a diferentes interpretações, e consequentemente diferentes formas de implementação. Esse é um ponto onde não há necessidade de levar o DDD ao pé da letra. O importante é garantir a premissa mais importante do DDD, que é manter a camada de domínio a mais isolada possível de todas as outras camadas da aplicação.
...