IoC é a melhor estratégia para desacoplar um sistema. Facilita a criação de testes, separa as dependências e isola o domínio. No entanto existe uma técnica, bem pouco usada, que permite interceptar um componente e adicionar novos comportamentos, e ainda assim executar o componente original.
A Importância do Desacoplamento de Sistemas com IoC
Se houvesse uma forma de definir performance em uma única palavra, Cache seria a resposta.
Há muitas formas de obter performance. Otimizando o código. Melhorando a consulta no banco. Criando um índice. Melhorando o algoritmo. Usando programação paralela. Adicionando mais hardware. Ainda assim, quando o seu sistema se tornar grande o suficiente, atendendo milhares de milhões de requisições por minuto, você será obrigado a rever a estratégia de cache da sua aplicação.
O Problema: A Necessidade de Cache em Aplicações de Grande Escala
Considere o seguinte código:
Veja que a Controller
espera um ICarStore
. Que por sua vez acessa o banco de dados. Efetua uma pesquisa e devolve a resposta da requisição.
Uma pergunta:
Como adicionar Cache sem alterar a Controller e nem o CarStore?
Imagine que a implementação do ICarStore
esteja num componente fora do seu alcance. Uma biblioteca do Nuget, por exemplo. E esse componente está demorando muito para responder.
Padrão Decorator: Interceptando Componentes para Melhoria de Performance
O Decorator consiste em utilizar o IoC. Para implementar vamos dividir em duas etapas.
A primeira é criar uma classe de cache que receba o ICarStore
e também faça a implementação da interface.
A segunda é registrar a Classe concreta que implementa o ICarStore
e substituir o registro dele no DI.
Primeira etapa
Veja a implementação abaixo
Esse componente vai receber uma classe Concreta que implementa ICarStore
e ao mesmo tempo, ela implementa essa interface.
Segunda etapa
Em algum lugar do código há um registro da Interface com a implementação dela.
É necessário interferir no DI do ASP.NET Core.
Primeiro o ASP.NET Core associa o ICarStore
à sua implementação original, CarStore
.
Em seguida o código registra a classe Concreta CarStore
e refaz o registro de ICarStore
, só que dessa vez, associando ao componente criado anteriormente.
Lembre-se que esse é um demo. Geralmente existe uma lógica para habilitar ou não essa substituição.
Abaixo o código do CarCachingStore
completo
Ouça e veja a implementação comentada
Casos de Uso e Benefícios do Padrão Decorator
Um bom uso dessa técnica é com Cache. A aplicação só conhece uma interface. Ela não precisa entender quando o dado virá do Cache. Assim evita implementações como:
- ICarCacheStore
- ICarStore
E é possivel controlar quando ativar o Cache de acordo com o ambiente. Utilizar Cache somente no ambiente de produção e em desenvolvimento manter os dados sempre frescos.
Você pode adicionar Log em componentes.
Quem utiliza?
Um grande projeto Open Source, IdentityServer4, utiliza através do Builder em situações que o componente é utilizado para ser utilizado em ambientes de produção.
Download
O código do projeto está disponível no meu GitHub