Clean Archtecture: demonstração de um caso prático de "refactoring" total

Clean Architecture: demonstração de um caso prático de refactoring total.

Tal como já foi demonstrado em artigos anteriores neste blogue, a Clean Architecture é flexível o que permite substituir um componente por outro (Teixeira, 2024).

Será demonstrado um caso prático a partir de um simples ficheiro de código até a uma estrutura desacoplada.

Conceitos chave 

Clean Architecture

Robert C.Martin criou a Clean Architecture que é um padrão de design de software em que foco são as regras de negócio empresariais, mais difíceis de mudar (Domain Layer) garantido o desacoplamento de fora para dentro, isto é, tudo o que é externo deve ter um protocolo(Gateways, Repositories, Presenters, .etc) que o implemente. Na Figura 1, encontra-se representada o esquema padrão da Clean Architecture:

 




Figura 1- Clean Architecture

Fonte: (C.Martin, 2012)

 

Cache 

A cache é uma memória de acesso rápido que armazena dados para uso futuro.

Esta memória pode-se encontrar em softwares como por exemplo um browser de Internet (Ravoof, 2023), mas também pode ser encontrado no próprio processador do computador (Leitão, 2016) e em algumas aplicações como Redis.

Cliente HTTP

O cliente HTTP serve-se do protocolo descrito no nome para conectar-se num serviço Web existente em rede. Uma pesquisa do Google trata-se de uma comunicação entre um cliente HTTP e um servidor através de métodos específicos.

Caso de estudo: Cliente em linha de comandos para resgatar filmes de um servidor externo

Para a criação deste cliente, utilizou-se o Node.js em conjunto com algumas bibliotecas como por exemplo, o axios e a cache Redis.

Considere o seguinte ficheiro da Figura 2:


Figura 2- index.js

 

É possível observar que existe algumas dependências externas, como por exemplo, a API (Application Programming Interface) de filmes OpenMovieDatabase. E se amanhã esta API deixar de funcionar e passar-se a chamar outro nome? Como API é externa, não existe controlo do comportamento porque o código desta API pertence a outra pessoa. No entanto, na Clean Architecture, não interessa como é que a API funciona. Apenas terá de implementar um protocolo para resgatar os filmes.

Outra dependência clara, por exemplo na linha 11, é a cache em memória. E se amanhã quiséssemos criar um servidor HTTP que alimente uma base de dados com filmes de várias fontes e quiséssemos remover a cache em memória e substituir pelo Redis por exemplo?

 Uma boa dica para realizar um refactoring em algum código é fazermos a pergunta tal como no parágrafo anterior com a frase “E se amanhã (…)?”. Isto ajuda bastante a descobrir falhas de arquitetura no código.

Inicialmente, começou-se por definir o caso de uso SearchMovies (Figura 3):

  

Figura 3- Caso de uso SearchMovies

 

 

No construtor estão definidos os protocolos com as dependências da fonte de dados e da cache.

Na função execute, a cache é verificada ou não dependendo da sua existência. Se existir, a função this.cache.get() vai tentar buscar os valores existentes. Se existir esses valores são retornados.

Em caso de não existir valores, ou não existir cache, os valores são diretamente retornados da API de filmes linha 16

Após isso definiu-se o contrato da API de filmes (Figura 4):


Figura 4- Protocolo de comunicação com a OMDB

 

O construtor recebe a chave da API necessária para a realização de requests. Na linha 11 é feita a chamada a API de filmes usando a função axios.default.get().

Em caso de não exisitir dados será lançada uma exceção indicando a indisponibilidade da API (linha 19).

 

De seguida desacoplou-se também a interface CLI das regras de negócio, criando um adapter chamada NodeReadlineAdapter:


Figura 5- Adaptador da consola

 Este adapter recebe o caso de uso da Figura 3 e cria uma propriedade para inicializar a interface.

A função init() cria a interface de comunicação e inicializa a consola para leitura de dados realizando todo o processo de negócio através da função this.inputText() da linha 35.



Figura 6- Cache em memória


Figura 7- Cache Redis

A classe da Figura 7 recebe uma conexão do Redis criada externamente no início da aplicação. Pelo desconhecimento total do funcionamento do Redis, optou-se em vez de armazenar em listas (Educative, 2024)  por converter os objetos em string representada por um JSON de filmes o que é acaba por gastar menos memória da cache considerando que cada caractere de uma string vale 1 byte.

Por fim criou-se a raiz da aplicação (Figura 8):


Figura 8- Composite Root

A função initApp conecta-se ao Redis e configura todas as dependências necessárias para aplicação funcionar sendo executada na linha 22.

Resultados:

Pesquisando o nome de alguns filmes, pode-se notar que a aplicação foi buscar os dados à API externa (Figura 9) :

 


Figura 9- Pesquisa de filmes sem cache

Ao fazer a pesquisa uma segunda vez pelo mesmo filme verificou-se que os dados foram resgatados da cache e não da API.


Figura 10- Pesquisa de filmes com cache

 

No entanto, algo que se poderia melhorar neste sistema seria ao fim de algum tempo a cache ser limpa para os padrões iniciais.

Com este artigo, demonstrou-se novamente a flexibilidade da Clean Architecture através do refactoring total de uma aplicação em consola. A experiência com o Redis foi uma novidade para o autor do mesmo


Referências:

C.Martin, R. (2012). Clean Coder Blog. https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

Educative. (2024). Redis Data Types - Complete Guide to Redis. https://www.educative.io/courses/complete-guide-to-redis/redis-data-types

Leitão, M. (2016). Memória Cache.

Ravoof, S. (2023). O Que é Cache? Saiba mais Sobre Esta Tecnologia Comum e Complexa. https://kinsta.com/pt/blog/o-que-e-cache/

Teixeira, A. (2024). Migração de dados usando Clean Architecture. https://programandocomandre.blogspot.com/2024/02/migracao-de-dados-usando-clean.html