Entendendo conceitos da Arquitetura limpa
Published: 2023-10-11 02:14:27

## Tabela de Conteúdo

- [**Prólogo**](#prólogo)
- [**Camadas**](#camadas)
   * [**Entidades**](#entidades)
   * [**Casos de uso**](#casos-de-uso)
   * [**Adaptadores de interface**](#adaptadores-de-interface)
   * [**Framework e drivers**](#framework-e-drivers)
- [**Conclusão**](#conclusão)
- [**Referências**](#referências)

## Prólogo

Já faz algum tempo que venho me aventurando estudando um pouco mais sobre arquitetura e design de software, e recentemente acabei me esbarrando no conceito de Arquitetura Limpa.

Esse padrão foi proposto por Robert C. Martin (Uncle Bob) em uma postagem em seu blog em agosto de 2012. Este padrão tem como objetivo separar o software em camadas, onde quanto mais interno, maior é o nível do software.

Essa arquitetura tem como objetivo produzir sistemas que são:

- **Independência de frameworks**: a arquitetura não depende da existência de nenhuma biblioteca externa. Isso permite que você use os frameworks como ferramentas em de vez de ser obrigado a adaptar seu sistema a ele;

- **Testabilidade**: as regras de negócio podem ser testadas sem a UI, banco de dados ou qualquer outro elemento externo;
- **Independência de UI**: A UI pode mudar sem afetar o resto do sistema. Uma UI web pode ser substituída, por uma de console por exemplo.
- **Independência de banco de dados**: Você pode trocar o MySql por Mongo por exemplo sem afetar as regras de negócios;
- **Independência de fatores externos**: Suas regras de negócios não sabem nada sobre as interfaces do mundo externo.

## Camadas

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdl5tsmvm4coswpzh1z6.png)

O diagrama acima é uma representação da arquitetura limpa criado pelo próprio autor. Por padrão o autor divide o sistema em quatro camadas: **Entidades**, **Casos de uso**, **Adaptadores de interface** e **Frameworks** e **drivers**. Quanto mais interno, maior é o nível do software. Os círculos mais externos são mecanismos. Os círculos mais internos são políticas.

A principal regra desse padrão é a Regra da Dependência. Essa regra diz que as dependências do código só podem apontar para dentro. Um círculo interno não pode saber qualquer coisa sobre algo em um círculo externo.

Geralmente resolvemos essa aparente contradição usando o [Princípio de Inversão de Dependência](https://en.wikipedia.org/wiki/Dependency_inversion_principle). Em uma linguagem orientada a objetos como o Java, por exemplo.Podemos utilizar interfaces e relacionamentos de herança de modo que as dependências do código-fonte se oponham ao fluxo de controle.

### Entidades

No círculo mais interno temos as entidades. As entidades são responsáveis por manter toda a regra de negócio da aplicação. Mas afinal, o que é uma regra de negócio? Robert Martin define regras de negócio como:

> Regras de negócio são regras e procedimentos que geram ou economizam dinheiro para a empresa. [..] Podem gerar ou economizar dinheiro mesmo se forem executadas manualmente.

Vale destacar o último trecho da explicação no qual o autor menciona que uma regra de negócio pode gerar ou economizar dinheiro mesmo se forem executadas de forma manual. Por exemplo, um banco cobrar N% de juros por um empréstimo é uma regra de negócio, visto que não importa se essa informação é calculada pelo computador ou por uma caixa com um ábaco. Chamaremos essas regras de **Regras Cruciais de Negócio**.

As regras de negócio normalmente exigem alguns dados para trabalhar. Por exemplo, continuando com o exemplo anterior, para realizar um empréstimo precisamos de um **saldo**, uma **taxa de juros** e um **cronograma de pagamentos**. Chamaremos essas informações de** Dados Cruciais de Negócio**. Esses dados existiriam mesmo se o sistema não fosse automatizado.

Juntando as **Regras Cruciais de Negócio **e os **Dados Cruciais de Negócio **conseguimos construir a nossa entidade Empréstimo. Uma entidade é um objeto contido em nosso sistema. Ela incorpora um pequeno conjunto de regras cruciais de negócio que operam em cima dos dados cruciais de negócios.

Quando criamos esse tipo de classe, estamos reunindo o software que implementa um conceito crucial para o negócio onde estamos separando esse software de todas as outras questões do sistema automatizado que estamos construindo. A entidade é puro negócio e nada mais,

Importante ressaltar que não é necessário uma linguagem orientada a objetos para se implementar uma entidade. Basta que você reúna os dados e as regras cruciais do negócio em um módulo único e separado do restante do sistema.

### Casos de uso

Ao contrário das regras de negócio que são puras e podem ser executadas manualmente, os casos de uso não seriam executadas em um ambiente manual visto que só fazem sentido para sistemas automatizados. Segundo Robert Martin um caso de uso é:

> Caso de uso é uma descrição da maneira como um sistema automatizado é usado. Ele especifica a entrada e a a ser fornecida pelo usuário, a saída retornada e os passos de processamento envolvidos na produção dessa saída.

Casos de usos são nada mais nada menos que objetos com métodos que implementam as regras de negócio da aplicação, além de um conjunto de dados que serão manipulados e as referência para as Entidades com as quais interage. Em suma, os casos de uso especifica como e quando as Regras Cruciais de Negócios dentro das entidades serão invocadas.

<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsvczerrcarp1smddkgk.png" alt="my alt text"/>
  <figcaption>Exemplo de casos de uso</figcaption>
</figure>

A figura acima representa um exemplo de caso de uso de uma aplicação usada por bancários para criar um novo empréstimo. Por determinação do banco, para oferecer um empréstimo para um cliente é necessário validar seus dados além que sua pontuação de crédito deve ser superior a 500 pontos. Com isso o banco pode determinar que o sistema não proceda com a tela de estimativa de pagamento até que a tela de informações pessoais seja preenchida e verificada.

### Adaptadores de interface

<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zqelqyomszrxyezcq2jd.png" alt="my alt text"/>
  <figcaption>Adaptadores de interface funcionam como adaptadores de tomadas
</figcaption>
</figure>

Esta camada é composta por um conjunto de adaptadores de interface que convertem dados no formato que é mais conveniente para os casos de uso e entidades, para o formato mais conveniente para algum agente externo como a base de dados ou a web.

### Framework e drivers

<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ec16v4gn3t1swqe579ey.png" alt="my alt text"/>
  <figcaption>Frameworks web estão localizados nesta camada
</figcaption>
</figure>

## Conclusão

Ao separar o software em camadas e obedecer a regra da dependência a aplicação criada será altamente testável e de fácil manutenção, visto que quando uma das partes externas se tornar obsoleta, como a base de dados é substituir por outro atualizado com o mínimo de esforço.

## Referências
- **Blog Clean Coder**
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
- **Livro Arquitetura limpa: O guia do artesão para estrutura e design de software**