Injeção de dependência através de atributos é o ideal?
Tags: spring
Published: 2021-02-23 11:56:14

No framework Spring quando queremos fazer alguma injeção de dependência (DI) é comum fazermos por atributos. 
```
 @Autowired
 private InjectedDependency injectedDependency;
```
Porém este método tem suas desvantagens e vou dizer quais. 
Mas antes vamos escolher uma batida para acompanhar.

{% spotify spotify:track:04Z4xUSktqIO8tvf2U7OhY %}

Agora sim.

Existem 3 maneiras de se realizar a injeção de dependência no Spring, [apesar da documentação, no momento que escrevo, citar apenas duas](https://docs.spring.io/spring-framework/docs/5.0.3.RELEASE/spring-framework-reference/core.html#beans-factory-collaborators). A já citada e exemplificada por atributo, através do construtor da classe e por setters métodos.

Pelo construtor:
```
private InjectedDependency injectedDependency;

@Autowired
public MyDependencyInjection(InjectedDependency injectedDependency) {
  this.injectedDependency = injectedDependency;
}
```

E por setters:
```
private InjectedDependencyOne injectedDependencyOne;
private InjectedDependencyTwo injectedDependencyTwo;

@Autowired
private void setInjectedDependencyOne(InjectedDependencyOne injectedDependencyOne) {
  this.injectedDependencyOne = injectedDependencyOne;
}

@Autowired
private void setInjectedDependencyTwo(InjectedDependencyTwo injectedDependencyTwo) {
  this.injectedDependencyTwo = injectedDependencyTwo;
}
```

A primeira vista realizar a injeção de dependência por atributos parece ser, e é, mais simples e menos verbosa. Uma linha e direto ao ponto(tirando a anotação). Porém nem sempre o simples é o melhor, eis os pontos negativos.

###### Não permite imutabilidade dos nossos atributos

Nossa injeção não funcionará com atributos da classe que forem declarados como `final`, logo perdemos a imutabilidade destes atributos. Com a injeção através dos construtores não perderiamos a imutabilidade destes atributos.

###### Ferir o S do SOLID

Adicionar dependências a nossa classe por atributos por ser menos verboso pode trazer o problema de nossa classe possuir várias dependências sem nos darmos conta que a classe esta fazendo mais do que deveria, tendo mais de uma responsabilidade ferindo o _Single responsibility principle_. A injeção através dos construtores nos ajudaria tornando este construtor cheio e mais visível da quantidade de dependências e responsabilidades da classe . 
Aqui diria que é mais questão de dar visibilidade que uma refatoração pode ser necessária.

###### Esconde as dependências

A classe perde a responsabilidade por obter e gerenciar as dependências, deixando a cargo dos containers de injenção de dependência. Neste cenário seria ideal deixar claro, além de ser recomendável quando se usa DI, quais as dependências utilizadas são obrigatórias e quais são opcionais. O que ficaria inviável através de atributos. Utilizando construtores para obrigatórios e setters para opcionais conseguimos.

###### Acoplamento do container de DI

Como citado anteriormente a responsabilidade agora será dos containers de DI, neste caso containers Spring. O que deixa nosso desenvolvimento acoplado ao container.
Fora do container da aplicação fica mais dificíl utilizar estas dependências. Em um cenário de testes unitários por exemplo, seria necessário instanciar este Spring container(o que alteraria nosso teste unitário para um de integração) e utilizar `reflexão` para settar estes atributos.
Utilizando a DI com construtores invés de por atributos, apenas instanciamos estas classes e passamos como nossas dependências.

**Conclusão**

Realizar a injeção de dependência por construtores ou através de setters apesar de ser mais verboso deixa nosso código mais legível, na minha opinião. 
Um dos exemplos seria quando temos um construtor com muito parâmetros, neste caso as dependências, indica que nossa classe faz mas do que deveria e pode caber uma refatoração. Ainda sobre ser tornar o código legível, podemos citar também sobre a obrigatoriedade de uma dependência quando passada através de construtores ou sua opcionalidade quando passada por setteres.

Se você achou que tem um ponto ou vários que não faz sentido comenta ae pra gente debater sobre, uma discussão saúdavel é ótimo para aprender. 

_Referências que usei_

* https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/
* https://blog.marcnuri.com/field-injection-is-not-recommended/