Injeção de dependências para uma Arquitetura limpa
Tags: javascript, typescript, frontend, architecture
Published: 2023-05-24 02:27:05

Parafraseando <a href="http://cleancoder.com" target="_blank">Robert C. Martin</a> em seu livro <a href="https://www.amazon.com.br/Arquitetura-Limpa-artes%C3%A3o-estrutura-software-ebook/dp/B085PP6Y8P" target="_blank">Arquitetura limpa</a>, mais precisamente no capítulo 5, quando fala sobre **inversão de dependência** (pag 44). O paradigma OO geralmente proporciona maior facilidade para a aplicação da inversão de dependências, este é um dos princípios SOLID e permite direcionar as dependências do código. Assim não precisamos alinhá-las junto ao fluxo da aplicação de forma acoplada e por consequência dificultando mudanças no projeto.

A possibilidade de escolher responsáveis para determinadas tarefas e trocá-los a qualquer momento nos dá poder! E o que fazemos com ele? Por exemplo, você pode reorganizar as dependências do código para que regras de negócio não dependam de componentes front-end ou da técnica adotada e usada até este momento do projeto para acesso a dados.


![Gráfico de dependências](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u851jy3snzsi2ogy8nkl.png)


Note o domínio (regras de negócio) no canto inferior esquerdo, isolado. Enquanto a camada data-access (acesso a dados) faz o intermédio entre ela e as camadas feature e a aplicação, que é onde estão nossos componentes front-end.

Pode não ser intuitivo aos primeiros olhares, mas isso faz com que essas camadas se tornem plug-ins para as regras de negócio, que é onde há menos mudanças e maior valor no software.

Além disso, as regras de negócio, a UI e o acesso a dados podem ser transpilados em pacotes separados e independentes, unidades publicáveis com as mesmas dependências. Contudo, o pacote de regras de negócio não dependerá dos pacotes que contém a UI e o acesso a dados.

![Gráfico de tarefas executoras](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fanqp8ua3w27lmn0aoua.png)


Significa que as regras de negócio podem ser implantadas independentemente da UI e da camada de acesso a dados. Que por sua vez, permite que haja deploy em momentos diferentes, independentes, permitindo que times diferentes trabalhem em seus respectivos pacotes sem impactos entre eles. Pois mudanças em componentes da UI ou do acesso a dados, por exemplo, não devem ter nenhum efeito negativo sobre as regras de negócio. 

Veja este repositório: <a href="https://github.com/guiseek/getlab" target="_blank">getlab</a>, ele está dividido em pacotes como camadas e suas respectivas responsabilidades, como abordado até agora. A branch main, a camada de acesso a dados, está usando Storage do navegador como base de dados.

Para fazer a substituição de Storage para acesso a uma API REST com persistência em uma base NoSQL, foi necessário implementar as classes responsáveis por isso, ou seja, classes concretas para <a href="https://github.com/guiseek/getlab/blob/mongodb/libs/data-access/src/lib/infrastructure/team-http.repository.ts" target="_blank"> TeamRepository</a> e <a href="https://github.com/guiseek/getlab/blob/mongodb/libs/data-access/src/lib/infrastructure/schedule-http.repository.impl.ts" target="_blank">ScheduleRepository</a>, depois substituí-las nos registros de dependências. Como está na branch mongodb.

Se antes estávamos usando desta forma

```ts
register({
  for: TeamRepository,
  use: TeamStorageRepositoryImpl,
});
```
Podemos apenas alterar quem será usado a partir de agora
```ts
register({
  for: TeamRepository,
  use: TeamHttpRepositoryImpl,
});
```
[Veja o código](https://github.com/guiseek/getlab/blob/afccbeebfd9003f9bcad13f428f9e66505fcefa7/libs/data-access/src/lib/providers.ts#L44)

Agora sempre que pedirmos TeamRepository, teremos uma instância de TeamHttpRepositoryImpl

```ts
const teamRepository = inject(TeamRepository)
// TeamHttpRepositoryImpl
```

Sem que nenhuma alteração em regras de negócios ou componentes da UI fossem necessárias.

## Conclusão

Vimos que devemos dividir as responsabilidades do código em camadas, vimos também que uma responsabilidade não deve interferir em outras e que principalmente devemos proteger a camada onde estão nossas regras de negócios. Com isso é possível ter times trabalhando de forma isolada e independentes. Mas como isso pode ser feito?

### Vejo duas soluções / oportunidades

1. Apresentar o design pattern **Dependency Injection** (Injeção de Dependências);
2. Falar sobre divisão de camadas utilizando arquitetura em monorepos;

Digo isso pois em uma aplicação Front-end comum, não basta dividir o código em camadas de diretórios para que seja possível executar build como pacotes independentes e é neste ponto que entra a arquitetura de monorepos, no entanto, é um tema que gera assunto para um outro artigo inteiro, então escreverei o próximo aprofundando estes dois assuntos, combinado?

Abraços