Desmistificando o design pattern Dependency Injection

Quando eu escutava alguém dizendo:

” Ah legal podemos resolver isso com dependency injection…”

ou então:

“Nossa esse esquema de dependency injection é muito legal resolve tudo né?”

Eu balançava a cabeça e concordava dizendo:

“Com certeza isso resolve nossos problemas”.

Sinceramente eu nem fazia ideia direito o que cargas d’água era isso, mas já aplicava nos meus projetos sem saber que isso tinha o nome de injeção de dependência.

A verdade é que dependency injection ou injeção de dependência é um nome bonito que no nosso mundo de desenvolvimento parece ser ciência de foguetes, porém posso afirmar que é um termo de R$100,00 para um conceito de R$ 1,00 . Não quero desvalorizar o padrão de projeto só enaltecer que não é tão complicado como as pessoas fazem parecer. Com isso pensei porque não escrever um texto sucinto para desmistificar isso? e aqui estamos então vamos lá!

A versão realmente curta

Injeção de dependência significa dar a um objeto a uma variável de instancia. De fato é só isso.

A versão mais longa PARTE I – Dependência não injetada

Classes possuem em sua implementação métodos e atributos . Nada novo né? Vamos chamar isso de “dependências”.

Algumas pessoas chamas isso de “variáveis”, algumas vezes quando estão se sentindo chiques chamam de “variáveis  da instância”.

Veja o exemplo:

 private DatabaseThingie myDatabase; 

 public Example() { 
 myDatabase = new DatabaseThingie(); 
 } 

 public void DoStuff() { 
 ... 
 myDatabase.GetData(); 
 ... 
 } 
}

Como podem ver temos uma variável com dependência explicita chamada “myDatabase”. Ela é inicializada no construtor. Onde está a dependência não injetada nesse caso? Simples por ser uma declaração explicita não existe como a variável “myDatabase” ser de outro tipo senão DatabaseThings e ela está tendo sua instancia criada dentro da própria classe. SIMPLES ASSIM!

A versão mais longa PARTE II – Injeção de Dependência

Se nós desejarmos, poderíamos passar a variável para o construtor que iria “injetar” a “dependência” na classe. Agora quando nós usamos a variável (dependência) nós utilizamos o objeto que foi passado ao invés da instância um novo criado dentro dentro da classe.

public class Example { 
 private DatabaseThingie myDatabase; 

 public Example() { 
 myDatabase = new DatabaseThingie(); 
 } 

 public Example(DatabaseThingie useThisDatabaseInstead) { 
 myDatabase = useThisDatabaseInstead; 
 }

 public void DoStuff() { 
 ... 
 myDatabase.GetData(); 
 ... 
 } 
}

De fato isso é tudo o que de fato é, o resto são apenas variações do tema.

  •  Você pode setar a dependência também por (waaaaaaait for it…) um método setter. Rá!
  • Você poderia setar a dependência chamando um método setter que está definido em uma interface se quisesse.
  • Você poderia ter a dependência como interface e então polirramificante passar algum poli suco para ela. (Whatever!)

Você é o mago livre do seu código!

A versão mais longa PARTE III – Por quê fazemos isso?

Além de muitas coisas é uma mão na roda para isolar classes durante testes.

public class ExampleTest { 
 TestDoStuff() { 
 MockDatabase mockDatabase = new MockDatabase(); 

 // MockDatabase is a subclass of DatabaseThingie, so we can 
 // "inject" it here: 
 Example example = new Example(mockDatabase); 

 example.DoStuff(); 
 mockDatabase.AssertGetDataWasCalled(); 
 } 
}

public class Example { 
 private DatabaseThingie myDatabase; 

 public Example() { 
 myDatabase = new DatabaseThingie(); 
 } 

 public Example(DatabaseThingie useThisDatabaseInstead) { 
 myDatabase = useThisDatabaseInstead; 
 } 

 public void DoStuff() { 
 ... 
 myDatabase.GetData(); 
 ... 
 } 
}

Para quem trabalha com Angular JS por exemplo sempre escuta ou lê que o framework funciona basicamente sobre injeção de dependência.  Vamos demonstrar onde isso ocorre para que você possa ver na prática.

angular.module("root", [])
.controller("index", [
"$scope", 
"myStuff",
"myOtherStuff",
function($scope, myStuff, myOtherStuff ) {
$scope.message = "Hello World";
}]);

Como você sabe na declaração do  controller existe a injeção de dependência, onde o segundo parâmetro em é um array que recebe quais são os parâmetros que deverão ser passados como referência, veja que a última posição do array é a function que recebe os mesmos parâmetros que foram declarados nas outras posições. Isso não está parecendo um construtor recebendo já as instâncias como nos exemplos citados acima? SIM É EXATAMENTE ISSO!

Isso é injeção de dependência, apenas passar uma instancia para o objeto e não o criar dentro desse objeto.

Existem muitas formas de tornar esse conceito muito mais complicado. (Existe várias formas de tornar qualquer conceito muito mais complicado) Ser simples não é algo fácil. Algumas vezes tal complexidade é realmente necessária e nunca é minha primeira opção. Eu escolhi não discutir o “sexo dos anjos” aqui mas se você quer se aprofundar mais nisso e nos termos complexos recomendo partir daqui.

Então é isso pessoal, se gostaram do texto deixa um comentário, me siga nas redes sociais e principalmente no GitHub. Um forte abraço e espero ter te ajudado.

  • Marlysson Silva

    Show!!

    Não sei se caberia, mas algo relacionado que provavelmente a galera “usa” junto é a inversão de controle, que está muito relacionada a injeção de dependência..

    Ótimo post 😀

  • Obrigado pelo comentário @@marlyssonsilva:disqus.

    Legal bem ressaltado assim que tiver um tempo vou falar dessa parte também, realmente importante.