Est ServiceLocator un anti-modèle?
J'ai lu récemment Marque Seemann de l'article sur le Service Localisateur anti-modèle.
Auteur souligne deux principales raisons pour lesquelles les ServiceLocator est un anti-pattern:
-
D'utilisation de l'API question (dont je suis parfaitement bien avec)
Quand la classe emploie un localisateur de Service, il est très dur de voir ses dépendances, dans la plupart des cas, la classe n'a qu'un constructeur sans paramètre.
En contraste avec ServiceLocator, DI approche exposer explicitement les dépendances via les paramètres du constructeur si les dépendances sont facile vu dans IntelliSense. -
Problème d'entretien (ce qui m'intrigue, c')
Considérez les points suivants expample
Nous avons une classe 'MyType' qui emploie un localisateur de Service d'approche:
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
}
}
Maintenant, nous voulons ajouter une autre dépendance à la classe de MyType'
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
//new dependency
var dep2 = Locator.Resolve<IDep2>();
dep2.DoSomething();
}
}
Et c'est là où mon incompréhension commence. L'auteur dit:
Il devient beaucoup plus difficile de dire si vous êtes l'introduction d'une modification de rupture ou non. Vous avez besoin de comprendre l'ensemble de l'application dans laquelle le Service Locator est utilisée, et que le compilateur ne va pas vous aider.
Mais attendez une seconde, si nous étions à l'aide de DI approche, nous allons introduire une dépendance avec un autre paramètre dans le constructeur (dans le cas du constructeur d'injection). Et le problème sera toujours là. Si l'on peut oublier de configurer ServiceLocator, alors on peut oublier d'ajouter une nouvelle cartographie dans notre conteneur IoC et DI approche aurait le même problème de temps.
Aussi, l'auteur a mentionné à propos de l'unité de test de difficultés. Mais, ne nous ont des problèmes avec DI approche? Ne portons-nous pas besoin de mettre à jour tous les tests qui ont été l'instanciation de cette classe? Nous avons mis à jour à passer un nouveau moqué de dépendance juste pour faire notre test compilable. Et je ne vois pas les avantages de cette mise à jour et de passer du temps.
Je ne suis pas en train de défendre le Service Localisateur d'approche. Mais cette incompréhension me font penser que je vais perdre quelque chose de très important. Quelqu'un pourrait dissiper mes doutes?
MISE À JOUR (RÉSUMÉ):
La réponse à ma question "Est le Service Localisateur d'un anti-pattern" dépend vraiment de la situation. Et je ne dirais pas pour la rayer de votre liste d'outils. Il peut être très pratique lorsque vous commencez à traiter avec le code existant. Si vous êtes assez chanceux pour être au tout début de votre projet, alors les DI approche pourrait être un meilleur choix car il a certains avantages par rapport au Service Locator.
Et ici sont les principales différences qui m'a convaincu de ne pas utiliser le Service de Localisateur pour mes nouveaux projets:
- Le plus évident et important: le Service Localisateur de masque de classe dépendances
- Si vous êtes en utilisant un conteneur IoC, il ne sera probablement analyser tous les constructeur au démarrage afin de valider l'ensemble des dépendances et de vous donner de la rétroaction immédiate manquant mappages (ou de la mauvaise configuration); ce n'est pas possible si vous utilisez votre conteneur IoC en tant que Service Locator
Pour plus de détails lire d'excellentes réponses qui sont données ci-dessous.
Vous avez raison, ça dépend. Dans les grandes applications Android, par exemple, jusqu'à présent, les gens ont été très réticents à utiliser DI en raison de problèmes de performances sur les bas spec appareils mobiles. Dans de tels cas, vous devez trouver une alternative à toujours écrire de code de tests, et je dirais Service Locator est un bon-assez de substitution dans ce cas. (Note: les choses peuvent changer pour Android quand la nouvelle de la Dague 2.0 DI-cadre est assez mature.)
Notez que depuis que cette question a été posté, il y a une mise à jour sur la Marque Seemann Service Locator est un Anti-Patron de la poste décrivant la façon dont le service localisateur de viole de la programmation orientée objet par briser l'encapsulation, qui est son meilleur argument encore (et la raison sous-jacente de tous les symptômes qu'il a utilisé dans tous les avant les arguments). mise à Jour 2015-10-26: Le problème fondamental avec le Service Locator, c'est qu'il viole l'encapsulation.
OriginalL'auteur davidoff | 2014-04-01
Vous devez vous connecter pour publier un commentaire.
Si vous définir des modèles comme les anti-modèles juste parce qu'il y a certaines situations où il n'est pas bon, alors, OUI, c'est un anti-modèle. Mais avec ce raisonnement, tous les modèles serait aussi anti-modèles.
Au contraire, nous devons regarder si il y a valide les usages des modèles, et pour le Service Locator il y a plusieurs cas d'utilisation. Mais nous allons commencer par regarder les exemples que vous avez donné.
L'entretien cauchemar avec cette classe, c'est que les dépendances sont cachés. Si vous créez et l'utilisation de cette classe:
Vous ne comprenez pas qu'il a des dépendances s'ils sont masqués à l'aide de l'emplacement du service. Maintenant, si nous avons plutôt utiliser l'injection de dépendance:
Vous pouvez directement spot les dépendances et ne peut pas utiliser les classes avant de le satisfaire.
Dans une ligne typique d'application d'entreprise, vous devez éviter l'utilisation de services de localisation pour cette raison. Il devrait être le modèle à utiliser quand il n'y a pas d'autres options.
Est le modèle d'un anti-modèle?
Pas.
Par exemple, l'inversion de contrôle des conteneurs ne pourrait pas fonctionner sans le service de localisation. C'est la façon dont ils résolvent les services en interne.
Mais un bien meilleur exemple est ASP.NET MVC et WebApi. Que pensez-vous fait de l'injection de dépendance possible dans les contrôleurs? C'est là que l'emplacement du service.
Vos questions
Il y a deux problèmes plus graves:
Avec le constructeur d'injection à l'aide d'un conteneur de vous gratuit.
C'est vrai. Mais avec le constructeur injection, vous n'avez pas de scanner l'ensemble de la classe pour savoir qui dépendances manquantes.
Et certains mieux conteneurs également de valider l'ensemble des dépendances au démarrage (par l'analyse de tous les constructeurs). Donc, avec ces conteneurs, vous obtenez l'erreur d'exécution directement, et pas plus tard temporelle point.
Pas. Comme vous n'avez pas de dépendance à un service statique de localisation. Avez-vous essayé d'obtenir des tests en parallèle de travail statique des dépendances? Ce n'est pas amusant.
Votre seul argument pour le Service Localisateur de ne pas être un anti-modèle est la suivante: "l'inversion de contrôle des conteneurs ne pourrait pas fonctionner sans le service de localisation". Cet argument est cependant pas valide, puisque le Service Locator est sur les intentions et non pas sur la mécanique, comme l'explique clairement ici par Mark Seemann: "UN conteneur d'injection de dépendances encapsulé dans une Composition de la Racine n'est pas un Localisateur de Service - c'est une composante de l'infrastructure."
Web API ne pas utiliser le Service de Localisation pour les DI dans les Contrôleurs. Il ne fait pas de DI. Ce qu'il fait est: Il vous donne la possibilité de créer vos propres ControllerActivator de passer dans la Configuration des Services. À partir de là, vous pouvez créer une composition de racine, qu'il soit Pur, DI, ou dans des Conteneurs. Aussi, vous sont un mélange de l'utilisation de l'Emplacement du Service, en tant que composante de votre modèle, avec la définition de "Service de Patron de localisation." Avec cette définition, la Composition de la Racine DI peut être considéré comme un "Service Patron de localisation." Donc tout l'intérêt de cette définition est discutable.
Je veux souligner que c'est généralement une bonne réponse, j'ai juste commenté un trompeur point que vous avez fait.
DI et SL sont les deux version de "restitutions" de la Coi. SL est juste le mal moyen de le faire. Un conteneur IoC être SL, ou il pourrait utiliser DI. Cela dépend de comment c'est câblé. Mais SL est mauvais, mauvais, mauvais. C'est une façon de cacher le fait que vous êtes étroitement associant tout ensemble.
OriginalL'auteur jgauffin
Je tiens également à souligner que, SI vous êtes à la refactorisation de code hérité que le Service Locator modèle n'est pas seulement un anti-modèle, mais c'est aussi une nécessité pratique. Personne ne va jamais de vague d'un coup de baguette magique sur des millions de lignes de code et tout à coup ce code va être DI prêt. Donc, si vous voulez commencer à introduire le DI à une base de code, c'est souvent le cas que l'on va changer les choses pour devenir DI services lentement, et le code qui fait référence à ces services souvent de ne PAS être DI services. D'où CES services, vous devrez utiliser le Localisateur de Service afin d'obtenir des instances de ces services qui ONT été converties pour utiliser les DI.
Donc lors d'un refactoring de grandes applications de commencer à utiliser DI concepts, je dirais que non seulement Localisateur de Service n'est PAS un anti-modèle, mais que c'est la seule façon de l'appliquer progressivement DI concepts à la base de code.
OriginalL'auteur jwells131313
De l'essai de point de vue, Localisateur de Service est mauvais. Voir Misko Hevery Google Tech Talk belle explication avec des exemples de code http://youtu.be/RlfLCWKxHJ0 de départ à la minute 8:45. J'ai aimé son analogie: si vous avez besoin de 25$, demander directement de l'argent plutôt que de donner à votre portefeuille d'où l'argent sera pris en compte. Il compare également Localisateur de Service avec une botte de foin qui a l'aiguille que vous avez besoin et sait comment faire pour le récupérer. Les Classes à l'aide de Localisateur de Service sont difficiles à réutiliser à cause de cela.
OriginalL'auteur user3511397
Il y a 2 raisons pour lesquelles l'aide de localisateur de service est mauvais dans ce domaine.
Clair et simple: Une classe avec un localisateur de service est plus difficile à réutiliser que celui qui accepte ses dépendances par le biais de son constructeur.
OriginalL'auteur NightOwl888
Ma connaissance n'est pas assez bon pour en juger, mais en général, je pense que si quelque chose a une utilisation dans une situation particulière, il ne signifie pas nécessairement qu'il ne peut pas être un anti-modèle. En particulier, lorsque vous traitez avec de la 3e partie des bibliothèques, vous n'avez pas le plein contrôle sur tous les aspects et vous pouvez vous retrouver à l'aide de la pas la meilleure solution.
Voici un paragraphe de Adaptative Code Via C#:
OriginalL'auteur Siavash Mortazavi
L'Auteur soutient que "le compilateur ne sera pas vous aider" - et c'est vrai.
Lorsque vous daignez une classe, vous aurez envie de choisir avec soin son interface - parmi d'autres objectifs pour le rendre le plus indépendant ... que ça fait du sens.
En amenant le client à accepter la référence à un service (une dépendance) explicite de l'interface, vous
Vous avez raison, la DI a ses problèmes et inconvénients, mais les avantages l'emportent sur eux, et de loin ... de l'OMI.
Vous avez raison, qu'avec DI il y a une dépendance introduit dans l'interface (constructeur) - mais ce n'est, espérons-le, très dépendance que vous avez besoin et que vous souhaitez rendre visible et vérifiable.
Le 'statique'/'au moment de la compilation vérification de l'argument est un homme de paille. @Davidoff a souligné, DI est également sensibles à des erreurs d'exécution. Je voudrais également ajouter que les Ide modernes fournir de l'info-bulle des vues de commentaire/résumé informations pour les membres, et même dans ceux qui n'en ont pas, quelqu'un va toujours être à la recherche à la documentation jusqu'à ce qu'elles "savent" de l'API. Documentation la documentation, si nécessaire paramètre du constructeur ou une remarque sur la façon de configurer une dépendance.
La réflexion sur la mise en œuvre de codage et d'assurance de la qualité - la lisibilité du code est un élément crucial, en particulier pour la définition de l'interface. Si vous pouvez faire sans automatique de la compilation des contrôles et si vous le faites de manière adéquate commentaire / document de votre interface, alors je suppose que vous pouvez au moins partiellement remédier aux inconvénients de l'cachée de la dépendance sur un type de variable globale avec pas facilement visible et prévisible contenu. Je dirais que vous avez besoin de bonnes raisons pour utiliser ce modèle qui l'emportent sur les inconvénients de cette.
OriginalL'auteur Zrin
Oui, localisateur de service est un anti-pattern, il viole l'encapsulation et solide.
OriginalL'auteur Alireza Rahmani Khalili