Há padrões de arquitetura de software estabelecidos a partir do uso do estilo arquitetural de camadas, porém ao unir na prática camadas e tais padrões, alguns detalhes conceituais são compreendidos ou implementados de forma inadequada. O tema apresenta o uso de camadas junto a outros padrões como microsserviços, clean architecture, hexagonal architecture, DDD, dentre outros, destacando os benefícios, boas práticas e pontos de atenção.
A arquitetura de software vem amadurecendo ao longo dos anos, novos estilos e padrões de arquiteturas surgiram e se estabeleceram. Alguns destes ainda são motivos de debates com relação a que categoria se enquadram, ou seja, se são estilos ou padrões.
O guia não pretende entrar neste debate, e sim focar em como essas arquiteturas trabalham associadas ao uso de camadas e para normalizar e facilitar o detalhamento no tema, todas arquiteturas citadas serão tratadas como padrões de arquitetura.
O uso de camadas é uma peça central no detalhamento a seguir, por este motivo é indicado a leitura do tema Camadas para haver um melhor entendimento sobre os tópicos apresentados.
Muitos padrões de arquitetura apresentaram novas formas de organizar, implementar e reutilizar software, e apoiados sobre conceitos como a inversão e injeção de dependências, dentre outros, contribuíram para novas visões e adaptações no uso de camadas.
Porém isso não garante que os softwares estão bem arquitetados e implementados, em muitos momentos os softwares parecem seguir o padrão “Espaguete” de arquitetura, ou seja, tudo misturado e bagunçado.
Na sequência, para os padrões citados é abordado a visão, boas e más práticas junto ao uso de camadas. O detalhe e aprofundamento de cada padrão é está em temas próprios no guia.
MVC
O padrão de arquitetura MVC, assim como o conceito de camadas, é antigo, sendo apresentado pela primeira vez no fim da década de 70. Mas foi sua aplicabilidade em soluções web que o tornou popular e um padrão bastante adotado por frameworks em diversas linguagens. Abaixo algumas:
- Spring MVC, em Java
- Ruby on Rails, em Ruby.
- Django, em Python.
- AngularJS, Ember, em JavaScript.
- ASP.NET MVC, em .net
Em uma visão resumida, esse padrão determina a organização do software em 3 camadas, sendo elas:
- Model: camada de manipulação dos dados.
- View: camada de interação do usuário.
- Controller: camada de controle entre Model e View.
O MVC se tornou um dos padrões mais conhecidos e associados ao uso de 3 camadas, ao ponto de ser confundido por muitos com o próprio conceito de 3 camadas. Ele propõe que a camada Model seja responsável pela leitura e escrita de dados, View pela interação com o usuário e Controller seja a responsável por receber as requisições da View, interagir com a Model e retornar os dados para View.
É uma boa forma de organizar as responsabilidades através do uso de camadas, muitos projetos usam essa arquitetura, muito em consequência do uso de frameworks como os já citados. Porém na prática o código implementado muitas vezes não respeita os conceitos do MVC e menos ainda sobre o uso de camadas.
É comum haver código implementado com situações como:
- Models com atributos referentes a usabilidade da View, como flags de controle e formatação de dados.
- Models convertendo dados para formatos usados na View, como Json, xml, dentre outros.
- Controllers e Views fazendo validações que são de responsabilidade da Model.
- Controllers e Views com lógica de negócio, as quais devem estar nas Models.
- Views interagindo diretamente com Models sem passar pelo Controller.
Na prática, apenas o uso de MVC não garante a aplicação dos conceitos relacionados a camadas, é preciso estar atento e compreender as responsabilidades e limites de cada camada para que isso resulte em implementações de qualidade e organizadas para obter as vantagens do uso de camadas.
Active Records
Este padrão de arquitetura, apresentado por Martin Fowler no livro Padrões de Arquitetura de Aplicações Corporativas, apresenta que um objeto carrega dados e comportamento, e geralmente esses dados são persistentes em um banco de dados, logo a lógica de acesso a dados deve estar neste objeto.
É um padrão apoiado sobre premissas da OO (Orientação/Objeto) e simplifica a forma como desenvolvedores(as) codificam a interação com banco de dados. Porém propor a implementação da lógica de negócio e persistência juntas em uma mesma classe vai contra um dos princípios SOLID, o SRP (Single-responsibility principle).
Essa pequena violação dos princípios SOLID em uma arquitetura de camadas pode causar sérios problemas de organização e responsabilidade do código, a ponto de fazer esse padrão de arquitetura ser considerado por alguns um “anti-padrão”. Na prática ela permite haver código implementado com situações como:
- Camadas superiores não imediatas à de dados fazendo chamadas a ela, mesmo com isolamento estrito.
- Camadas superiores com lógica de fluxo de persistência de dados, que deveriam estar na camada de dados.
- Classes que representam o modelo com excesso de código e lógica de camadas superiores como Controller ou View.
O Active Records é comumente usado junto ao padrão MVC citado no tópico anterior, alguns exemplos famosos são os frameworks: Ruby on Rails para linguagem Ruby e Django para linguagem Python.
A junção ao MVC amplifica as chances de implementações que não respeitam os conceitos relacionados ao uso de camadas, destacando as já citadas no tópico anterior, principalmente em soluções que utilizam modelo server-side.
Este padrão é útil para aplicações simples, então possui aplicabilidade. Porém requer muita atenção de desenvolvedores(as), principalmente quando usado junto ao MVC para que não seja um causador de violações com relação ao uso de camadas.
DDD
Em DDD, tema apresentado no guia, o objetivo principal é estruturar e modelar a implementação do código com foco no domínio do negócio. É uma abordagem que explicitou à desenvolvedores(as) que há uma diferença entre código de infraestrutura do software, de controle da aplicação e de interação do usuário para código focado na lógica e regras de negócio.
Essa abordagem, caminha na direção da visão de camadas, principalmente com relação a camada de negócio. Porém ela é mais profunda, apontando que:
- Algumas camadas lógicas dentro da camada de negócio como Controllers, ou outras relacionadas ao fluxo da aplicação não fazem parte do domínio de negócio.
- Artefatos relacionados ao domínio devem ser agrupados por contextos e não por suas camadas lógicas.
A figura abaixo apresenta o diagrama tradicional de DDD e um paralelo com um modelo apresentado no tema Camadas, unindo os conceitos de DDD para composição da camada de negócio.
Na visão de DDD, a camada de domínio é o ativo de maior valor e importância em um software, sendo ela a camada a ter a maior chance de reutilização. Outras camadas de um software também podem fazer uso de boas práticas do DDD, como a organização por contextos, uso da linguagem ubíqua, dentre outros.
DDD explora outros aspectos e conceitos e neste tópico o guia apenas exemplifica como a arquitetura de camadas e DDD convergem, sendo uma ótima abordagem a ser aplicada no desenvolvimento de software e fortemente recomendada pelo guia.
Hexagonal architecture
Hexagonal Architecture, tema apresentado no guia, também conhecido por “ports and adapters architecture”, é um padrão apoiado sobre o uso de camadas, e que busca uma outra forma de representar e aplicar na prática as questões de organização, isolamento e dependência entre as camadas. Quando criado, teve como motivação os problemas citados no tema Camadas com relação a desorganização no uso de camadas e a infiltração de lógica de negócio em outras camadas.
Abaixo um desenho representado a proposta da Hexagonal architecture.
A proposta é que o software seja implementado sem se preocupar com uma interface para o usuário ou banco de dados. O que remete o foco ao domínio do negócio. Há uma mudança com relação à visão tradicional de camadas, abandonando a visão vertical e trazendo uma visão hexagonal onde cada lado do hexágono representa uma integração, que pode ser vista como outras camadas.
Questões que normalmente estão nas camadas mais superiores ou mais inferiores passam a ser tratadas como Adapters, logo elas podem ser substituíveis. A Application, exibida no centro da figura, passa a ser reutilizável ao trabalhar com “Portas de entrada” para os Adapters.
Esse padrão de arquitetura é um amadurecimento com relação ao uso de camadas e recomendada pelo guia.
Clean architecture
Clean architecture, tema apresentado no guia, aborda uma visão que na prática consolida o uso de camadas, inversão de dependências e DDD. Assemelha-se à proposta da Hexagonal Architecture, mas segue a linha proposta por outro padrão, o Onion architecture.
Seu desenho mais famoso traz uma visão diferente da tradicional de camadas, mas ainda assim é totalmente apoiada sobre o uso delas. Abaixo o desenho citado:
É outra forma de representar a hierarquia entre as camadas, mas mantendo as premissas de isolamento e inversão de dependências. Clean Architecture aborda vários conceitos importantes para implementar software e camadas organizadas e reutilizáveis, como as camadas mais próximas do núcleo definirem as interfaces para persistência e a implementação concreta destas interfaces estar no círculo mais externo fazendo parte de “Frameworks e Drivers”, o que é a inversão de dependências na prática, podendo inclusive também fazer uso de injeção de dependência.
Além disto trabalha sobre a representação de casos de uso, trazendo para o código uma representação mais forte dos casos de uso dos usuários do software, o que acompanha também questões abordadas em DDD.
Este padrão é um amadurecimento com relação ao uso de camadas, e requer desenvolvedores(as) com conhecimento e maturidade nestes temas, além de alguns padrões de projeto. É uma das arquiteturas que proporcionam maior organização das responsabilidades do código sendo fortemente recomendada pelo guia.
Microsserviços
Arquitetura em microsserviços, tema apresentado no guia, se tornou popular na última década e se consolidou como uma opção na construção de soluções. Na relação com o uso de camadas, os microsserviços passam a ser uma divisão física orientada pelo domínio do negócio, e cada microsserviço pode ainda aplicar o uso das camadas lógicas citadas no tema Camadas.
Na figura é exemplificado que cada microsserviço deve nascer em função da segregação de um contexto do domínio de negócio. Esse contexto, segregado em um microsserviço, pode de acordo com a necessidade ser implementado usando todos os conceitos e padrões citados no tema, de forma que independente de seu tamanho ainda possam obter as vantagens do uso de camadas.
Microsserviços permitem dentre muitas vantagens (que não serão abordadas nesse tópico) a escala de partes da solução de forma mais inteligente, porém há um grande risco, por vezes não percebido, relacionado a forma como eles se comunicam. Estando separados fisicamente, eles estão vulneráveis a mesma questão da separação física de camadas, que é a provável comunicação entre eles através do uso de rede.
Para evitar que microsserviços chamem uns aos outros de forma inadvertida, uma boa abordagem é o uso de arquitetura orientada a eventos.
Destacando o objetivo citado no tema Camadas de organizar responsabilidades, o uso de camadas também pode ser aplicado com a finalidade de estabelecer níveis para o uso de acesso de microsserviços.
Um exemplo na figura abaixo:
A exemplo da figura, é possível ter os microsserviços organizados logicamente de forma que:
- Serviços de um domínio de infraestrutura estejam em uma camada inferior e não saibam de forma explícita da existência dos serviços de camadas superiores. São exemplos:
- Serviços de notificação.
- Serviços de autenticação.
- Serviços de cache.
- Serviços de integração com serviços externos.
- Serviços de um domínio Core, ou seja, contextos que fazem parte do núcleo do negócio. Pode-se considerar os contextos cuja entidades são essenciais para operação do negócio, como:
- Contexto de contas do cliente.
- Contexto de usuários do cliente.
- Contextos de cadastros gerais da solução.
- Serviços dos demais contextos, aqui estando os demais serviços de uma solução, os quais provavelmente conhecem os serviços das camadas inferiores, porém os inferiores não os conhecem.
Microsserviços são recomendados para soluções que estão crescendo ou já possuem grande tamanho, porém é importante estar atento aos pontos citados neste tópico e em outros no tema próprio. Para soluções pequenas e simples, ainda é válido iniciar com arquitetura monolítica.
Os padrões de arquiteturas apresentados comprovam como o uso de camadas é importante e está amadurecendo. Porém ainda há no dia a dia o desafio de na prática fazer com que as implementações respeitem os conceitos tanto de camadas quanto dos padrões citados.
É essencial que desenvolvedores(as) adquiram conhecimento e sejam disciplinados no uso dos conceitos para que de fato tenha-se código e camadas organizadas, reutilizáveis e que possibilitem softwares sustentáveis e passíveis de evolução e manutenção.
Acesse os links abaixo para se aprofundar mais sobre conteúdos citados nesse tema!
- Livro Padrões de Arquitetura de Aplicações Corporativas
- Martin Fowler, é um renomado engenheiro de software autor de importantes livros na área de arquitetura de software
- The Onion Architecture, artigo publicado por Jeffrey Palermo detalhando o padrão.
Confira todos os links à conteúdos externos citados nos temas do guia dev!
- 01/02/2021 - Publicação do tema. Autor: Isaac Felisberto de Souza