Padrões de DI: Introdução – Robson Castilho
Padrões de DI: Introdução
Data: 07/06/2014Autor: Robson Castilho 6 Comentários
Inicio com este post uma série sobre padrões de Dependency Injection ou, daqui em diante, simplesmente "DI".
Este primeiro consiste em uma rápida introdução sobre DI, antes de seguirmos com os padrões de fato.
1. O QUE É DI
DI é uma técnica que tem por finalidade o desenvolvimento de software com baixo acoplamento e, portanto, mais fácil de ser mantido.
Pensar em DI é pensar com carinho onde empregamos o uso do famoso "new", de forma que possamos minimizar o acoplamento entre as classes do software, tornando-o mais flexível.
2. PRINCIPAIS VANTAGENS
DI é o meio e não o fim. Portanto, as vantagens obtidas estão no resultado, ou seja, no código de baixo acoplamento. São elas:
Late binding: capacidade de substituir comportamento do software por meio de configuração, ou seja, sem a necessidade de recompilar o código.
Extensibilidade: habilidade de mudar o código com o mínimo de alterações possíveis. Lembram do Princípio do Aberto/Fechado?
Manutenibilidade: facilidade de manter o código, graças a uma definição bem clara de responsabilidades. Lembram do Princípio da Responsabilidade Única?
Testabilidade: no sentido de a aplicação ser capaz de ser testada por meio de testes de unidade.
3. O QUE DI COBRE
3.1. OBJECT COMPOSITION
Inicialmente o foco de DI estava unicamente na composição de objetos (Object Composition), isto é, na capacidade de construir aplicações pela composição de módulos/componentes.
Isso acontece quando quebramos as classes em responsabilidades bem definidas e removemos o controle das dependências PARA FORA da classe-consumidora. Em outras palavras, quem USA uma dependência, não a CRIA.
Retirando esse "peso" de criar a dependência da classe-consumidora, ganhamos mais flexibilidade, podendo usar (ou injetar) diferentes implementações.
Vejamos um pequeno exemplo:
// uma classe-consumidora altamente acoplada
// à sua dependência
public class UmServicoQualquer
public void Executa()
var repositorio = new SqlRepositorio();
var obj = repositorio.ObterPor(id: 5);
// mesma classe, agora fazendo uso de DI
private readonly IRepositorio repositorio;
public UmServicoQualquer(IRepositorio repositorio)
var obj = this.repositorio.ObterPor(id: 5);
Observem que, na primeira implementação, o consumidor cria explicitamente a dependência (new SqlRepositorio()), ficando acoplado a uma implementação concreta do repositório.
Já na última implementação, a dependência é injetada no consumidor, deixando-o livre da responsabilidade de criação e totalmente alheio à implementação da dependência.
Para alcançarmos o tão precioso baixo acoplamento, é imprescindível um dos conceitos mais antigos de orientação a objetos: programar para interfaces, não para implementações. Exatamente o que foi feito no exemplo, onde o consumidor dependente de uma abstração, a interface IRepositorio.
Além da composição de objetos, hoje em dia outros dois conceitos são aspectos importantes em DI: Interception e Object Lifetime.
3.2. INTERCEPTION
Ao aplicarmos DI, como visto no item anterior, ganhamos a capacidade de interceptar o momento de injeção da dependência e "envelopá-la" em outra classe, acrescentando comportamento à dependência sem modificá-la.
Parece familiar? Sim. Interception nada mais é do que uma aplicação do design pattern Decorator. Usando Interception, podemos implementar cross-cutting concerns como log e controle de acesso, entre outros.
3.3. OBJECT LIFETIME
Outro aspecto que ganhamos ao inverter as dependências é a habilidade de controlarmos quando novas instâncias são criadas e quando saem do escopo, ou seja, o tempo de vida do objeto (Object Lifetime).
Por exemplo, podemos decidir quando uma mesma instância de uma dependência deverá ser injetada em todo consumidor (Singleton lifetime) ou quando uma nova instância é criada toda vez que a dependência for solicitada (Transient lifetime).
4. TIPOS DE DEPENDÊNCIAS
Agora estamos prontos para sair injetando tudo que imaginarmos, certo? Muita calma nessa hora. Existem dependências estáveis e instáveis (ou voláteis). O foco de DI está na segunda categoria.
São dependências voláteis aquelas que possuem pelo menos uma das características abaixo:
– São dependências externas, ou seja, que estão fora do processo da aplicação, como bancos de dados, message queues, web services e o sistema de arquivos do SO.
– Possuem comportamento não-determinístico, como o famoso DateTime.Now ou geração de números aleatórios.
– Necessitam ser abstraídas por possuírem diferentes comportamentos, que precisam ser alternados em tempo de execução (ex.: strategies).
Em geral, estaremos injetando "fazedores de coisas"e que normalmente deixam a aplicação mais "desplugável" (*), ou seja, mais fácil de ter seus módulos substituídos ou usados (inclusive por testes) em isolamento.
(*) conceitualmente, chamamos de seam esta dependência (abstração) que serve de ponto de contato entre uma parte e outra da aplicação.
5. RELAÇÃO ENTRE DI E O PRINCÍPIO DA INVERSÃO DE DEPENDÊNCIA (DIP)
Falamos anteriormente sobre programar para interfaces, conceito tratado no DIP. Portanto, o Princípio da Inversão de Dependência é o princípio que é base para a prática de DI.
Este artigo, o primeiro da série "Padrões de DI", apresentou o conceito de Dependency Injection, dando uma visão geral do que é DI e seus 3 aspectos: Object Composition, Interception e Object Lifetime.
Embora os dois últimos aspectos sejam também de grande importância, esta série focará exclusivamente em Object Composition, que é a base de DI, trazendo padrões e conceitos que lidam sobre ONDE compor as dependências, QUANDO resolvê-las e COMO injetá-las.
arquitetura de softwaredependency injectionfeaturedorientacao a objetospatterns
Anterior Post anterior: Tell, don't ask
Avançar Próximo post: Testando acoplamento
6 comentários em "Padrões de DI: Introdução"
07/06/2014 às 08:41
Muito bom Robson, parabéns.
Estou aguardando os demais.
Mto obrigado, cara
Jefferson S Nascimento disse:
Muito bom Robson!!
07/06/2014 às 20:21
Valeu.[]s
09/06/2014 às 17:03
Aprendendo muito com seus artigos, já uso alguns desses padrões que você apresenta em seu blog porém sem saber que uso haha, a nomeclatura não sou muito bom nas sopas de letrinhas, mas sei o que deixa meu codigo facil de manter! Logo seus artigos me ajuda a identificar os nomes doa padrões que uso!