Organizando seu projeto .NET com Arquitetura Hexagonal — Parte 02

Alex Alves
4 min readOct 16, 2020

— Ir para Parte 01 —

Agora que sabemos, teoricamente, o que é uma Arquitetura Hexagonal, vamos a parte prática 🚀!

Para isso, desenvolveu-se uma API em .NET Core 3.1 e utilizou-se o Visual Studio 2019 Community.

O modelo de negócio será simples. Teremos, apenas, algumas operações referentes a times de futebol, tais como:

  • Cadastro de um time de futebol e notificação por email
  • Recuperação de todos os times de futebol

Antes de inciarmos, vale ressaltar um ponto. Para desenvolver esse tipo de aplicação é importante saber, muito bem, o que é S.O.L.I.D., Injeção de Dependência e Inversão de Controle.

Show me the Code! 💻

Antes de iniciarmos de fato, vamos definir uma estrutura prévia:

| — src
| — — Adapters
| — — — Driving
| — — — — API
| — — — Driven
| — — — — DataBase
| — — — — Email
| — — Core
| — — — Application
| — — — Domain

Visto isso, vamos partir para criar nossa aplicação! Lembrando que, tirando o projeto da API, todos os demais projetos serão do tipo ClassLibrary. Sendo assim, nossa estrutura ficará assim:

Camada Domain

Nesta camada é onde ficará a declaração das nossas “Portas”/Interfaces (Adapters) de saída para comunicação com o meio externo, além das entidades que representam o nosso negócio e a “porta de entrada” para a regra de negócio especificamente (Services).

Driven Adapters

Neste contexto, teremos duas camadas/projetos. Um representando a comunicação e operações com um banco de dados e outro representando operações de email, como o envio.

Repare que cada projeto “carrega” suas próprias dependências, através das classes “EmailModuleDependency” e “DataBaseInMemoryModuleDependency”, onde há ExtensionMethods para fazer as devidas injeções. Fazemos isso para isolar as dependências de cada projeto da solução como um todo. Isso facilita quando você deseja remover alguma dessas “portas” ou atualizar seus específicos pacotes e a probabilidade de afetar a solução é pequena. Veja abaixo como ficaria o projeto que gerencia o Email:

Criamos a classe e herdamos a interface referente a ela, a qual criamos na camada Domain.

Após isso, fazemos o registro das dependências, onde iremos chamar apenas a Interface da classe “EmailManager”.

Camada Application

Nesta camada é onde ficará as implementações, de fato, das regras de negócio, de acordo com a interface IClubService.

Repare que, além de termos as classes que são as implementações das regras, temos, também, a classe “Applicati onModuleDependency”. Esta classe é responsável por conter todas as dependências desse módulo específico (inversão de controle). Isso é feito nos demais módulos, conforme mostrado acima.

Vamos analisar a classe “ClubServiceManager”:

  • Primeiro ponto é que a registramos com a sua devida Interface “IClubService” a qual será utilizada como porta de entrada para a regra de negócio.
  • Depois disso, recebemos, via construtor, todas as dependências com o mundo externo que necessitamos. No caso as operações com o banco de dados e email.
  • Não utilizamos classes concretas para operar no meio externo, mas sim as Interfaces que, de fato, são as nossas portas.
  • Após termos todas as dependências de que necessitamos, basta realizarmos as regras de negócios devidas

Driving Adapters

São os projetos que irão desencadear alguma ação. Neste caso, temos apenas um único projeto que é a API. E é importante que, para cada projeto desse tipo, adicione-se as dependências das solução, no caso de cada módulo, conforme mostrado abaixo:

Feito isso, podemos acionar alguma ação através das controllers:

Chamando o nosso serviço através da porta/interface de entrada “IClubService”.

Com isso finalizamos nossa parte prática! 😁

Caso queira ver o código deste projeto, acesse-o no GitHub! 💻

Tem alguma dúvida, sugestão ou comentário? Deixe abaixo! 🤓

--

--

Alex Alves

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.