A injeção em campo é um pouco "ação assustadora à distância" para o meu gosto.
Considere o exemplo que você forneceu na sua postagem dos Grupos do Google:
public class VeracodeServiceImplTest {
@Tested(fullyInitialized=true)
VeracodeServiceImpl veracodeService;
@Tested(fullyInitialized=true, availableDuringSetup=true)
VeracodeRepositoryImpl veracodeRepository;
@Injectable private ResultsAPIWrapper resultsApiWrapper;
@Injectable private AdminAPIWrapper adminApiWrapper;
@Injectable private UploadAPIWrapper uploadApiWrapper;
@Injectable private MitigationAPIWrapper mitigationApiWrapper;
static { VeracodeRepositoryImpl.class.getName(); }
...
}
Então, basicamente, o que você está dizendo é que "eu tenho essa classe com estado privado, ao qual anexei @injectable
anotações, o que significa que o estado pode ser automagicamente preenchido por algum agente de fora, mesmo que meu estado tenha sido declarado privado. "
Eu entendo as motivações para isso. É uma tentativa de evitar grande parte da cerimônia que é inerente à criação de uma classe adequadamente. Basicamente, o que se está dizendo é que "estou cansado de escrever todo esse texto padrão, então vou apenas anotar todo o meu estado e deixar o contêiner de DI cuidar de defini-lo para mim".
É um ponto de vista perfeitamente válido. Mas também é uma solução alternativa para os recursos de linguagem que, sem dúvida, não devem ser contornados. Além disso, por que parar por aí? Tradicionalmente, o DI contava com cada classe com uma interface complementar. Por que não eliminar todas essas interfaces com anotações também?
Considere a alternativa (isso será C #, porque eu o conheço melhor, mas provavelmente há um equivalente exato em Java):
public class VeracodeService
{
private readonly IResultsAPIWrapper _resultsApiWrapper;
private readonly IAdminAPIWrapper _adminApiWrapper;
private readonly IUploadAPIWrapper _uploadApiWrapper;
private readonly IMitigationAPIWrapper _mitigationApiWrapper;
// Constructor
public VeracodeService(IResultsAPIWrapper resultsApiWrapper, IAdminAPIWrapper adminApiWrapper, IUploadAPIWrapper uploadApiWrapper, IMitigationAPIWrapper mitigationApiWrapper)
{
_resultsAPIWrapper = resultsAPIWrapper;
_adminAPIWrapper = adminAPIWrapper;
_uploadAPIWrapper = uploadAPIWrapper;
_mitigationAPIWrapper = mitigationAPIWrapper;
}
}
Já sei algumas coisas sobre essa aula. É uma classe imutável; O estado pode ser definido apenas no construtor (referências, neste caso em particular). E como tudo deriva de uma interface, eu posso trocar as implementações no construtor, que é onde suas zombarias entram.
Agora, tudo que meu contêiner de DI precisa fazer é refletir sobre o construtor para determinar quais objetos ele precisa atualizar. Mas essa reflexão está sendo feita sobre um membro público, de maneira de primeira classe; isto é, os metadados já fazem parte da classe, tendo sido declarados no construtor, um método cujo objetivo expresso é fornecer à classe as dependências necessárias.
Concedido isso é muito clichê, mas é assim que a linguagem foi projetada. As anotações parecem um truque sujo para algo que deveria ter sido incorporado ao próprio idioma.