.NET - Domain-Driven Design e Onion Architecture


Neste artigo vamos tratar dos conceitos básicos do Domain-Driven Design(DDD) e a Onion Architecture e como podemos juntar essas duas abordagens.

O que é Domain-Driven Design ?

Antes de responder a esta pergunta precisamos entender o que é o Domain ou Domínio.

O Domain ou domínio é uma esfera de conhecimento, e, refere-se ao conhecimento do negócio que o software esta tentando modelar.

O Domain-Drive Design (DDD) é uma abordagem onde o foco principal esta nos valores reais do negócio, no propósito, no objetivo do negócio, mais do que em tecnologias ou frameworks.

Os conceitos de detalhes da tecnologia são importantes mas são um meio para atingir o objetivo do negócio.

E para poder entender e ter uma compreensão clara do negócio e de seu domínio, é essencial adotar uma abordagem colaborativa envolvendo especialistas técnicos e especialistas em domínio, que devem usar a mesma linguagem para uma comunicação eficaz.

Outro ponto importante é reduzir a complexidade usando design orientado a objetos e padrões de design para evitar ter que reinventar a roda.

Assim, três atuações importantes devem existir na abordagem do DDD:

Os Especialistas em domínio são as pessoas que conhecem as regras de negócios. Eles podem ser gerentes de contabilidade, especialistas em marketing, cozinheiros, garçons, etc. Eles podem ou não ter qualquer conhecimento em tecnologia.

Os Especialistas Técnicos são as pessoas responsáveis por traduzir o conhecimento dos especialistas do domínio em software. Para que essa comunicação seja eficaz, é importante usar uma linguagem comum entre especialistas técnicos e especialistas no domínio. Chamamos isso de linguagem comum ou linguagem onipresente.

A Linguagem Ubíqua, que deve ser utilizada em todas as formas de comunicação, desde reuniões e documentação até o código-fonte, tornando-se o modelo de domínio implementado no código.

Outro conceito importante é definir o limite de atuação de um domínio que é conhecido como Bounded Context.

Bounde Context

Ao usar uma linguagem onipresente, cada termo (embora semelhante) deve ter apenas um significado. Ao contrário da linguagem humana, onde as palavras podem significar coisas diferentes dependendo do contexto, o software não lida bem com a ambigüidade.

Para lidar com isso, o DDD requer que cada idioma pertença a um contexto de aplicativo. Esse contexto é chamado de Bounded Context ou contexto limitado. Ele define um escopo onde uma linguagem onipresente pode ser usada livremente. Fora dele, os termos podem ter outros significados.

Como no DDD a linguagem é o modelo e vice-versa, cada Bounded Context define o escopo da aplicação de um modelo específico. Ou seja, um modelo só é válido dentro de seu próprio contexto limitado, conforme mostrado na figura a seguir:

Outro conceito importante usado o DDD é a Architecture Design que refere-se aos estilos de arquitetura usado na implementação do DDD como : Hexagonal, Onion, Layered, CQRS ,etc.

Quando usamos a abordagem do Domain-Driven Design, podemos usar diferentes arquiteturas. Existe, por exemplo, a arquitetura tradicional de três camadas. Essas camadas podem ser divididas em camadas menores. A ideia básica é ter a camada de apresentação na parte superior, a camada de negócios/domínio no meio e a camada de acesso a dados na parte inferior.

   Arquitetura em Camadas

       

Na arquitetura em Camadas a dependência segue o fluxo de cima para baixo onde Presentation Layer depende da camada Business/Domain e esta depende da camada Data Access Layer.

Onion Architecture

A Onion Architecture é uma arquitetura que fornece uma alternativa robusta para criar aplicativos para uma melhor testabilidade, manutenção e confiabilidade nas infraestruturas como bancos de dados e serviços.

