L'injection de terrain est un peu trop "action fantasmagorique à distance" à mon goût.
Prenons l'exemple que vous avez fourni dans votre publication Google Groupes:
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(); }
...
}
En gros, ce que vous dites, c’est que "j’ai cette classe avec un état privé, à laquelle j’ai joint des @injectable
annotations, ce qui signifie que l’état peut être automatiquement peuplé par un agent extérieur, même si mon état a été déclaré privé. "
Je comprends les motivations pour cela. C'est une tentative pour éviter une grande partie de la cérémonie qui est inhérente à la mise en place d'une classe correctement. En gros, ce que l’on dit, c’est: "Je suis fatigué d’écrire tout ce passe-partout, alors je vais simplement annoter tout mon état et laisser le conteneur de DI se charger de le régler pour moi."
C'est un point de vue parfaitement valable. Mais c’est aussi une solution de contournement pour les fonctionnalités de langage qui ne devraient sans doute pas être contournées. Aussi, pourquoi s'arrêter là? Traditionnellement, DI s’appuyait sur chaque classe ayant une interface compagnon. Pourquoi ne pas éliminer toutes ces interfaces avec des annotations?
Considérez l’alternative (cela va être C #, parce que je le connais mieux, mais il existe probablement un équivalent exact 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;
}
}
Je sais déjà certaines choses à propos de ce cours. C'est une classe immuable. state ne peut être défini que dans le constructeur (références, dans ce cas particulier). Et comme tout provient d’une interface, je peux échanger des implémentations dans le constructeur, c’est là que vos simulacres entrent en jeu.
Maintenant, tout ce que mon conteneur DI doit faire est de réfléchir au constructeur pour déterminer quels objets il doit créer. Mais cette réflexion se fait sur un membre du public, d'une manière de première classe; c'est-à-dire que les métadonnées font déjà partie de la classe, après avoir été déclarées dans le constructeur, une méthode dont le but spécifique est de fournir à la classe les dépendances dont elle a besoin.
Certes, cela fait beaucoup de choses, mais c’est ainsi que le langage a été conçu. Les annotations semblent être un sale bidouillage pour quelque chose qui aurait dû être intégré au langage lui-même.