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
Game
qui 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();