Des problèmes avec la circulaire de la dépendance et de la programmation orientée objet en AngularJS
AngularJS + la programmation orientée objet est un peu sexy fonctionnalité à utiliser
Salut, je suis avec succès à l'aide de la programmation orientée objet avec AngularJs pour un certain temps déjà (d'abord commencé avec angularjs avec l'héritage de la programmation orientée objet en action), la démarche permet de définir vos classes angulaire de services, que vous pourrez ensuite prolonger ou d'hériter de ce genre:
Application.factory('AbstractObject', [function () {
var AbstractObject = Class.extend({
virtualMethod: function() {
alert("Hello world");
},
abstractMethod: function() { //You may omit abstract definitions, but they make your interface more readable
throw new Error("Pure abstract call");
}
});
return AbstractObject; //You return class definition instead of it's instance
}]);
Application.factory('DerivedObject', ['AbstractObject', function (AbstractObject) {
var DerivedObject = AbstractObject.extend({
virtualMethod: function() { //Shows two alerts: `Hey!` and `Hello world`
alert("Hey!");
this._super();
},
abstractMethod: function() {
alert("Now I'm not abstract");
}
});
return DerivedObject;
}]);
Plunker: http://plnkr.co/edit/rAtVGAsNYggBhNADMeoT
en utilisant l'approche décrite, vous donne la possibilité de définir des classes qui magnifiquement intégrer dans angulaire de l'infrastructure. Vous obtenez toutes sortes de fonctionnalités intéressantes à partir de deux mondes - POO et AngularJs. L'injection de dépendance est gratuit pour vos classes, et il rend vos classes très simple, permet de mettre beaucoup de texte standard contrôleur de code dans certains de la classe de base qui peut ensuite être réutilisé.
Cependant
AngularJs infrastructure blocs précédemment décrit approche de déploie ses ailes sur tous les 100%. Le problème se produit lorsque vous essayez de définir récursive définitions de classe (c'est à dire récursive de l'agrégation), disons que vous avez deux définitions de classe comme Blog
et Tag
Application.factory('Blog', ['Tag', function (Tag) {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
return Blog;
}]);
Application.factory('Tag', ['Blog', function (Blog) {
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return Tag;
}]);
Ça ne marchera pas parce que les deux Blog
et Tag
sont auto-référencement eux-mêmes, provoquant la dépendance circulaire.
P. S
La dernière chose, j'ai trouvé un peu laid solution qui résout mon problème, dans mon cas précis, mais ne fonctionne pas, en général, et comme je l'ai dit, il n'est pas assez:
Application.factory('BlogNamespace', [function () {
var Blog = Class.extend({
tags: function() {
return this.tags;
}
});
var Tag = Class.extend({
Blogs: function() {
return this.blogs;
}
});
return {
Tag: Tag,
Blog: Blog
};
}]);
Question
Le correctif ci-dessus ne fonctionnera pas parce que les espaces de noms peuvent aussi être un objet de dépendance circulaire. Cela signifie qu'il n'est pas la solution au problème décrit, mais plutôt un niveau plus profond problème maintenant.
Des suggestions sur la façon dont il est possible de résoudre ce problème décrit dans le cas général?
Vous devez vous connecter pour publier un commentaire.
Une dépendance circulaire est toujours le signe de mélange de préoccupations, qui est vraiment une mauvaise chose. Miško Hevery, l'un des auteurs de AngularJS, explique une belle solution sur son blog génial. En bref, vous avez probablement un troisième service caché quelque part, qui est la seule partie de votre code vraiment nécessaire par les deux autres.
Tag
etBlog
prouve que Misko est juste, parce que ce sont des sortes d'entités de base de données qui se rapportent l'un à l'autre comme N:M et dans des bases relationnelles monde ce genre de situation est également résolu par le représentant de la troisième table relationnelle qui contient la référence à la fois àTag
etBlog
commeBlogTags
BlogTags
usine quiBlog
etTag
obtenir injecté avec? J'aurais vraiment préféré ne pas ajouter de "se joindre à la table des classes" dans ma base de code si je peux l'aider... Si ma seule autre option est de dépendances circulaires à l'aide de$injetor.get
comme vous l'avez souligné, je peut juste s'en tenir à cela.Je vais répondre à ma propre question juste parce que j'ai trouvé un moyen technique de résolution de la question que j'ai posté sur. Mais avant cela, je vous encourage fortement à utiliser sa suggestion, puisqu'il permet de résoudre un ensemble de problèmes qui sont généralement causées par une mauvaise architecture. Veuillez vous préférez l'utilisation de son approche en premier, et le retour de courant dans le cas où vous savez ce que vous faites.
Voilà:
Vous pouvez utiliser
$injector
service et injecter les définitions nécessaires au moment de l'exécution, ce qui est légal du point de vue technique, mais encore une fois selon cette post (difficile d'imaginer qu'il est écrit en 2008), c'est comme une magie noire, le faire et il va vous frapper en arrière:Modifier
Il s'est avéré que l'approche actuelle est un exemple de Service Locator modèle, qui est du Cio Antipattern.
DERNIER RECOURS: NE PAS ENCOURAGER LES
Dans mon cas, la meilleure façon de se déplacer d'une circulaire de la dépendance à des problème de ce genre dans angulaire, est à la fonction de déclenchement des appels via
$rootScope
-émissions. L'autre service peut ensuite écouter cette émission et de réagir avec la fonction souhaitée appel. Il peut ne pas être la solution la plus élégante, mais dans certains cas où l'interaction entre les services est essentiellement unidirectionnelle, de toute façon, il peut être une alternative raisonnable. (notez que cela permet également de retour-les valeurs à être passé à la fonction de diffuseur via des rappels uniquement)Un pseudo-exemple de ceci serait:
$broadcast
) n'était pas sensée être largement utilisé dans la production (je veux dire de la façon dont vous le proposer) c'est pourquoi il a cette$
signe de dollar avant.$broadcast
est l'un des plus grands défauts de conception qui n'a jamais été introduit angulaire. Il a gagné en popularité parmi embryon de communauté uniquement en raison d'un manque de compréhension / de la documentation et des exemples pour les premières versions de anguleux. Pour la plupart presque tous les cas d'utilisation qui implique$broadcast
peut être réécrite en direct de l'appel de fonction. L'utilisation de$broadcast
est un signe d'un problème dans votre application architecture.$broadcast
fait bien à l'est de votre code opaque et imprévisible. Regarder quelqu'un de code, vous ne savez jamais ce cas, vous devez vous abonner. Vous ne pouvez jamais être sûr que vous avez les abonnés abonnez. Et lorsque l'événement se produit, vous ne savez jamais qui l'a initié. Il est toujours près à la magie noire, la magie noire. Ne l'utilisez pas, il fera de votre projet jusqu'mauvais, vraiment mauvais.