Arquitetura Limpa: O conceito por trás do código
Tags: architecture, tutorial, cleanarchitecture, braziliandevs
Published: 2022-05-07 20:37:11

A utilização de sistemas computacionais se torna cada vez mais presente e essencial na sociedade. Desde tarefas cotidianas, como pedir refeições pelo celular e fazer transações bancárias, até realização esporádica de exames de imagem fazem uso de softwares. Para manter essa demanda crescente é necessário produzir e manter softwares dentro de custos adequados, visando o crescimento e a otimização do mesmo sem prejudicar o que já foi desenvolvido.

A engenharia de software é uma disciplina da engenharia que se preocupa com todos os aspectos da produção de software, tendo como principais atividades a especificação, o desenvolvimento, a validação e a evolução do software (SOMMERVILLE, 2010). Como o software é abstrato e não limitado a leis físicas, isso simplifica a engenharia de software. Do mesmo modo que essa simplificação fornece poder para que o desenvolvedor construa aplicações de maneira otimizada, a falta de restrição também pode tornar o software em algo complexo e difícil de manter.

Como as construções físicas são compostas de componentes menores como tijolo, concreto ou madeira, as construções de softwares são compostas por componentes de softwares que são feitos de outros componentes de softwares, e ambos os tipos de construções possuem uma arquitetura por trás com o objetivo de manter essa estrutura firme e segura. Um conceito da engenharia de software essencial para esse artigo é o de arquitetura de software. A arquitetura de software de um programa ou sistema computacional é a estrutura ou estruturas do sistema, que abrange os componentes de software, as propriedades externamente visíveis desses componentes e as relações entre eles (BASS; CLEMENTS; KAZMAN, 2012).

As mudanças que ocorrem durante o desenvolvimento de software são inevitáveis, e uma boa arquitetura tem como objetivo diminuir o tempo para executar essa mudança, que consequentemente diminui os custos financeiros e esforço. Uma arquitetura deve além de atender as demandas imediatas dos usuários, desenvolvedores e proprietários atender também essas expectativas ao longo do tempo (MARTIN, 2017).

Do mesmo modo que na arquitetura de construções existem diferentes estilos, como por exemplo o clássico, o romântico e o barroco, na arquitetura de software existem tipos arquiteturais como a Arquitetura Cliente-Servidor (Client-server Architecture), a Arquitetura Cebola (Onion Architecture) e a Arquitetura Limpa (Clean Architecture). Entretanto toda arquitetura de software tem o objetivo comum de dividir o software em camadas, tendo pelo menos uma camada para as regras de negócio e uma para as interfaces de usuário e sistema (MARTIN, 2017).

Uma arquitetura não deve apenas atender as demandas dos usuários, desenvolvedores e proprietários em um determinado momento, mas também corresponder a essas expectativas ao longo do tempo. Robert MARTIN (2017) propôs a Arquitetura Limpa com o objetivo de promover a implementação de sistemas coesos, independentes de tecnologia e favorecendo a reusabilidade do código. A seguir, nós veremos em mais detalhes essa arquitetura.

## Arquitetura Limpa

O conceito de Arquitetura Limpa foi definido por Robert C. Martin (MARTIN, 2017) no seu livro intitulado ”Arquitetura Limpa: O guia do artesão para estrutura e design de software”. Nessa arquitetura, os sistemas podem ser divididos em dois elementos principais: a **política** e os **detalhes**. A política são as regras e procedimentos de negócio e os detalhes são os itens necessários para a realização da política.(MARTIN, 2017) É a partir dessa divisão que a Arquitetura Limpa começa a se diferenciar dos outros padrões arquiteturais. O arquiteto deve criar uma forma do sistema reconhecer a política como elemento principal do sistema, e os detalhes como elementos irrelevantes para a política.

Na arquitetura limpa não é necessário escolher no início do desenvolvimento o banco de dados ou framework, pois todos esses são detalhes que não interferem na política e consequentemente podem ser alterados ao longo do tempo.

### Divisão de Responsabilidade

Na Arquitetura Limpa há uma divisão de camadas bem definida. A arquitetura possui independência de framework, ou seja, as camadas internas que contém as regras de negócio não dependem de nenhuma biblioteca de terceiros, o que permite ao desenvolvedor utilizar um framework como ferramenta e não adaptar o sistemas para atender as especificações de uma determinada tecnologia. Outras características da Arquitetura Limpa são: testabilidade, independência da UI, independência do banco de dados e independência de qualquer agente externo (as regras de negócio não devem saber nada sobre as interfaces do mundo externo). 

Para ilustrar todos esses conceitos foi criado um diagrama apresentado na figura abaixo.

![Clean Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swb7368xadsc5xf6eb0c.png)

Cada círculo da figura representa uma área diferente do software, sendo na parte mais interna as políticas e na mais externa os mecanismos. 

