Decorator Pattern: Implementando Cache no .NET

Victor Fructuoso
3 min readJan 25, 2021

--

Recentemente fiz uma apresentação sobre o uso de Design Patterns na prática. O objetivo dessa apresentação era demonstrar alguns padrões resolvendo problemas de sistemas reais em alinhamento com os princípios do SOLID.

Neste artigo trago de forma mais detalhada como usei o Decorator Pattern para resolver a necessidade implementar cache na camada de serviço.

Obs.: Esta prática funciona perfeitamente para qualquer camada da sua aplicação, desde que o princípio “Princípio da inversão da dependência” esteja sendo atendido.

Este artigo não entra em detalhes sobre o que é o SOLID ou como funciona uma solução de cache, vamos focar apenas na sua implementação utilizando o Decorator Pattern.

O Problema

Estamos fazendo uso de um serviço que é lento e não sofre mudanças com a mesma frequência em que é chamado, desta forma precisamos otimizar as chamadas a este serviço.

Desenho Inicial

Alternativa 1: Realizar a implementação do cache dentro do serviço, dando ao serviço a responsabilidade gerenciar o uso do Cache.

Alternativa 2: Realizar a implementação do cache em quem chama o serviço, neste caso dando ao controller tal responsabilidade.

Alternativa 3: Implementar o uso do cache de forma isolada, não modificando o funcionamento do serviço, muito menos de quem o chama.

Como vocês devem ter imaginado, as duas primeiras alternativas ferem os princípios “Princípio da responsabilidade única” e “Princípio Aberto-Fechado”

A Solução

Nossa proposta para resolver esse problema é criar duas implementações para a interface do serviço e aplicar o Decorator Pattern para gerar o seguinte fluxo.

Decorate ‘envolvendo’ nosso serviço

A solução consiste em criar uma implementação da interface IDetranVerificadorDebitosService, esta nova implementação fica responsável por gerenciar o cache através da interface IDistributedCache e chamar o _Inner apenas quando a resposta não estiver persistida em cache.

Neste modelo o controller continua dependendo de um IDetranVerificadorDebitosService, porém faremos a injeção de um novo Decorate, tornando a gestão do cache transparente tanto para o Controller quanto para o próprio serviço.

A interface IDistrubutedCache abstrai para o nosso código qual o mecanismo está sendo utilizado para fazer a gestão do cache, o .NET possui algumas implementações prontas para uso bastando apenas indicar qual implementação deve ser usada no Startup

No exemplo abaixo temos a uma implementação fake (também nativa do .NET) comentada e uma segunda implementação usando REDIS, modificar o provider de cache que você gostaria de usar é tão simples quanto isso.

Startup.cs registrando cache distribuído no REDIS

Obs.: Esta configuração deve ser utilizada apenas para ambientes de desenvolvimento, para uso produtivo é recomendado estudar a documentação do REDIS.

Ao colocar a nossa aplicação para rodar e executar várias requisições GET https://localhost:5001/api/Detran/Debitos?Placa=ABC1234&UF=PE podemos notar que apenas a primeira requisição levou o tempo máximo de 5 segundos, as demais tiveram o tempo de execução reduzido por fazer uso do cache.

POSTMAN

Passados os 20 segundos que foram definidos como TTL para o nosso cache, ele é desprezado e uma nova requisição é feita ao serviço.

Consultando chaves de cache armazenadas no REDIS

Segue link do repositório completo no GitHub com este e outros exemplos implementados. https://github.com/fructuoso/DesignPatternSamples

Referências:

Decorator (refactoring.guru)

Caching distribuído no ASP.NET Core | Microsoft Docs

--

--