L'injection de dépendances en Angular: que faut t-il retenir ?

Search for a command to run...

J'ai aimé cette explication de l'injection de dépendance. C'était simple à comprendre. Merci beaucoup.
Merci pour ton feedback ! C'est très encourageant 😃 Heureux de t'avoir pu être utile !
Depuis l'arrivée des Signals dans Angular, une question revient sans cesse dans les équipes : comment continuer à profiter de la puissance de RxJS, de ses opérateurs, de sa gestion fine des flux async

Si vous suivez l'actualité d'Angular avec la sortie de la version 20 du framework, vous avez probablement entendu de plus en plus ce terme. Mais au-delà du jargon, qu'est-ce que le Zoneless concrètement pour vos applications Angular ? Pourquoi est-il...

Si vous avez l’habitude de manipuler des formulaires réactifs (Reactive Forms) dans un projet Angular, vous connaissez certainement la méthode patchValue(…). Cette méthode, permet de mettre à jour les valeurs de votre formulaire. Cependant, son utili...

Depuis la sortie de la version 17 du framework Angular, on parle de la renaissance de Angular. Il y a eu beaucoup de changements majeurs depuis la version 16 du framework pour préparer le terrain à cette renaissance. Ces changements majeurs ont rendu...

Dans notre précédent article, nous avons vu ensemble ce qu'est un Signal Input et comment l'utiliser. Nous avons particulièrement remarqué sa similarité avec le décorateur @Input(). Dans ce nouvel article, nous verrons ensemble un nouveau type de inp...

L'une des qualités du framework Angular réside en sa facilité à permettre l'utilisation de la notion d'injection de dépendances (Dependency Injection en anglais). En effet, tout le framework repose sur cette notion ce qui nous permet d'interagir avec une multitude de classes sans se casser la tête. Avant, d'aller plus loin, voyons brièvement ensemble ce qu'est l'injection de dépendances.
En programmation orientée objet, nous manipulons des objets au moyen des classes. Supposons que nous avons trois (03) classes à savoir ClassA, ClassB et ClassC comme l'illustre cet exemple de code basé sur du TypeScript :
export class ClassA {
constructor() {
}
}
export class ClassB {
constructor() {
}
}
export class ClassC {
constructor() {
}
}
Notre objectif ici est de créer deux (02) objets respectivement des classes ClassA et ClassB que nous utiliserons dans notre classe ClassC. Nous avons donc le code qui suit :
export class ClassC {
objectA = new ClassA();
objectB = new ClassB();
constructor() {
}
}
Jusque-là, tout se passe bien. Supposons à présent que nos classes ClassA et ClassB contiennent des arguments dans leurs constructeurs respectifs comme l'indique le code suivant :
export class ClassA {
constructor(args) {
}
}
export class ClassB {
constructor(args) {
}
}
Ce changement au niveau de nos classes ClassA et ClassB nous contraint à modifier la façon dont nous créons nos objets dans la classe ClassC. Nous devons passer en paramètre des variables comme ceci :
export class ClassC {
objectA;
objectB;
constructor(argsA, argsB) {
this.objectA = new ClassA(argsA);
this.objectB = new ClassB(argsB);
}
}
Cette façon classique de faire soulève deux (02) problèmes essentiels :
Le premier problème c'est que le code n'est plus flexible parce que à chaque changement au niveau du constructeur de nos classes
ClassAetClassB, nous devons opérer des changements au niveau de la classeClassC.Le second problème c'est que notre code ne sera plus vraiment facile à tester parce que à chaque fois que nous créerons une instance de la classe
ClassC, nous aurons besoin d'indiquer les paramètres des classesClassAetClassBdans le constructeur de la classeClassC.Afin d'y remédier, l'astuce la plus simple est d'utiliser la notion d'
injection de dépendances.
En reprenant l'exemple de nos trois (03) précédentes classes, nous avons ceci :
export class ClassA {
constructor(args) {
}
}
export class ClassB {
constructor(args) {
}
}
export class ClassC {
objectA;
objectB;
constructor(private objectA: ClassA, private objectB: ClassB) {
this.objectA = objectA;
this.objectB = objectB;
}
}
Nous remarquons donc que les changements au niveau du constructeur de nos classes ClassA et ClassB ne nous obligent plus à modifier nos instances dans la classe ClassC.
Oui c'est magique 😂
En revenant sur notre thématique, Angular est entièrement basé sur le langage orienté objet TypeScript ce qui lui de mettre en place la notion d'injection de dépendances. Nous verrons quelques cas usuels d'utilisation de l'injection des dépendances dans nos projets :
Pour créer des instances de ces classes après avoir bien-sûr déclaré leurs modules là où il le faut, voici ce que nous faisons généralement :
export class MyComponent {
constructor(private router: Router, private route: ActivatedRoute) {
}
}
export class MyService() {
constructor(private http: HttpClient) {
}
}
Résultat, nous ne nous soucions pas de comment ces instances sont initialisées. C'est de l'injection de dépendances.
Lorsque nous créons nos propres services, voici comment nous les utilisons dans nos composants :
export class MyComponent {
constructor(private myService: MyService) {
}
}
En faisant ainsi, nous exploitons la notion d'injection de dépendances. En effet, si nous remarquons bien lors de la création de nos services, nous avons le décorateur @Injectable() qui nous permet d'injecter notre service là où nous désirons l'utiliser. Généralement, nous avons ceci :
@Injectable({ provideIn: 'root' })
export class MyService() {
constructor() {
}
}
provideIn permet de préciser la portée de notre service. Lorsque nous indiquons 'root' le service est créé et disponible au lancement de l'application. Nous avons aussi d'autres valeurs à savoir 'platform', 'any' et null, qui suivant le cas, nous amène à utiliser le tableau providers.Pour finir, nous pouvons également faire de l'injection de dépendance en utilisant la fonciton inject qui a subi des mises à jour depuis Angular 14:
/* au lieu de faire ceci : */
export class MyService() {
constructor(private http: HttpClient) {
}
}
/* nous pouvons faire : */
export class MyService() {
http = inject(HttpClient);
}
En somme, nous avons à présent une idée de comment Angular raisonne par rapport à l'injection de dépendance et nous comprenons davantage pourquoi nous sommes autorisés à utiliser certaines classes sans le mot clé new .
Pour plus d'informations :
👉 Understanding Dependency Injection