A regra principal para a Arquitetura Limpa é a Regra da Dependência, que diz que as dependências de um código fonte devem sempre apontar apenas para dentro, ou seja, na direção das políticas de nível mais alto. Dito isto, podemos afirmar que os elementos de um círculo mais interno não podem ter nenhuma informação sobre os elementos de um círculo mais externo. As classes, funções, variáveis, formato de dados ou qualquer entidade declarada em um círculo externo não deve ser mencionada pelo código de um círculo interno.

O círculo mais interno é o de Entidades, nele estão reunidos os objetivos de negócios da aplicação, contendo as regras mais gerais e de nível mais alto. Uma entidade pode ser um conjunto de estrutura de dados e funções ou um objeto com métodos, contanto que essa entidade possa ser usada por diversas aplicações. Essa camada não deve ser alterada por mudanças nas camadas mais externas, ou seja, nenhuma mudança operacional em qualquer aplicação deve influenciar nesta camada.

A camada de casos de uso contém as regras de negócio específicas da aplicação, agrupando e implementando todos os casos de uso do sistema. Os casos de uso organizam o fluxo de dados, para e a partir das entidades, e orientam as entidades na aplicação das Regras Cruciais de Negócios para atingir os objetivos do caso de uso (MARTIN, 2017). Essa camada também não deve ser afetada pelas camadas mais externas e suas mudanças não devem afetar a camada de entidades. Entretanto, se os detalhes de um caso de uso mudarem, uma parte do código desta camada será afetada.

A camada de adaptadores de interface possui um conjunto de adaptadores que fazem a conversão dos dados para o formato mais conveniente para as camadas ao seu redor. Em outras palavras, ela pega os dados de uma base de dados, por exemplo, e converte para o formato mais conveniente para as camadas de entidades e casos de uso. O caminho inverso de conversão também pode ser feito, dos dados das camadas mais internas para as camadas mais externas. Os apresentadores, visualizações e controladores pertencem a esta camada.

A camada mais externa do diagrama geralmente é composta pelos frameworks e bancos de dados. Nessa camada é feito o código que estabelece a comunicação com a camada de adaptadores de interface. Todos os detalhes ficam nessa camada, a web é um detalhe, base de dados é um detalhe, e todos esses elementos ficam na camada mais externa para não correr risco de causar interferências nas demais (MARTIN, 2017).

Mas se as camadas são tão independentes, como é feita a comunicação entre elas? Essa contradição é resolvida com o Princípio de Inversão de Dependência. Robert C. MARTIN (2017) expõe que pode-se organizar as interfaces e relacionamentos de herança para que as dependências do código fonte fiquem opostas ao fluxo do controle nos pontos certos. Se um caso de uso precisa se comunicar com o apresentador, essa chamada não pode ser direta, pois violaria a Regra da Dependência, então o caso de uso chama uma interface do círculo interno e o apresentador no círculo externo que faz a implementação. Essa técnica pode ser utilizada entre todas as camadas da arquitetura. Os dados que trafegam entre as camadas podem ser estruturas básicas ou objetos de transferência de dados simples, sendo esses dados apenas argumentos para chamadas de função. Não devem ser transmitidas entidades ou registros das bases de dados para não violar a Regra da Dependência.

## Conclusões

Não existe uma arquitetura que seja a "bala de prata" e consiga resolver todos os problemas. E não é a Arquitetura Limpa que veio para isto. 

Uma vez que a base da aplicação foi criada, a Arquitetura Limpa ajuda a manter e evoluir a aplicação sem que seja necessário muito custo (seja de recurso físico ou tempo). Essa ajuda se dá pelo fato de suas camadas serem independentes e pelo uso constante dos padrões de projetos, com isso as alterações de uma parte determinada do sistema tendem a não interferir com o funcionamento do restante da aplicação.

Em contrapartida, é necessário uma equipe mais experiente de desenvolvedores para atuar no sistema. É preciso de conhecimento de padrões de projeto para que consiga manter e estruturar o software. Também leva mais tempo do que uma aplicação MVP simples para que consiga ver os primeiros resultados, sendo importante ter um alinhamento forte com o cliente para deixar as vantagens futuras claras.

Por fim, conclui-se que para aplicações que tendem a crescer e se manter por muitos anos, a abordagem da Arquitetura Limpa é uma boa solução para ser utilizada. No entanto, para sistemas simples e que não evoluam, talvez não vale o esforço com tamanha arquitetura, sendo mais sábio seguir por padrões arquiteturais mais simples. 


### Referências

- SOMMERVILLE, Ian. Software Engineering. 9. ed. Harlow, England: Addison-Wesley, 2010. ISBN 978-0-13-703515-1.
- BASS, Len; CLEMENTS, Paul; KAZMAN, Rick. Software Architecture in Practice. 3rd. ed. [S.l.]: Addison-Wesley Professional, 2012. ISBN 0321815734.
- MARTIN, Robert C. Clean Architecture: A Craftsman’s Guide to Software Structure and Design. 1st. ed. USA: Prentice Hall Press, 2017. ISBN 0134494164.