Nette Documentation Preview

syntax
Questions fréquemment posées sur DI (FAQ)
*****************************************


DI est-il un autre nom pour IoC ? .[#toc-is-di-another-name-for-ioc]
--------------------------------------------------------------------

*Inversion of Control* (IoC) est un principe axé sur la manière dont le code est exécuté - que votre code initie un code externe ou que votre code soit intégré dans un code externe, qui l'appelle ensuite.
L'inversion de contrôle est un concept large qui inclut les [événements |nette:glossary#Events], le [principe |application:components#Hollywood style] dit [d'Hollywood |application:components#Hollywood style] et d'autres aspects.
Les usines, qui font partie de la [règle n° 3 : laisser l'usine s'en charger |introduction#Rule #3: Let the Factory Handle It], et représentent l'inversion de l'opérateur `new`, sont également des composantes de ce concept.

*Dependency Injection* (DI) concerne la manière dont un objet connaît un autre objet, c'est-à-dire la dépendance. Il s'agit d'un modèle de conception qui exige le passage explicite des dépendances entre les objets.

On peut donc dire que l'injection de dépendances est une forme spécifique d'IoC. Cependant, toutes les formes de contrôle interne ne conviennent pas en termes de pureté du code. Par exemple, parmi les anti-modèles, nous incluons toutes les techniques qui travaillent avec l'[état global |global state] ou ce que l'on appelle le [Service Locator |#What is a Service Locator].


Qu'est-ce qu'un Service Locator ? .[#toc-what-is-a-service-locator]
-------------------------------------------------------------------

Un localisateur de services est une alternative à l'injection de dépendances. Il fonctionne en créant un stockage central où tous les services ou dépendances disponibles sont enregistrés. Lorsqu'un objet a besoin d'une dépendance, il la demande au localisateur de services.

Cependant, par rapport à l'injection de dépendances, elle perd en transparence : les dépendances ne sont pas directement transmises aux objets et ne sont donc pas facilement identifiables, ce qui nécessite d'examiner le code pour découvrir et comprendre toutes les connexions. Les tests sont également plus compliqués, car nous ne pouvons pas simplement passer des objets fictifs aux objets testés, mais nous devons passer par le Service Locator. En outre, le Service Locator perturbe la conception du code, car les objets individuels doivent être conscients de son existence, ce qui diffère de l'injection de dépendances, où les objets n'ont aucune connaissance du conteneur DI.


Quand est-il préférable de ne pas utiliser l'injection de dépendance ? .[#toc-when-is-it-better-not-to-use-di]
--------------------------------------------------------------------------------------------------------------

Il n'y a pas de difficultés connues liées à l'utilisation du modèle de conception de l'injection de dépendances. Au contraire, l'obtention de dépendances à partir d'emplacements accessibles globalement entraîne un [certain nombre de complications |global-state], tout comme l'utilisation d'un localisateur de services.
Il est donc conseillé de toujours utiliser l'injection de dépendances. Il ne s'agit pas d'une approche dogmatique, mais simplement de l'absence d'une meilleure alternative.

Cependant, dans certaines situations, il n'est pas nécessaire de se transmettre des objets et de les obtenir dans l'espace global. Par exemple, lors du débogage d'un code, il est nécessaire de vidanger la valeur d'une variable à un moment précis du programme, de mesurer la durée d'une certaine partie du programme ou d'enregistrer un message.
Dans de tels cas, lorsqu'il s'agit d'actions temporaires qui seront ultérieurement supprimées du code, il est légitime d'utiliser un dumper, un chronomètre ou un logger accessible globalement. Ces outils, après tout, ne font pas partie de la conception du code.


L'utilisation de l'ID présente-t-elle des inconvénients ? .[#toc-does-using-di-have-its-drawbacks]
--------------------------------------------------------------------------------------------------

L'utilisation de l'injection de dépendances présente-t-elle des inconvénients, tels qu'une complexité accrue de l'écriture du code ou une baisse des performances ? Que perdons-nous lorsque nous commençons à écrire du code conformément à l'injection de dépendances ?

L'injection de dépendances n'a aucun impact sur les performances de l'application ou sur les besoins en mémoire. La performance du conteneur DI peut jouer un rôle, mais dans le cas de [Nette DI | nette-container], le conteneur est compilé en PHP pur, de sorte que sa surcharge pendant l'exécution de l'application est pratiquement nulle.

Lors de l'écriture du code, il est nécessaire de créer des constructeurs qui acceptent les dépendances. Dans le passé, cela pouvait prendre du temps, mais grâce aux IDE modernes et à la [promotion des propriétés des constructeurs |https://blog.nette.org/fr/php-8-0-apercu-complet-des-nouveautes#toc-constructor-property-promotion], c'est maintenant une question de quelques secondes. Les usines peuvent être facilement générées à l'aide de Nette DI et d'un plugin PhpStorm en quelques clics.
D'autre part, il n'est pas nécessaire d'écrire des singletons et des points d'accès statiques.

On peut conclure qu'une application bien conçue utilisant DI n'est ni plus courte ni plus longue qu'une application utilisant des singletons. Les parties du code travaillant avec les dépendances sont simplement extraites des classes individuelles et déplacées vers de nouveaux emplacements, c'est-à-dire le conteneur DI et les usines.


Comment réécrire une application existante en DI ? .[#toc-how-to-rewrite-a-legacy-application-to-di]
----------------------------------------------------------------------------------------------------

La migration d'une application existante vers l'injection de dépendances peut être un processus difficile, en particulier pour les applications complexes et de grande taille. Il est important d'aborder ce processus de manière systématique.

- Lors du passage à l'injection de dépendances, il est important que tous les membres de l'équipe comprennent les principes et les pratiques utilisés.
- Tout d'abord, effectuez une analyse de l'application existante afin d'identifier les composants clés et leurs dépendances. Créez un plan pour savoir quelles parties seront remaniées et dans quel ordre.
- Implémenter un conteneur DI ou, mieux encore, utiliser une bibliothèque existante telle que Nette DI.
- Refondre progressivement chaque partie de l'application pour utiliser l'injection de dépendances. Cela peut impliquer de modifier les constructeurs ou les méthodes pour qu'ils acceptent les dépendances en tant que paramètres.
- Modifier les endroits du code où les objets de dépendance sont créés afin que les dépendances soient injectées par le conteneur. Cela peut inclure l'utilisation d'usines.

N'oubliez pas que le passage à l'injection de dépendances est un investissement dans la qualité du code et la viabilité à long terme de l'application. Bien qu'il puisse être difficile d'effectuer ces changements, le résultat devrait être un code plus propre, plus modulaire et plus facilement testable, prêt pour les extensions et la maintenance futures.


Pourquoi la composition est-elle préférable à l'héritage ? .[#toc-why-composition-is-preferred-over-inheritance]
----------------------------------------------------------------------------------------------------------------
Il est préférable d'utiliser la [composition |nette:introduction-to-object-oriented-programming#composition] plutôt que l'[héritage |nette:introduction-to-object-oriented-programming#inheritance] car elle permet de réutiliser le code sans avoir à se soucier des conséquences des changements. Ainsi, elle permet un couplage plus lâche où nous n'avons pas à nous soucier du fait que la modification d'un code entraînera la nécessité de modifier d'autres codes dépendants. Un exemple typique est une situation appelée " [enfer du constructeur" |passing-dependencies#Constructor hell].


Nette DI Container peut-il être utilisé en dehors de Nette ? .[#toc-can-nette-di-container-be-used-outside-of-nette]
--------------------------------------------------------------------------------------------------------------------

Absolument. Le Nette DI Container fait partie de Nette, mais il est conçu comme une bibliothèque autonome qui peut être utilisée indépendamment des autres parties du framework. Il suffit de l'installer à l'aide de Composer, de créer un fichier de configuration définissant vos services, puis d'utiliser quelques lignes de code PHP pour créer le conteneur DI.
Et vous pouvez immédiatement commencer à tirer parti de l'injection de dépendances dans vos projets.

Le chapitre sur le [conteneur DI de Nette |nette-container] décrit un cas d'utilisation spécifique, y compris le code.


Pourquoi la configuration se fait-elle dans des fichiers NEON ? .[#toc-why-is-the-configuration-in-neon-files]
--------------------------------------------------------------------------------------------------------------

NEON est un langage de configuration simple et facilement lisible développé au sein de Nette pour configurer les applications, les services et leurs dépendances. Comparé à JSON ou YAML, il offre des options beaucoup plus intuitives et flexibles à cet effet. En NEON, vous pouvez naturellement décrire des bindings qu'il ne serait pas possible d'écrire en Symfony & YAML, soit du tout, soit seulement au travers d'une description complexe.


L'analyse des fichiers NEON ralentit-elle l'application ? .[#toc-does-parsing-neon-files-slow-down-the-application]
-------------------------------------------------------------------------------------------------------------------

Bien que les fichiers NEON soient analysés très rapidement, cet aspect n'a pas vraiment d'importance. En effet, l'analyse des fichiers n'a lieu qu'une seule fois lors du premier lancement de l'application. Ensuite, le code du conteneur DI est généré, stocké sur le disque et exécuté pour chaque demande ultérieure sans qu'il soit nécessaire de procéder à une nouvelle analyse.

C'est ainsi que cela fonctionne dans un environnement de production. Pendant le développement, les fichiers NEON sont analysés chaque fois que leur contenu est modifié, ce qui garantit que le développeur dispose toujours d'un conteneur DI à jour. Comme nous l'avons déjà mentionné, l'analyse proprement dite se fait en un instant.


Comment puis-je accéder aux paramètres du fichier de configuration dans ma classe ? .[#toc-how-do-i-access-the-parameters-from-the-configuration-file-in-my-class]
------------------------------------------------------------------------------------------------------------------------------------------------------------------

Gardez à l'esprit la [Règle n° 1 : Laissez-le vous être transmis |introduction#Rule #1: Let It Be Passed to You]. Si une classe nécessite des informations provenant d'un fichier de configuration, il n'est pas nécessaire de déterminer comment accéder à ces informations ; au lieu de cela, nous les demandons simplement - par exemple, par l'intermédiaire du constructeur de la classe. Et nous effectuons le transfert dans le fichier de configuration.

Dans cet exemple, `%myParameter%` est un espace réservé pour la valeur du paramètre `myParameter`, qui sera transmis au constructeur `MyClass`:

```php
# config.neon
parameters:
	myParameter: Some value

services:
	- MyClass(%myParameter%)
```

Si vous souhaitez passer plusieurs paramètres ou utiliser le câblage automatique, il est utile d'[envelopper les paramètres dans un objet |best-practices:passing-settings-to-presenters].


Nette prend-il en charge l'interface PSR-11 Container ? .[#toc-does-nette-support-psr-11-container-interface]
-------------------------------------------------------------------------------------------------------------

Nette DI Container ne supporte pas directement PSR-11. Cependant, si vous avez besoin d'interopérabilité entre le Nette DI Container et des bibliothèques ou des frameworks qui attendent l'interface de conteneur PSR-11, vous pouvez créer un [simple adaptateur |https://gist.github.com/dg/7f02403bd36d9d1c73802a6268a4361f] pour servir de pont entre le Nette DI Container et PSR-11.

Questions fréquemment posées sur DI (FAQ)

DI est-il un autre nom pour IoC ?

Inversion of Control (IoC) est un principe axé sur la manière dont le code est exécuté – que votre code initie un code externe ou que votre code soit intégré dans un code externe, qui l'appelle ensuite. L'inversion de contrôle est un concept large qui inclut les événements, le principe dit d'Hollywood et d'autres aspects. Les usines, qui font partie de la règle n° 3 : laisser l'usine s'en charger, et représentent l'inversion de l'opérateur new, sont également des composantes de ce concept.

Dependency Injection (DI) concerne la manière dont un objet connaît un autre objet, c'est-à-dire la dépendance. Il s'agit d'un modèle de conception qui exige le passage explicite des dépendances entre les objets.

On peut donc dire que l'injection de dépendances est une forme spécifique d'IoC. Cependant, toutes les formes de contrôle interne ne conviennent pas en termes de pureté du code. Par exemple, parmi les anti-modèles, nous incluons toutes les techniques qui travaillent avec l'état global ou ce que l'on appelle le Service Locator.

Qu'est-ce qu'un Service Locator ?

Un localisateur de services est une alternative à l'injection de dépendances. Il fonctionne en créant un stockage central où tous les services ou dépendances disponibles sont enregistrés. Lorsqu'un objet a besoin d'une dépendance, il la demande au localisateur de services.

Cependant, par rapport à l'injection de dépendances, elle perd en transparence : les dépendances ne sont pas directement transmises aux objets et ne sont donc pas facilement identifiables, ce qui nécessite d'examiner le code pour découvrir et comprendre toutes les connexions. Les tests sont également plus compliqués, car nous ne pouvons pas simplement passer des objets fictifs aux objets testés, mais nous devons passer par le Service Locator. En outre, le Service Locator perturbe la conception du code, car les objets individuels doivent être conscients de son existence, ce qui diffère de l'injection de dépendances, où les objets n'ont aucune connaissance du conteneur DI.

Quand est-il préférable de ne pas utiliser l'injection de dépendance ?

Il n'y a pas de difficultés connues liées à l'utilisation du modèle de conception de l'injection de dépendances. Au contraire, l'obtention de dépendances à partir d'emplacements accessibles globalement entraîne un certain nombre de complications, tout comme l'utilisation d'un localisateur de services. Il est donc conseillé de toujours utiliser l'injection de dépendances. Il ne s'agit pas d'une approche dogmatique, mais simplement de l'absence d'une meilleure alternative.

Cependant, dans certaines situations, il n'est pas nécessaire de se transmettre des objets et de les obtenir dans l'espace global. Par exemple, lors du débogage d'un code, il est nécessaire de vidanger la valeur d'une variable à un moment précis du programme, de mesurer la durée d'une certaine partie du programme ou d'enregistrer un message. Dans de tels cas, lorsqu'il s'agit d'actions temporaires qui seront ultérieurement supprimées du code, il est légitime d'utiliser un dumper, un chronomètre ou un logger accessible globalement. Ces outils, après tout, ne font pas partie de la conception du code.

L'utilisation de l'ID présente-t-elle des inconvénients ?

L'utilisation de l'injection de dépendances présente-t-elle des inconvénients, tels qu'une complexité accrue de l'écriture du code ou une baisse des performances ? Que perdons-nous lorsque nous commençons à écrire du code conformément à l'injection de dépendances ?

L'injection de dépendances n'a aucun impact sur les performances de l'application ou sur les besoins en mémoire. La performance du conteneur DI peut jouer un rôle, mais dans le cas de Nette DI, le conteneur est compilé en PHP pur, de sorte que sa surcharge pendant l'exécution de l'application est pratiquement nulle.

Lors de l'écriture du code, il est nécessaire de créer des constructeurs qui acceptent les dépendances. Dans le passé, cela pouvait prendre du temps, mais grâce aux IDE modernes et à la promotion des propriétés des constructeurs, c'est maintenant une question de quelques secondes. Les usines peuvent être facilement générées à l'aide de Nette DI et d'un plugin PhpStorm en quelques clics. D'autre part, il n'est pas nécessaire d'écrire des singletons et des points d'accès statiques.

On peut conclure qu'une application bien conçue utilisant DI n'est ni plus courte ni plus longue qu'une application utilisant des singletons. Les parties du code travaillant avec les dépendances sont simplement extraites des classes individuelles et déplacées vers de nouveaux emplacements, c'est-à-dire le conteneur DI et les usines.

Comment réécrire une application existante en DI ?

La migration d'une application existante vers l'injection de dépendances peut être un processus difficile, en particulier pour les applications complexes et de grande taille. Il est important d'aborder ce processus de manière systématique.

  • Lors du passage à l'injection de dépendances, il est important que tous les membres de l'équipe comprennent les principes et les pratiques utilisés.
  • Tout d'abord, effectuez une analyse de l'application existante afin d'identifier les composants clés et leurs dépendances. Créez un plan pour savoir quelles parties seront remaniées et dans quel ordre.
  • Implémenter un conteneur DI ou, mieux encore, utiliser une bibliothèque existante telle que Nette DI.
  • Refondre progressivement chaque partie de l'application pour utiliser l'injection de dépendances. Cela peut impliquer de modifier les constructeurs ou les méthodes pour qu'ils acceptent les dépendances en tant que paramètres.
  • Modifier les endroits du code où les objets de dépendance sont créés afin que les dépendances soient injectées par le conteneur. Cela peut inclure l'utilisation d'usines.

N'oubliez pas que le passage à l'injection de dépendances est un investissement dans la qualité du code et la viabilité à long terme de l'application. Bien qu'il puisse être difficile d'effectuer ces changements, le résultat devrait être un code plus propre, plus modulaire et plus facilement testable, prêt pour les extensions et la maintenance futures.

Pourquoi la composition est-elle préférable à l'héritage ?

Il est préférable d'utiliser la composition plutôt que l'héritage car elle permet de réutiliser le code sans avoir à se soucier des conséquences des changements. Ainsi, elle permet un couplage plus lâche où nous n'avons pas à nous soucier du fait que la modification d'un code entraînera la nécessité de modifier d'autres codes dépendants. Un exemple typique est une situation appelée " enfer du constructeur".

Nette DI Container peut-il être utilisé en dehors de Nette ?

Absolument. Le Nette DI Container fait partie de Nette, mais il est conçu comme une bibliothèque autonome qui peut être utilisée indépendamment des autres parties du framework. Il suffit de l'installer à l'aide de Composer, de créer un fichier de configuration définissant vos services, puis d'utiliser quelques lignes de code PHP pour créer le conteneur DI. Et vous pouvez immédiatement commencer à tirer parti de l'injection de dépendances dans vos projets.

Le chapitre sur le conteneur DI de Nette décrit un cas d'utilisation spécifique, y compris le code.

Pourquoi la configuration se fait-elle dans des fichiers NEON ?

NEON est un langage de configuration simple et facilement lisible développé au sein de Nette pour configurer les applications, les services et leurs dépendances. Comparé à JSON ou YAML, il offre des options beaucoup plus intuitives et flexibles à cet effet. En NEON, vous pouvez naturellement décrire des bindings qu'il ne serait pas possible d'écrire en Symfony & YAML, soit du tout, soit seulement au travers d'une description complexe.

L'analyse des fichiers NEON ralentit-elle l'application ?

Bien que les fichiers NEON soient analysés très rapidement, cet aspect n'a pas vraiment d'importance. En effet, l'analyse des fichiers n'a lieu qu'une seule fois lors du premier lancement de l'application. Ensuite, le code du conteneur DI est généré, stocké sur le disque et exécuté pour chaque demande ultérieure sans qu'il soit nécessaire de procéder à une nouvelle analyse.

C'est ainsi que cela fonctionne dans un environnement de production. Pendant le développement, les fichiers NEON sont analysés chaque fois que leur contenu est modifié, ce qui garantit que le développeur dispose toujours d'un conteneur DI à jour. Comme nous l'avons déjà mentionné, l'analyse proprement dite se fait en un instant.

Comment puis-je accéder aux paramètres du fichier de configuration dans ma classe ?

Gardez à l'esprit la Règle n° 1 : Laissez-le vous être transmis. Si une classe nécessite des informations provenant d'un fichier de configuration, il n'est pas nécessaire de déterminer comment accéder à ces informations ; au lieu de cela, nous les demandons simplement – par exemple, par l'intermédiaire du constructeur de la classe. Et nous effectuons le transfert dans le fichier de configuration.

Dans cet exemple, %myParameter% est un espace réservé pour la valeur du paramètre myParameter, qui sera transmis au constructeur MyClass:

# config.neon
parameters:
	myParameter: Some value

services:
	- MyClass(%myParameter%)

Si vous souhaitez passer plusieurs paramètres ou utiliser le câblage automatique, il est utile d'envelopper les paramètres dans un objet.

Nette prend-il en charge l'interface PSR-11 Container ?

Nette DI Container ne supporte pas directement PSR-11. Cependant, si vous avez besoin d'interopérabilité entre le Nette DI Container et des bibliothèques ou des frameworks qui attendent l'interface de conteneur PSR-11, vous pouvez créer un simple adaptateur pour servir de pont entre le Nette DI Container et PSR-11.