L'iniezione sul campo è un po 'troppo "azione spettrale a distanza" per i miei gusti.
Considera l'esempio che hai fornito nel post di Google Gruppi:
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(); }
...
}
Quindi sostanzialmente quello che stai dicendo è che "ho questa classe con stato privato, a cui ho allegato @injectable
annotazioni, il che significa che lo stato può essere popolato automagicamente da un agente dall'esterno, anche se il mio stato è stato dichiarato privato. "
Capisco le motivazioni per questo. È un tentativo di evitare gran parte della cerimonia inerente alla corretta organizzazione di una classe. Fondamentalmente, quello che si sta dicendo è che "Sono stanco di scrivere tutto questo bollettino, quindi ho intenzione di annotare tutto il mio stato e lasciare che il contenitore DI si occupi di impostarlo per me".
È un punto di vista perfettamente valido. Ma è anche una soluzione alternativa per le funzionalità del linguaggio che probabilmente non dovrebbero essere aggirate. Inoltre, perché fermarsi qui? Tradizionalmente, DI ha fatto affidamento sul fatto che ogni classe avesse un'interfaccia complementare. Perché non eliminare anche tutte quelle interfacce con le annotazioni?
Considera l'alternativa (sarà C #, perché lo conosco meglio, ma probabilmente c'è un equivalente esatto in 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;
}
}
So già alcune cose su questa lezione. È una classe immutabile; lo stato può essere impostato solo nel costruttore (riferimenti, in questo caso particolare). E poiché tutto deriva da un'interfaccia, posso scambiare le implementazioni nel costruttore, che è dove entrano in gioco le tue beffe.
Ora tutto ciò che il mio contenitore DI deve fare è riflettere sul costruttore per determinare quali oggetti è necessario per rinnovare. Ma quella riflessione viene fatta su un membro pubblico, in un modo di prima classe; cioè i metadati fanno già parte della classe, essendo stati dichiarati nel costruttore, un metodo il cui scopo esplicito è quello di fornire alla classe le dipendenze di cui ha bisogno.
È scontato che questo sia un gran numero di piatti, ma è così che è stato progettato il linguaggio. Le annotazioni sembrano un trucco sporco per qualcosa che avrebbe dovuto essere incorporato nel linguaggio stesso.