A Onion Architecture é baseada no princípio de inversão de controle. Ela é composta de várias camadas concêntricas que fazem interface umas com as outras em direção ao núcleo. Essa arquitetura não depende da camada de dados, como nas arquiteturas multicamadas tradicionais, mas sim do modelo de domínio.

Podemos encontrar alguns conceitos de Domain-Driven Design presentes na camada de domínio do Onion Architecture, mas é importante destacar que DDD e Onion Architecture não são necessariamente a mesma coisa. Podemos usar Onion sem usar DDD.

O desenho acima é simplificado. Existem outras representações da Onion Architecture que apresentam camadas adicionais, que podem ser subdivididas em camadas menores. Mas a Onion Architecture geralmente consiste em quatro camadas:

  1. Infraestrutura,
  2. Serviços de aplicativo,
  3. Serviços do domínio
  4. Núcleo do domínio

O Domain-Driven Design também tem um conceito de serviço ligeiramente diferente do conceito de serviço de aplicativo. Isso pode causar confusão e nos forçar a sempre qualificar com "Estou me referindo ao serviço de aplicativo" ou "Estou me referindo ao serviço de domínio". Portanto, é mais simples nomear a API da camada de serviço do aplicativo, que também descreve melhor o que essa camada representa.

A seta apontando da camada de infraestrutura para a camada central representa o fato de que cada camada pode ver as camadas subjacentes, mas as camadas mais internas não têm visibilidade ou conhecimento das camadas externas.

A seguir vamos descrever resumidamente cada uma das camadas ou círculos concêntricos:

Core Domain

Quando usamos a Onion Architecture, começamos com a camada central, o núcleo. Mantemos todos os objetos de domínio que têm valor comercial no núcleo. Nunca devemos incluir conceitos tecnológicos como banco de dados, REST ou SQL. A camada central, sendo a camada central, nem sabe que seu domínio, API e infraestrutura existem.

Domain Services

A camada de Domain Services é onde todas as regras de negócios existem. Ao controlar o domínio por meio da API e inserir toda a lógica de negócios dentro do domínio, temos um aplicativo portátil.

API

Usamos a API para nos comunicarmos com o domínio. Para isso, devemos expor apenas objetos imutáveis, evitando o uso indevido da API para obter acesso ao domínio. Se retornarmos objetos mutáveis por meio da API, as pessoas que usam o código podem obter acesso aos componentes do domínio que não pretendemos expor. Embora a API tenha acesso ao Domain Services  ao Core Domain, ela não sabe nada sobre a Infraestrutura.

Infrastructure

Esta é a camada mais externa. Inclui adaptadores para bancos de dados, UI, serviços externos como RESTful, etc. Ela tem acesso a todas as áreas da API, Domínio e Core, embora geralmente a maioria das operações que acessam o Domínio devam fazê-lo por meio da API. A exceção a isso seria algo como interfaces de domínio que contêm implementações de infraestrutura.

Você vai encontrar representações com mais ou menos camadas e com outros nomes dado às camadas mas o que sempre deve permanecer é a regra da dependência onde as camadas externas dependem das internas e não o contrário.

Lembrando que as camadas externas são os módulos de baixo nível e as camadas internas são os módulos de alto nível.

Assim o Domain-Driven Design nos dá uma abordagem mais realista para definir o que realmente tem valor de negócios e com a Onion Architecture, alcançamos um bom nível de desacoplamento e podemos abstrair as especificações de tecnologia que são secundárias para o negócio.

A abstração da infraestrutura torna mais fácil adaptar e adotar novas tecnologias que melhor atendam aos requisitos do aplicativo.

Na próxima parte do artigo vamos mostrar uma a criação de um projeto ASP .NET Core Web API onde vamos usar a arquitetura em cebola ou Onion Architecture.

"Aquele que diz: "Eu o conheço (Jesus)", mas não guarda os seus mandamentos, esse é mentiroso, e a verdade não está nele."
1 João 2:4

Referências:


José Carlos Macoratti