Nos posts anteriores da série “Padrões de DI”, vimos o que é “Dependency Injection” e o que podemos ganhar com essa técnica. Também vimos onde e como usar um container de DI, conhecendo os conceitos de Composition Root e Register-Resolve-Release.
Neste post e nos próximos, veremos como utilizar padrões que tornam possível o uso de DI por toda nossa aplicação. São técnicas diretamente relacionadas ao DESIGN das classes e que, portanto, desconhecem totalmente qual container está em uso (se é que há algum em uso!).
Começaremos pela mais conhecido: Constructor Injection.
1. O QUE É
Constructor Injection é um padrão de DI que consiste em exigir as dependências por meio de um construtor público (*). É certamente o padrão de DI mais fácil de ser implementado.
(*) É uma boa ideia utilizar apenas 1 construtor público para evitar ambiguidades para os clientes da classe.
2. QUANDO USAR
Deve ser usado sempre que a dependência for obrigatória (*), ou seja, não faz sentido que o objeto “funcione” sem a mesma. Ao usar o construtor, torna-se explícita a obrigatoriedade da dependência já na definição da classe (e também para os clientes da classe).
Em outras palavras: “Quer criar um objeto do meu tipo? Então, por favor, forneça-me essa(s) dependência(s)!”.
Usando Constructor Injection, garantimos que a dependência estará presente e pronta para uso por todo o ciclo de vida do objeto que a consome. E, como dito desde o início desta série, retiramos a responsabilidade de criação da dependência da classe que a utiliza, reduzindo acoplamento.
(*) No ótimo livro “Growing Object-Oriented Software Guided by Tests”, os autores categorizam o relacionamento entre objetos em: “dependências”, “notificações” e “ajustes”, sendo as primeiras, por definição, obrigatórias. No entanto, eles próprios usam essa classificação como algo para ajudá-los no design e não como uma regra na qual fiquem pensando obsessivamente.
3. COMO IMPLEMENTAR
Já vimos o uso de Constructor Injection nos posts anteriores da série, mas reforçarei o conceito aqui com um pouco mais de detalhes (comentários no código apenas para melhor explicação):
public class GeradorDeRelatorio { // dependência armazenada em um field readonly, // o que garante que, após atribuída no construtor, // não poderá ser mais alterada private readonly IDocumento _documento; // constructor injection em uso public GeradorDeRelatorio(IDocumento documento) { // guard-clause para garantir que a // dependência seja fornecida sempre if (documento == null) throw new ArgumentNullException("documento"); // atribui dependência ao field declarado acima _documento = documento; } // usando a dependência nos métodos da classe public void Gerar() { // ..... _documento.QuebrarPagina(); _documento.AdicionarTexto("Aprendendo DI"); // ..... } }
Bem simples, não?
Temos agora uma classe mais flexível, que atende o Open/Closed Principle para os tipos de documento a serem utilizados e que é TESTÁVEL! Uma classe testável é que aquela que pode ser testada por um teste de unidade, uma vez que conseguimos isolá-la de dependências externas.
4. CONCLUSÃO
Vimos neste post o primeiro padrão que nos permite o uso de DI, chamado de Constructor Injection, quando usá-lo e o quanto é simples implementá-lo.
Nos próximos posts, veremos padrões “irmãos” do Constructor Injection, porém um pouco mais específicos.
» Continuar para [Parte 5 – Property Injection]
Participe! Vamos trocar uma ideia sobre desenvolvimento de software!