L'injection de dépendances
Notions théoriques
L'injection de dépendances est un patron de conception qui permet de rendre nos applications plus modulaires, plus testables et plus maintenables.
Au lieu de créer des objets à l'intérieur d'une classe ou d'une méthode, nous les passons en tant que paramètres (on "injecte" les dépendances).
Dans notre jeu de combat, par exemple, nous pourrions avoir une classe
Gamequi dépend d'une classeFighter. Au lieu de créer un objetFighterà l'intérieur de la classeGame, nous pourrions le passer en paramètre à la méthodestartGame.
Pourquoi utiliser l'injection de dépendances ?
- Cela nous permet de changer les détails de ces objets sans avoir à modifier la classe ou la méthode qui les utilise.
Car elle se base sur le principe de l'inversion de contrôle.
- De plus, cela facilite les tests unitaires, car vous pouvez injecter des fausses données (mocks) pour tester la classe indépendamment de ses dépendances réelles.
Qu'est-ce que l'inversion de contrôle ?
Cela signifie que ce n'est pas la classe qui contrôle comment et quand créer ses dépendances, mais c'est une entité externe (généralement un conteneur d'injection de dépendances) qui s'en charge.
Par exemple, disons que vous avez une classe Game qui utilise un objet Fighter.
Si Game crée l'objet Fighter directement,
alors chaque fois que vous voulez changer quelque chose sur Fighter
(par exemple, changer les paramètres du constructeur),
vous devez également modifier Game.
En revanche, si Game reçoit un objet Fighter par injection de dépendances
(c'est-à-dire qu'un objet Fighter est passé au constructeur de Game),
alors Game n'a pas besoin de savoir comment Fighter est créé.
Cela signifie que vous pouvez changer Fighter comme vous le souhaitez, sans avoir à modifier Game.
L'injection de dépendances rend votre code plus flexible et plus facile à maintenir, car les modifications d'une partie du code n'entraînent pas nécessairement des modifications dans d'autres parties.
Exemple pratique
class Fighter {
public function attack() {
// Code pour attaquer
}
}
class Game {
private $fighter;
public function __construct(Fighter $fighter) {
$this->fighter = $fighter;
}
public function startGame() {
// Utiliser $this->fighter pour commencer le jeu
$this->fighter->attack();
}
}
Et maintenant, nous pouvons injecter un objet Fighter dans un objet Game comme ceci :
$fighter = new Fighter();
$game = new Game($fighter);
$game->startGame();