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.