Lorsque je conçois mon système à partir de zéro, je suis souvent confronté à un dilemme: mon objet doit Transférer informations dans un autre objet OR si les objets doivent extraire les données nécessaires d’un autre objet.
Existe-t-il quelque chose qui ressemble à une norme dans la conception OOP, selon laquelle je devrais préférer que les données soient extraites par des objets plutôt que transférées dans des objets?
Quelqu'un peut-il avoir l'expérience de conseiller, si une approche est meilleure sur l'autre du point de vue à long terme , ou lorsque la structure/cadre/diagramme OOPdevient plus complexe?
Selon dites ne demandez pas , Push est meilleur - ou plus OO. Vous ne voulez pas interroger un objet pour obtenir des données afin de pouvoir faire quelque chose, vous voulez qu'un objet le fasse, car c'est lui qui connaît ses données.
Comme indiqué dans d'autres réponses, ni Push ni Pull n'est préférable, mais vous devez plutôt choisir celui qui correspond le mieux à vos besoins de conception.
De ici discuter du fait qu'un modèle d'observateur devrait être basé sur Push ou Pull:
Qui déclenche la mise à jour?
La communication entre le sujet et ses observateurs est terminée via la méthode notify déclarée dans l’observateur. Mais ça peut être déclenché depuis un sujet ou un objet observateur. Habituellement, le La méthode notify est déclenchée par le sujet lorsque son état est modifié . Mais parfois, lorsque les mises à jour sont fréquentes, les modifications consécutives de le sujet déterminera de nombreuses opérations de rafraîchissement inutiles dans le fichier observateur. Afin de rendre ce processus plus efficace, l'observateur peut être chargé de lancer l’opération de notification quand considérer nécessaire.
Pour ce motif, la caractéristique déterminante est la fréquence à laquelle les données changent, puis le débit correspondant auquel les observateurs souhaitent recevoir ces données. Si les observateurs souhaitent obtenir des données plus lentement que le sujet ne les génère (un exemple serait le GPS sur un téléphone, vous n’avez pas besoin de votre position tout le temps, mais uniquement lorsque vous en avez un usage spécifique). plus efficace. Si les observateurs veulent des données aussi rapides que le sujet peut les produire (un exemple possible serait une application de titre boursier en temps réel), les notifications push sont probablement meilleures.
Je pense que la discussion ici manque en quelque sorte le point crucial de tirer et pousser et elle est bloquée sur des exemples et des cas individuels.
Pousser: / L’avantage de pousser est que vous connaissez vos données et ce que vous poussez. Aucun composant ne connaît (ou ne devrait pas connaître) les données mieux que le composant qui en est propriétaire, ce qui impliquera théoriquement une meilleure conception et un système plus robuste.
Tirant : Le seul avantage que je vois dans l'approche tirant est que le composant tirant sait exactement quand il doit tirer. Il peut initier la conversation lorsqu'il a besoin des données et qu'aucun composant ne sait (ou ne devrait pas savoir) quand les données sont nécessaires, plutôt que le composant qui en a besoin.
Ma conclusion est la suivante: quel que soit le composant propriétaire de la transaction, il lance la transaction . Si vous récupérez des données à partir d'une API, il est évident que le client de l'API sera propriétaire de la transaction et procédera ainsi à une extraction. Si vous diffusez un message alors que le radiodiffuseur est propriétaire de la transaction, il effectue un Push.
Cela ne devrait pas être différent dans OOP (il y a peut-être quelque chose que j'ai oublié), mais une approche par traction est préférable.
La raison pour laquelle je dis que cela est dû aux tendances récentes dans les modèles de conception. Domain Driven Design and CQRS étant parmi les plus importants, ils favorisent le couplage lâche, ce qui est une très bonne chose.
Un objet ne doit pas se soucier de ce qu'un autre objet fait avec ses données, ce n'est pas sa responsabilité pour ainsi dire. L'objet doit uniquement rendre les données disponibles et ceux qui en ont besoin doivent les extraire/les extraire de cet objet. Regardez la conception événementielle.
Il rend l'objet indépendant des autres objets et le rend plus portable (il n'est pas nécessaire de changer où il pousse, car il sera retiré).
TL; DR Je recommanderais d'arrêter de pousser.
NOTE: Tous ces différents modèles ne s’excluent pas mais coexistent.
destination. Appuyez sur (source)
source. Pull (destination)
Sélectionnez votre solution en regardant les dépendances que vous souhaitez avoir dans votre code.
Si Source et Destination ne peuvent pas dépendre de ce qui est nécessaire pour le schéma précédent, l'action doit être effectuée par une méthode externe qui connaît (dépend) de la Source et de la Destination. Cependant, il n'a qu'un accès public aux deux.
Si vous avez besoin d'une source ISource virtuelle pour alimenter une IDestination, vous devez utiliser ces interfaces pour exposer toutes les méthodes nécessaires à une méthode externe pour effectuer l'action.
Si une seule méthode externe ne peut exécuter l'action sur aucune ISource ni aucune IDestination, vous pouvez examiner le modèle de visiteur, la classe de visiteur effectuant toutes les actions spécifiques sur les Source1 et SourceX Destination1 et DestinationY.
Le mot push/pull est relatif. Il y aura un pousseur qui a des données et il y aura un extracteur qui a besoin de données. Si nous stockons réellement les données dans un endroit neutre et non pas dans Push-er/Pull-er, de nombreuses possibilités s’offrent à vous de régler un problème à la fois. On met à jour les données quand il l’a (envoi de notification si nécessaire) et les autres tirent. les données à sa convenance ... De nombreux modèles de conception, MVC, Observer, Command, etc. sont en place pour gérer le scénario.
La réponse dépend de vos objectifs d'architecture, autrement dit, il n'y a pas de solution générale.
Dans une architecture client-serveur, vous aurez probablement un système en couches sur le backend où les objets extraient l'état d'autres objets. Cela signifie que seuls certains "services" mettront à jour l'état d'un objet. Exemple: créer un nouvel objet, mettre à jour le champ d'un objet, etc. (comme ajouter un nouveau poste de commande à la commande totale).
Dans une application de bureau monolithique, cela pourrait être complètement différent. Vous utilisez probablement des variantes de "Modèle-Vue-Contrôleur" et des modèles d'observateur, etc. Dans ce cas, vous transmettez des informations poussées, par exemple. à l'interface utilisateur.
Généralement, «extraire des données» signifie que vous passez un appel ajax et exécutez un rappel lorsque sa réponse a abouti. Ce n'est pas mauvais, mais cela peut être excessivement intensif si vous vérifiez les mises à jour des données et que vous le faites donc sur un intervalle.
Mais dans le contexte d’une application Web en ligne, une alternative à cela est Push avec longue interrogation. Puisque les longues interrogations ne sont pas très différentes de la première méthode, je vous propose de procéder comme suit:
Créez une méthode d'interrogation longue qui extrait les données d'un point de terminaison semi-public Push url (un service Web pour pubsub), puis mettez à jour tout ce qui doit être mis à jour à l'aide d'un modèle de conception éditeur/abonné de votre client. De cette façon, vos mises à jour sont davantage découplées de la source de données.
Voici un livre blanc écrit par IBM sur ce sujet. http://www.ibm.com/developerworks/library/specification/ws-pubsub/
Premièrement, la ligne directrice générale est claire: les objets sont data et behavior. Cela encourage moins de getters et donc moins de tire en fournissant des méthodes qui font quelque chose avec les données internes.
Seul "Push is better" (dans la réponse acceptée) ne peut pas fonctionner correctement, car une opération Push dans une classe donnée peut nécessiter une nouvelle traction sur l'objet poussé. Au lieu de cela, la meilleure pratique devrait être d'ajouter l'opération Push là où elle convient le mieux à l'abstraction. Cela peut même conduire à une nouvelle classe/composition de classes plus abstraite (voir Heuristiques de conception orientée objet , Riel, 1996, p. 37 et suivantes).
De mon point de vue ... En tant que développeur d’applications de bureau utilisant mvc, il existe un équilibre délicat qui vous permet de transmettre des données lorsque celles-ci sont disponibles à vos objets de modèle, puis de s’appuyer sur la logique du modèle (horloges/événements asynchrones/notifications), puis poussé vers les contrôleurs et ensuite vers la vue ... Les interactions ui peuvent aller dans les deux sens selon les préférences, elles peuvent déclencher un message d'actualisation ou de mise à jour qui indique au contrôleur qu'il doit faire quelque chose, ou peut spécifiquement Transférer des données dans le contrôleur et souvent à son tour le modèle.
Bien sûr, cela est simplifié et confondu avec des scénarios du monde réel, mais le fait de disposer des ressources suffisantes pour le faire d'une manière particulière peut aller très loin.