- Qual é o problema com a arquitetura das aplicações atuais?
- Um projeto, na maioria das vezes, é começado pequeno, por uma pessoa e sem saber como será a sua evolução.
- Pode acontecer de novas pessoas entrarem no projeto e não conhecerem as regras que guiam a aplicação.
- Um dos princípios de organização é o MVC ou Model View Controller.
- No MVC a regra de negócio fica na Model, os templates na View e a mediação é feita pelo Controller.
- O MVC não é suficiente para manter uma aplicação com código compreensível durante muito tempo.
- A ideia de utilizar MVC veio de frameworks e a maioria das aplicações estão acopladas de alguma maneira a frameworks.
- Um projeto é iniciado normalmente (1) escolhendo um framework, (2) instalando um esqueleto, (3) removendo códigos de demonstração, (4) gerando entidades e controllers automaticamente e (5) tendo o código final.
- Essa é uma abordagem outside-in e esse não é o diferencial da sua aplicação.
- A parte interna de um problema é a parte mais interessante.
- O teste da parte de fora é mais lento.
- As bibliotecas e frameworks são responsáveis pelo encapsulamento das coisas.
- O código que é altamente acoplado ao mecanismo de entrega.
- Isso torna a reusabilidade do código impossível.
- É impossível executar o código mais de uma vez.
- Falta a intenção do código ser explicitada.
- São vistos apenas dados passando através das camadas e não sabemos nem como e nem porquê.
- Normalmente utilizamos como referência código da documentação como RAD e não temos a intenção.
- O CRUD é útil em diversas ocasiões mas não em todas.
- Alguns problemas são:
- acoplamento ao framework
- acoplamento ao mecanismo de entrega (por exemplo, a web)
- testes lentos
- falta de intenção do código
- Devemos encontrar o que é a essência da nossa aplicação.
- A essência de uma aplicação pode ser chamada de core da aplicação ou coração da aplicação.
- O termo coração da aplicação nos remete ao livro Domain-Driven Design do Eric Evans.
- "The heart of software is its ability to solve domain-related problems to its users."
- "All other features, vital though they may be, support this basic purpose."
- O que é importante para a sua aplicação é o seu modelo de domínio ou domain model e as interações que são feitas com ele e isso constitui as uses cases da sua aplicação.
- O que não é importante é saber qual banco de dados ou framework utiliza.
- O core domain não precisa conhecer nada do mundo externo. Não importa se quem o chama é uma pessoa ou uma máquina.
- A camada existente entre a aplicação (core domain) e o mundo externo é a camada de infra-estrutura.
- Na camada de infra-estrutura existirá código responsável pela comunicação da aplicação com o mundo externo como a web, linha de comando, sistema de arquivo, sistema de filas, banco de dados ou envio de e-mail.
- Uma camada é responsável pela separação de coisas.
- Existem regras para cruzar uma camada como a comunicação só pode se dar em uma direção.
- Uma camada possui limites.
- Artigo Screaming Architecture do Robert Martin.
- Uma arquitetura limpa é relacionada a uma arquitetura hexagonal.
- Robert Martin propôs que caso haja dependências entre camadas que elas sejam das camadas mais externas para as camadas mais internas ou nas mesmas camadas.
- O que cruza os limites das camadas são as mensagens ou chamadas de métodos.
- As chamadas de métodos ou funções juntamente com seus argumentos são mensagens enviadas.
- Os argumentos de métodos ou funções podem ser encapsulados em um objeto para serem enviados nas mensagens.
- Uma aplicação permite o envio de mensagens ao expor as portas de entrada ou input ports. Por exemplo, rotas web, CLI ou REST API.
- Cada lado do hexágono representa uma porta de entrada.
- A motivo de ser um hexágono é qua a maioria das aplicações têm em média 6 portas de entrada.
- Cada porta utiliza um protocolo de comunicação. Por exemplo, a porta web fala utilizando HTTP e a porta de mensagem fala utilizando AMQP.
- Uma requisição HTTP é traduzida (utilizando Controllers, Requests e Forms) para conversar com a aplicação internamente (Entities, Value Objects e Repositories).
- O processo de tradução de uma requisição HTTP para algo que possa ser utilizado pelo core domain é chamado de adapters. conjunto de código
- Não confundir com o padrão de projeto Adapter.
- Ports and Adapters é um alias para Hexagonal Architecture e foi inventado pelo Alistair Cockburn.
- O artigo original sobre arquitetura hexagonal pode ser encontrada aqui.
- As portas permitem que a comunicação aconteça.
- Pensando na aplicação como um objeto (com a sua lógica interna escondida) as portas permitem que pessoas e sistemas se comuniquem com ela.
- Para cada porta existe um adapter.
- Os adapters são responsáveis por traduzir mensagens do mundo externo para algo que seja compreensível dentro da aplicação.
- Um comando é criado a partir de uma requisição HTTP para representar a intenção de um usuário.
- Um comando é um objeto auto-contido que não se trata mais de web, de objetos de requisição ou objetos de formulário.
- É uma ótima ideia criar um comando a partir de uma requisição web pois se deixa clara a intenção do usuário.
- Evita-se que a intenção do usuário seja perdida ao copiar os dados entre as camadas.
- As principais características de um comando são:
- expressar a intenção desejada
- implicar em mudanças
- diz que algo deve acontecer na aplicação
- independente de mecanismo de entrega
- pode ser via web ou console
- tratar-se apenas de uma mensagem
- não é capaz de fazer nenhuma alteração por si só
- é passado para uma parte da aplicação capaz de fazer algo
- Um command handler é a parte da aplicação responsável pela manipulação de um comando.
- Um command handler pode ser chamado
RegisterPatientHandler
e aceitar um comando chamadoRegisterPatient
. - Um command bus pode ser utilizado para distribuir os comandos para seus respectivos handlers.
- Pode-se utilizar alguma biblioteca para command bus como SimpleBus ou Tactician.
- Recebe-se uma requisição HTTP através da porta web. A requisição HTTP passará pelas camadas de infraestrutura, aplicação até chegar na camada de domínio.
- A camada de infraestrutura contém tudo o que é necessário para traduzir a requisição HTTP para algo compreensível pela aplicação. Por exemplo, objetos de
Request
,Controller
eForm
. - A camada de aplicação contém tudo o que é necessário para realizar ações. Por exemplo, objetos de command e command handler.
- A camada de domínio contém o domínio da aplicação como entidades e repositórios.
- Uma entidade, que está na camada de domínio, utiliza um entity manager, que está na camada de infraestrutura, para realizar a persistência utilizando a porta de persistência.
- O problema é que uma uma camada interna não pode depender de uma camada externa.
- Para solucionar esse problema utiliza-se o princípio de inversão de dependência.
- Nesse caso, define-se o repositório como uma interface na camada de domínio e faça a implementação na camada de infraestrutura depender dela.
- Uma vantagem da utilização dessa abordagem é utilizar uma implementação para testes de banco de dados em memória.
- "A good software architecture allows decisions [...] to be defererd and delayed." por Robert Martin em Screaming Architecture.
- A arquitetura hexagonal permite uma melhor separação de responsabilidade com as camadas de core (domínio e aplicação) e infraestrutura.
- Alguns projetos podem separar os códigos em diretórios de domínio, aplicação e infraestrutura.
- Códigos que se encontram em controllers podem ser movidos para os command handlers.
- A arquitetura hexagonal dá suporte para ideias como DDD, TDD, BDD, CQRS e event sourcing.
-
-
Save wilcorrea/17b47203a0c54f55b17244bba8d6da16 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment