DEV Community

Cover image for Cursus NestJS - Les providers
WebeleonFR for Webeleon

Posted on

Cursus NestJS - Les providers

Bonjour et bienvenue dans le cinquiéme module du cursus NestJS par Webeleon!
Je m'appel Julien et je serai ton guide tout au long de cette aventure.

Dans cette vidéo, je vais te parler d'un des éléments les plus important de NestJS: Les providers

Un point SOLID

Avant de rentrer dans le gras du sujet, j'aimerais faire un rapide rappel sur un concept essentiel du clean code.

SOLID est un acronyme qui représente 5 principe d'architecture logiciel qui ont pour objectif de rendres les source (orienté objet) plus lisible, compréhensible et maintenable.

  • Principe de responsabilité unique (Single responsibilty): Une classe ne doit avoir qu'un seul et unique role!
  • Principe d'ouverture-fermeture (Open-closed principle): Une classe doit être ouverte au extension (via un systéme de plugin par exemple, cf architecture hexagonale) mais fermé au modification.
  • Prinicpe de la substitution de Liskov (Liskov substitution): L'utilisation de classes héritant d'une interface commune doivent pouvoir s'utiliser de maniére transparente.
  • Principe de segregation des interfaces (Interface segregation principle): Mieux faut avoir un grand nombre d'interface spécifique q'une seul interface générique.
  • Principe d'inversion de dépendances (Dependency inversion principle): Il faut dépendre des abstractions et non des implémentations.

Qu'est ce qu'un provider?

Les providers (literallement: fournisseurs) sont un concept fondamental de NestJS.

Le terme peux paraitre un peu ésotérique mais il représente une réalité assez simple.

Il s'agit de classe compatible avec le systéme d'injection de dépendance de NestJS.
Pour cela il faut ajouter l'annotation @Injectable du paquet @nestjs/common sur la class cible.

import { Injectable } from '@nestjs/common';

@Injectable()
export class MonSuperProvider {}
Enter fullscreen mode Exit fullscreen mode

Cette logique va permettre de créer un ensemble d'outils qui vont pouvoir être cabler facilement.

Déclaration dans un module

Afin de pouvoir utiliser notre provider via l'injection de dépendances il necessaire de le déclarer dans un module (voir même le bon module mais nous y reviendront dans la leçon suivante).

import { Module } from '@nestjs/common';
import { MonSuperProvider } from './mon-super.provider';

@Module({
  imports: [],
  controllers: [],
  providers: [MonSuperProvider],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Injection

Une des grandes force des providers, c'est de pouvoir profiter du systéme d'injection de dépendance.
Une fois le provider déclaré dans un module, il est possible de l'utiliser dans n'importe quelle classe du module en l'ajoutant via le constructeur.

import { Controller, Get } from '@nestjs/common';
import { MonSuperProvider } from './mon-super.provider';

@Controller()
export class AppController {
  constructor(
    private readonly superProvider: MonSuperProvider,
  ) {}

  @Get()
  getUnTruc() {
    return this.superProvider.fetchUnTrucDansLaBDD();
  }
}
Enter fullscreen mode Exit fullscreen mode

Il sera ensuite disponible dans le this de la classe. Dans cet exemple, une instance de la classe MonSuperProvider est disponible via this.superProvider dans tout la class AppController.

Les services

Les providers les plus courants sont les services.
Ils ont pour roles la gestions des données entre les controllers et les sources de données.

Pour créer un Service manuellement, il suffira d'appliquer la procédure de création d'un provider et de remplace le terme provider par Service.

Création rapide via la ligne de commande nest:

nest g service nomDuService
Enter fullscreen mode Exit fullscreen mode

provider custom

Il est aussi possible de rendre injectable dans un module plus ou moins n'importe quoi en utilisant le pattern des provider custom.

Au lieu de fournir une classe dans la section providers, tu peux passer un objet qui contiendra le jeton d'injection (injection token) et le moyen de le récupérer.

import { Module } from '@nestjs/common';

@Module({
  imports: [],
  controllers: [],
  providers: [
    {
      provide: 'MA_CONSTANTE',
      useValue: '1234'
    },
    {
      provide: 'MON_SERVICE_MOCK',
      useValue: {
        unTruc: () => {
          // implementation
        }
      }
    },
    {
      provide: 'injection token',
      useClass: ClassToUse,
    },
    {
      provide: 'injection token',
      imports: [/* module dont dépend la factory */],
      inject: [/* providers à injecter dans la factory */],
      useFactory: async (/* dépendance injecté dans le même ordre que déclaré au dessus */) => {
        // logique permettant de construire le provider
        return // provider construit, ce qui sera injecté.
      }
    }
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Pour injecter un provider custom, il est necessaire d'utiliser le décorateur @Inject(injection_token).

import { Injectable, Inject } from '@nestjs/common';

@Injectable()
class EncoreUnProvider {
  constructor(
    @Inject('MA_CONSTANTE') private readonly maConstante: string,
    @Inject('MON_SERVICE_MOCK') private readonly monServiceMock: UneInterfaceOuUneClasse
  ) {}
}

Enter fullscreen mode Exit fullscreen mode

Cette technique est trés utile pour la mise ne place de tests afin de limiter les dépendances.

Ceci n'est qu'une approche superficielle des providers custom, une documentation compléte est disponible en anglais

Conclusion

Laisse-moi tes questions en commentaire, je me ferai un plaisir d'y répondre.

L'intégralité du cursus est disponible sur github.

Ou viens directement les poser sur le serveur discord webeleon!

La prochaine fois nous verrons l'utilisation avancée des modules alors abonne-toi pour progresser rapidement sur NestJS!

Latest comments (1)

Collapse
 
umasankarswain profile image
umasankar-swain