Je refactorise une application PHP , et j'essaie de faire autant d' injection de dépendance (DI) que possible.
Je sens que j'ai une bonne compréhension de son fonctionnement, et je peux certainement voir mes cours devenir beaucoup plus légers et plus robustes.
Je refactorise pour pouvoir injecter une dépendance plutôt que de créer un nouvel objet dans la classe, mais à un moment donné, je vais devoir créer des objets, c'est-à-dire utiliser le new
mot clé redouté .
Le problème que je rencontre maintenant est à quel point puis-je réellement créer de nouveaux objets? On dirait que je vais me retrouver dans une classe de haut niveau, créant des tas de nouveaux objets car il n'y a nulle part où aller. Cela ne va pas.
J'ai lu certains blogs qui utilisent des classes d'usine pour créer tous les objets, puis vous injectez l'usine dans d'autres classes. Vous pouvez alors appeler les méthodes d'usine et l'usine crée le nouvel objet pour vous.
Ce qui m'inquiète, c'est que mes cours d'usine vont être new
gratuits pour tous! Je suppose que cela peut être OK car ce sont des classes d'usine, mais y a-t-il des règles à respecter lors de l'utilisation d'un modèle d'usine et d'une DI, ou est-ce que je vais loin de la marque ici?
la source
new
. Bien sûr, il y a quelques points d'entrée où vous devez appeler dans le conteneur IoC, mais il ne devrait pas y en avoir beaucoup. En règle générale, vous configurez l'IoC une fois, puis demandez qu'une classe soit résolue par demande. Dans le cas de MVC, c'est généralement le contrôleur.Réponses:
Après un peu de recherche sur ce sujet, il semble que (comme mentionné dans un commentaire ci-dessus), la classe de niveau supérieur dont je parlais s'appelle la racine de composition .
Il semble en effet être la solution acceptée pour ajouter la création de tous les objets au sein de cette racine de composition (ou référencer un conteneur IoC à partir d'ici).
Ma préoccupation initiale à ce sujet était que cette classe de haut niveau finirait par être un peu en désordre. C'est vrai dans une certaine mesure, mais les avantages pèsent les inconvénients. Par exemple, je peux voir que la lisibilité, la testabilité et la maintenabilité de toutes mes autres classes se sont améliorées.
La classe de niveau supérieur peut être un peu désordonnée, jonchée de
new
,set_property()
mais je dois dire que je préfère en fait avoir tout ce code en un seul endroit plutôt que dispersé dans toutes les autres classesUne autre page utile pour discuter des performances de cette méthode ici
la source
Une classe Factory aura
new
saupoudré tout au long. Ce serait créer n'importe quel objet que vous demandez et probablement les dépendances de cet objet. Puisque le travail des usines est d'instancier le bon objet pour vous, avoirnew
dans cette classe n'est pas une mauvaise chose.DI est pour que vous ayez une conception à couplage lâche. Vous pouvez apporter des modifications à votre application en modifiant la dépendance fournie à chaque objet. Rendre votre application flexible, extensible et facile à tester.
Au niveau supérieur, vous disposerez d'un code qui instanciera quelques usines, établira des connexions aux services et enverra une réponse. Il aura une quantité importante d'
new
appels statiques pour instancier les objets nécessaires à votre application. Ce serait là que cela appartient.la source
Mes deux cents ici:
Vous ne précisez pas si vous utilisez un framework d'injection de dépendances. Je pense que vous devriez certainement. Utilisez quelque chose qui vous offre les fonctionnalités dont vous avez besoin: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .
Vous utilisez normalement la configuration ou un point central pour l'instanciation des objets initiaux qui composent votre application. Le conteneur créera les objets pour vous.
Vous accédez ensuite aux objets (services, fournisseurs, contrôleurs ...) via le conteneur IoC. Il créera de manière transparente un objet pour vous si nécessaire, ou vous donnera une référence à l'instance existante appropriée.
Bien sûr, dans votre implémentation particulière d'objets, vous pouvez instancier d'autres objets sur lesquels vous n'avez pas besoin de DI (structures de données, types personnalisés, etc.), mais c'est une programmation normale.
Normalement, vous utilisez une fabrique si vous souhaitez que le framework IoC instancie certains objets IoC via vos usines (cela est nécessaire lorsque l'instanciation d'un objet particulier nécessite un travail supplémentaire). Si vous pouvez simplement créer vos objets avec "new Object ()" et définir certaines propriétés, vous ne voulez pas nécessairement utiliser un modèle Factory.
En d'autres termes, je dirais que l'utilisation d'un modèle Factory pour une classe ou un groupe de classes dépend de la façon dont vous souhaitez modéliser ces classes, et non de l'utilisation de DI (sauf si votre implémentation DI nécessite explicitement des usines, ce qui est inhabituel).
Vous configurez également votre infrastructure IoC pour utiliser une usine lorsque vous utilisez une bibliothèque tierce qui nécessite déjà l'utilisation d'une usine. Dans ce cas, vous n'avez aucun contrôle à ce sujet et vous devez dire à votre conteneur IoC: "hé, quand je demande une de ces interfaces, vous devez utiliser cette usine pour me fournir une instance appropriée".
Dans ce cas, il semble que vous n'ayez pas besoin d'utiliser des modèles Factory pour ces objets / services / contrôleurs / quoi que ce soit, et vous pouvez simplement configurer votre IoC pour instancier avec "new" la classe appropriée et injecter tout le reste.
J'espère que ça aide.
la source
doing DI manually beats the whole purpose of using an Inversion of Control container
- Si vous entendez par là "... qui centralise vos dépendances dans un fichier de configuration", alors vous avez raison, car c'est tout ce qu'un conteneur IoC fait vraiment. Le véritable objectif de DI est le découplage, et vous pouvez le faire en fournissant vos dépendances dans une méthode constructeur. Vous n'avez pas du tout besoin d'un framework DI pour cela.