La inyección de campo es un poco demasiado "acción espeluznante a distancia" para mi gusto.
Considere el ejemplo que proporcionó en su publicación de Grupos de 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(); }
...
}
Entonces, básicamente, lo que está diciendo es que "tengo esta clase con estado privado, a la que he adjuntado @injectable
anotaciones, lo que significa que el estado puede ser poblado automáticamente por algún agente externo, a pesar de que mi estado ha sido declarado privado". "
Entiendo las motivaciones para esto. Es un intento de evitar gran parte de la ceremonia que es inherente a organizar una clase correctamente. Básicamente, lo que uno dice es que "estoy cansado de escribir toda esta repetitiva, así que voy a anotar todo mi estado y dejar que el contenedor DI se encargue de prepararlo para mí".
Es un punto de vista perfectamente válido. Pero también es una solución alternativa para las características del lenguaje que posiblemente no deberían evitarse. Además, ¿por qué parar allí? Tradicionalmente, DI confía en que cada clase tenga una interfaz complementaria. ¿Por qué no eliminar todas esas interfaces con anotaciones también?
Considere la alternativa (esto será C #, porque lo conozco mejor, pero probablemente haya un equivalente exacto en 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;
}
}
Ya sé algunas cosas sobre esta clase. Es una clase inmutable; solo se puede establecer en el constructor (referencias, en este caso particular). Y debido a que todo se deriva de una interfaz, puedo intercambiar implementaciones en el constructor, que es donde entran tus simulacros.
Ahora todo lo que mi contenedor DI tiene que hacer es reflexionar sobre el constructor para determinar qué objetos necesita para renovarse. Pero esa reflexión se está haciendo en un miembro público, de una manera de primera clase; es decir, los metadatos ya forman parte de la clase, habiéndose declarado en el constructor, un método cuyo propósito expreso es proporcionar a la clase las dependencias que necesita.
De acuerdo, esto es un montón de repeticiones, pero así es como se diseñó el lenguaje. Las anotaciones parecen un truco sucio para algo que debería haberse incorporado al lenguaje mismo.