Dans la conception de mon programme, j'arrive souvent au point où je dois passer des instances d'objet à travers plusieurs classes. Par exemple, si j’ai un contrôleur qui charge un fichier audio, puis le passe à un lecteur, et le joueur le transmet au lecteurRunnable, qui le repasse à nouveau ailleurs, etc. savoir comment l'éviter. Ou est-ce bien de faire ça?
EDIT: Peut-être que l'exemple du lecteur n'est pas le meilleur car je pourrais charger le fichier plus tard, mais dans d'autres cas cela ne fonctionne pas.
la source
Intéressant que personne n'ait encore parlé d' objets immuables . Je dirais que le fait de passer d'un objet immuable à travers toutes les couches est une bonne chose plutôt que de créer beaucoup d'objets de courte durée pour chaque couche.
Eric Lippert discute de l'immutabilité sur son blog
D'autre part, je dirais que passer des objets mutables entre les couches est une mauvaise conception. Vous construisez essentiellement un calque avec la promesse que les calques environnants ne le modifieront pas de manière à casser votre code.
la source
Faire passer des instances d'objet est une chose normale à faire. Cela réduit la nécessité de conserver l'état (c'est-à-dire les variables d'instance) et dissocie le code de son contexte d'exécution.
Un problème auquel vous pouvez être confronté est le refactoring, lorsque vous devez modifier les signatures de plusieurs méthodes le long de la chaîne d’appel en réponse à la modification des exigences de paramètre d’une méthode située au bas de cette chaîne. Cependant, cela peut être atténué avec l'utilisation d'outils de développement de logiciels modernes qui facilitent le refactoring.
la source
Peut-être mineure, mais il y a le risque d'affecter cette référence quelque part dans l'une des couches, ce qui pourrait éventuellement causer une fuite de mémoire ou une référence en suspens.
la source
Si vous transmettez des objets simplement parce que vous en avez besoin dans une zone distante de votre code, l'utilisation de modèles de conception d'injection de contrôle et de dépendance ainsi que, éventuellement, d'un conteneur IoC approprié peut résoudre de manière satisfaisante les problèmes liés au transport d'instances d'objet. Je l'ai utilisé sur un projet de taille moyenne et je ne songerais plus jamais à écrire un gros morceau de code serveur sans l'utiliser.
la source
Passer des données dans un ensemble de couches n'est pas une mauvaise chose, c'est vraiment la seule façon pour un système en couches de fonctionner sans violer la structure en couches. Le problème, c’est que vous transmettez vos données à plusieurs objets du même calque pour atteindre votre objectif.
la source
Réponse rapide: Il n’ya rien de mal à passer des instances d’objets. Comme mentionné également, il convient de ne pas attribuer cette référence à toutes les couches, ce qui pourrait entraîner une perte de référence ou des fuites de mémoire.
Dans nos projets, nous utilisons cette pratique pour faire passer des objets DTO (objet de transfert de données) entre les couches et cette pratique est très utile. Nous réutilisons également nos objets dto pour construire une fois plus complexe, comme pour un résumé.
la source
Je suis avant tout un développeur d'interface utilisateur Web, mais il me semble que votre malaise intuitif réside peut-être moins dans la transmission d'instance que dans le fait que vous utilisez un peu de procédure avec ce contrôleur. Votre contrôleur doit-il transpirer tous ces détails? Pourquoi fait-il même référence au nom de plus d'un autre objet pour obtenir de l'audio lu?
Dans la conception POO, j'ai tendance à penser en termes de ce qui est toujours vert et de ce qui est plus susceptible d'être sujet à changement. Le sujet du changement est ce que vous allez vouloir mettre dans vos boîtes à objets plus grandes afin que vous puissiez maintenir des interfaces cohérentes même lorsque les joueurs changent ou que de nouvelles options sont ajoutées. Ou vous vous trouvez vouloir échanger des objets audio ou des composants en gros.
Dans ce cas, votre contrôleur doit déterminer qu’il est nécessaire de lire un fichier audio, puis de le faire de manière cohérente / permanente. Le lecteur audio, par contre, pourrait facilement changer à mesure que la technologie et les plates-formes sont modifiées ou que de nouveaux choix sont ajoutés. Tous ces détails doivent figurer sous l'interface d'un objet composite plus grand, IMO, et vous ne devriez pas avoir à réécrire votre contrôleur lorsque les détails de la manière dont l'audio est lu changent. Ensuite, lorsque vous transmettez une instance d'objet avec les détails tels que l'emplacement du fichier dans l'objet plus grand, tout échange est effectué à l'intérieur d'un contexte approprié dans lequel une personne est moins susceptible de faire quelque chose de stupide avec elle.
Donc, dans ce cas, je ne pense pas que ce soit cette instance d'objet renvoyée qui pourrait vous déranger. C’est que le capitaine Picard se rend dans la salle des machines pour allumer le noyau de chaîne, puis remonte sur le pont pour tracer les coordonnées, puis appuie sur le bouton «Coup de poing» après avoir activé les boucliers au lieu de nous à la planète X à la chaîne 9. Faites-le ainsi. " et laisser son équipe régler les détails. Parce que, lorsqu'il le gère de cette manière, il peut commander n'importe quel navire de la flotte sans connaître la configuration de chaque navire et son fonctionnement. Et c’est finalement la plus grande victoire de conception POO pour laquelle tirer, IMO.
la source
C'est une conception assez commune qui finit par se produire, même si vous pouvez avoir des problèmes de latence si votre application est sensible à ce genre de chose.
la source
Ce problème peut être résolu avec des variables à portée dynamique, si votre langue les utilise, ou un stockage local au thread. Ces mécanismes nous permettent d'associer des variables personnalisées à une chaîne d'activation ou à un thread de contrôle, de sorte que nous ne soyons pas obligés de transférer ces valeurs dans un code qui n'a rien à voir avec elles, simplement pour pouvoir les communiquer avec un autre code. qui en a besoin.
la source
Comme les autres réponses l'ont souligné, ce n'est pas une conception intrinsèquement médiocre. Il peut créer un couplage étroit entre les classes imbriquées et celles qui les imbriquent, mais le desserrage du couplage peut ne pas être une option valide si l'imbrication des références fournit une valeur à la conception.
Une solution possible consiste à "aplatir" les références imbriquées dans la classe du contrôleur.
Au lieu de transmettre plusieurs fois un paramètre via des objets imbriqués, vous pouvez conserver dans le contrôleur des références à tous les objets imbriqués.
La façon dont cela est mis en œuvre (ou même s’il s’agit même d’une solution valable) dépend de la conception actuelle du système, telle que:
C'est un problème que j'ai rencontré dans un modèle de conception MVC pour un client GXT. Nos composants d'interface graphique contenaient des composants d'interface graphique imbriqués pour plusieurs couches. Lorsque les données du modèle ont été mises à jour, nous avons fini par les faire passer à travers plusieurs couches jusqu'à atteindre le ou les composants appropriés. Cela créait un couplage indésirable entre les composants de l'interface graphique, car si nous souhaitions qu'une nouvelle classe de composant d'interface graphique accepte les données de modèle, nous devions créer des méthodes pour mettre à jour les données de modèle dans tous les composants d'interface graphique contenant la nouvelle classe.
Pour résoudre ce problème, nous avons conservé dans la classe View une mappe de références à tous les composants d'interface graphique imbriqués afin que, chaque fois que les données du modèle étaient mises à jour, la vue puisse envoyer les données de modèle mises à jour directement aux composants d'interface graphique qui en avaient besoin, fin du récit. . Cela a bien fonctionné car il n'y avait qu'une seule instance de chaque composant d'interface graphique. Je pouvais voir que cela ne fonctionnait pas très bien s'il y avait plusieurs instances de certains composants de l'interface graphique, ce qui rendait difficile l'identification de la copie à mettre à jour.
la source
Ce que vous décrivez est un modèle de conception appelé chaîne de responsabilité . Apple utilise ce modèle pour son système de gestion des événements, à sa juste valeur.
la source