Inversion de contrôle dans Dynamics 365

Développeurs et architectes, vous créez une application avec Dynamics 365? Comment veiller à cibler les cas d’utilisation selon le contexte d'affaires et non selon la méthode utilisée pour y parvenir? Pour ce faire, découvrez l’injection de dépendances et l’inversion de contrôle.

Orientation typique – Détails de mise en œuvre masquant le cas d’utilisation

Je me concentrerai sur la mise en œuvre de ce concept dans Dynamics 365, car la rédaction des plugins correspondants pose un certain défi. En effet, l'architecture d'un plugin semble résister à l'inversion de contrôle.Voici un exemple : à la création d’un compte, nous voulons créer une tâche pour faire le suivi dans une semaine avec le titulaire (il s’agit d’un exemple de plugin tiré du kit de développement logiciel de Dynamics 365, simplifié via la PluginBase de mon collègue David Rivard). Normalement, à la création d’un plugin, on se concentre sur l’événement qui se produit (ici, la création d’un compte) pour écrire la logique nécessaire à la création d’une tâche. La lecture du code est donc nécessaire pour en saisir le but.C'est ici que le principe de l’inversion du contrôle entre en jeu. Quand un compte est créé, je veux que la tâche soit créée aussi, sans que je n'aie à savoir comment. L’idée est de faire abstraction des détails d’implémentation, qui devraient dépendre du cas d’utilisation (et non l’inverse). Ainsi, le code reste axé sur le but à atteindre.Avant toute adaptation, le code ressemblerait à ce qui suit; nous devons donc le lire pour en comprendre le but :Avant

Passer des détails de mise en œuvre à une approche par cas d’utilisation

La première étape de l’inversion de contrôle consiste à transférer les détails de mise en œuvre dans une autre classe. On peut alors la tester sans utiliser Dynamics (un test unitaire au lieu d’un test d’intégration). Voici le code après avoir transféré la logique dans une autre classe : Après le transfert dans une autre classe - 3 fichiersL’objectif du plugin devient clair. L’interface est illustrée ci-dessous, et la classe concrète CreateTaskOnAccountCreationCommand la met en œuvre essentiellement de la même manière qu’auparavant.  

Intégration de Ninject de manière prise en charge dans un projet de plugin de Dynamics 365

J’ai déjà travaillé sur un projet qui ne comportait pas d’injection de dépendance. Laissez-moi vous dire qu’il devient fastidieux de créer les objets quand le constructeur comporte une douzaine de paramètres. C’est là que brille l’injection de dépendance. Pour supprimer la dépendance à l’égard des détails de mise en œuvre, il faut demander à Ninject de créer une instance de la classe. Cette inversion de contrôle se fait généralement en utilisant Nuget pour importer sa bibliothèque. Par contre, c’est impossible dans Dynamics 365, qui nd prend pas en charge la fusion de plusieurs bibliothèques. Une solution consiste à télécharger tout le code source de Ninject et à copier tous les fichiers sources (*.cs) dans notre projet (la licence de Ninject le permet). Pour ne plus dépendre des détails d’implémentation, nous commençons à utiliser Ninject. Donc, le plugin ne saura plus comment les détails sont implémentés. Pourquoi procéder ainsi? Pour l’avantage de ne pas avoir à connaître les détails de l’implémentation. Ainsi, nous pourrions les remplacer par une autre implémentation et la tester indépendamment de Dynamics 365.

Introduction de l’inversion de contrôle avec Ninject

Il faut d’abord ajouter le résolveur de dépendances et Ninject, puis lier les interfaces à leurs implémentations. Nous ajoutons donc une référence à Ninject .  

Créer une instance de classe avec Ninject

De cette façon, le plugin ignore l’implémentation de la création de tâche, mais à la lecture du code, nous en comprenons le but. L’inversion de contrôle est effectuée par Ninject:Donc, au moment d’exécuter les détails (dans notre cas, créer une tâche lors de la création d’un compte), Ninject crée une instance de la classe CreateTaskOnAccountCreationCommand, ce qui relie l’interface qui me dit que je veux exécuter la commande avec les détails d’implémentation. Il est donc possible de remplacer une implémentation par une autre en changeant uniquement le DependencyResolver. Enfin, l’injection de dépendance signifie que Ninject crée pour nous les objets avec tous leurs membres. Si ce n’était pas le cas, la tâche serait fastidieuse. Par exemple, nous pourrions fractionner le code de sorte que la création de tâche soit une classe et que l’orchestrateur qui l’invoque lors de la création d’un compte soit une autre classe. Certes, on pourrait dire que c’est exagéré pour un besoin aussi simple, mais pour des projets plus complexes comportant de nombreuses dépendances, l’approche devient intéressante. Voici l’orchestrateur : Cependant, la commande requiert deux autres paramètres lorsqu’elle est instanciée :

Créer une instance de classe et passer dans le OrganizationService depuis le plugin

Sans Ninject et l’inversion de contrôle, il faudrait créer tous les objets et fournir les paramètres nécessaires à tous les constructeurs. Plutôt, nous disons simplement à Ninject de lier les interfaces aux classes qui les implémentent et parfois de spécifier des paramètres, par exemple pour la commande suivante : Lorsque Ninject crée l’objet CreateTaskOnAccreationCreationCommand, il choisit le constructeur le plus complexe et crée les objets nécessaires. Dans notre cas, il crée une instance de l’objet CreateTaskCommand et la transmet au constructeur CreateTaskOnAccreationCreationCommand. Pour créer l’objet CreateTaskCommand, il va créer une instance de l’objet TaskFactory et la passer au constructeur CreateTaskCommand ainsi qu’à l’instance IOrganizationService que le plugin a fournie lors de son exécution.

Le point sur l’approche

Enfin, la dissimulation des détails d’implémentation rend le code plus facile à lire et à comprendre. On se détache de la mise en place de plugins concrets. Cette méthode facilite la substitution des détails d’implémentation et permet de tout faire en un seul endroit. Elle facilite également les tests de logique dans chacune des classes, car nous pouvons mettre en œuvre une interface qui teste des fragments de code sans tester l’ensemble.  Pour récapituler, voici les avantages de la méthode proposée :

  • axée sur les cas d’utilisation;
  • code clair et facile à comprendre, à entretenir et à tester;
  • couplage faible pour pouvoir remplacer des parties du code plus facilement.

Bref, il va sans dire que la méthode s’illustre dans les projets d’envergure et qu’elle ne vaut pas l’effort dans un petit projet comme celui pris en exemple. Cependant, cet exemple a été utilisé pour illustrer les principes qui peuvent être appliqués dans un grand projet. Cet article est une initiative de notre expert Jean-François Fortin.

À lire aussi

Comment connecter Dynamics 365 à Azure pour enregistrer les erreurs?

Vous aimeriez en savoir plus?

Notre équipe peut vous accompagner avec des conseils personnalisés, des formations ou de nouvelles solutions adaptées à vos besoins. Optimisez l’utilisation de vos technologies et vos processus quotidiens : contactez l’un(e) de nos expert(e)s.

Pour rester au fait des dernières nouvelles, suivez-nous sur LinkedIn et sur notre chaîne Youtube!