Problème
J'ai récemment lu beaucoup de choses sur les singletons étant mauvais et comment l'injection de dépendances (que je comprends comme "utilisant des interfaces") est meilleure. Lorsque j'ai implémenté une partie de cela avec des rappels / interfaces / DI et en adhérant au principe de ségrégation d'interface, je me suis retrouvé avec un sacré bordel.
Les dépendances d'un parent d'interface utilisateur où, fondamentalement, celles de tous ses enfants se sont combinées, de sorte que plus la hiérarchie d'un élément d'interface utilisateur était élevée, plus son constructeur était gonflé.
Tout en haut de la hiérarchie de l'interface utilisateur se trouvait une classe Application, contenant les informations sur la sélection actuelle et une référence à un modèle 3D qui doit refléter les changements. La classe d'application implémentait 8 interfaces, et ce n'était qu'un rond-point sur un cinquième des produits (/ interfaces) à venir!
Je travaille actuellement avec un singleton contenant la sélection actuelle et les éléments d'interface utilisateur ayant une fonction pour se mettre à jour. Cette fonction fait couler l'arborescence de l'interface utilisateur et les éléments de l'interface utilisateur, puis accède au singleton de sélection actuel selon les besoins. Le code me semble plus propre de cette façon.
Question
Un singleton peut-il convenir à ce projet?
Sinon, y a-t-il un défaut fondamental dans ma façon de penser et / ou de mettre en œuvre l'ID qui le rend si lourd?
Informations supplémentaires sur le projet
Type: Panier pour les appartements, avec cloches et sifflets
Taille: 2 mois-homme pour le code et l'interface utilisateur
Maintenance: Aucune mise à jour en cours d'exécution, mais peut-être "version 2.0" plus tard
Environnement: Utilisation de C # dans Unity, qui utilise une entité Système de composants
Dans presque tous les cas, l'interaction utilisateur déclenche plusieurs actions. Par exemple, lorsque l'utilisateur sélectionne un élément
- la partie de l'interface utilisateur montrant cet élément et sa description doit être mise à jour. Pour cela, il doit également obtenir des informations à partir d'un modèle 3D afin de calculer le prix.
- plus haut dans l'interface utilisateur, le prix total global doit être mis à jour
- une fonction correspondante dans une classe sur un modèle 3D doit être appelée pour y afficher les changements
la source
Réponses:
Je pense que la question est un symptôme, pas une solution.
Une solution à la recherche d'un problème; cela et l'incompréhension est probablement en train de corrompre votre conception. Avez-vous lu cette question SO sur DI vs Singleton, différents concepts ou non? J'ai lu cela comme enveloppant simplement un singleton pour que le client n'ait pas à faire face à un singleton. C'est. Juste. Une. Bonne. Encapsulation. Je pense que c'est parfait.
Construisez d'abord les petits morceaux, puis passez-les dans le constructeur de la chose à laquelle ils appartiennent et passez cette plus grande chose dans le constructeur de la prochaine chose la plus grande ...
Si vous avez des problèmes de construction complexes, utilisez le modèle d'usine ou de constructeur. En bout de ligne, il y a cette construction complexe tirée dans sa propre classe pour garder les autres classes propres, propres, compréhensibles, etc.
Cela ressemble à l'absence de capacité d'extension. La conception de base est manquante et tout est entassé par le haut. Il devrait y avoir plus de construction, de composition et d'héritage ascendant.
Je me demande si votre design est "top heavy". On dirait que nous essayons de faire d'une classe tout ou n'importe quoi. Et le fait qu'il s'agisse d'une classe d'interface utilisateur, et non d'une classe de domaine métier, me fait vraiment me poser des questions sur la séparation des préoccupations.
Revoyez votre conception depuis le début et assurez-vous qu'il existe une abstraction de produit solide et de base sur laquelle vous pouvez vous baser pour créer des productions de catégories plus complexes ou différentes. Ensuite, vous feriez mieux d'avoir des collections personnalisées de ces choses, donc vous avez un endroit où mettre la fonctionnalité "au niveau de la collection" - comme ce "3ème modèle" que vous mentionnez.
Une grande partie de cela peut tenir dans des classes de collection personnalisées. Il peut également s'agir d'une structure de classe indépendante en soi en raison de la profondeur et de la complexité. Ces deux choses ne s'excluent pas mutuellement.
Lisez à propos du modèle de visiteur. C'est l'idée d'avoir des mandrins entiers de fonctionnalités câblés de manière abstraite à différents types.
Design et DI
90% de toute l'injection de dépendance que vous ferez jamais est le passage des paramètres du constructeur. C'est ce que dit le quy qui a écrit le livre . Concevez bien vos classes et évitez de polluer ce processus de réflexion avec une notion vague sur la nécessité d'utiliser un bidon DI. Si vous en avez besoin, votre design vous le proposera pour ainsi dire.
Concentrez-vous sur la modélisation du domaine commercial des appartements.
Évitez l'approche Jessica Simpson de la conception : "Je ne sais absolument pas ce que cela signifie, mais je le veux."
Les éléments suivants sont tout simplement faux:
la source
"Hiérarchie des classes" est un peu un drapeau rouge. Hypothétique: une page Web avec 5 widgets. La page n'est l'ancêtre d'aucun des widgets. Il peut contenir une référence à ces widgets. Mais ce n'est pas un ancêtre. Au lieu de la hiérarchie des classes, pensez à utiliser la composition. Chacun des 5 widgets peut être construit seul, sans référence aux autres widgets ou à la page d'accueil. La page d'accueil est ensuite construite avec suffisamment d'informations pour créer une page de base et disposer les objets widget (Collection) qui lui sont transmis. La page est responsable de la mise en page, etc., mais pas de la construction et de la logique des widgets.
Une fois que vous utilisez la composition, DI est votre meilleur ami. DI vous permet d'échanger chaque widget pour n'importe quelle version ou type de widget que vous définissez dans DI. La construction des widgets est capturée dans l'ID et est distincte de la page supérieure. Peut-être même que la composition de la collection peut être définie dans votre DI. La première page effectue la mise en page en fonction des widgets qui lui sont transmis, comme il se doit. Aucune modification du constructeur de la page d'accueil n'est nécessaire. La première page n'a besoin que de la logique pour effectuer la mise en page des widgets et transmettre des informations vers / depuis le widget en fonction des interfaces définies.
Au lieu de faire passer des auditeurs de haut en bas de la chaîne de composition, injectez une collection d'auditeurs aux widgets qui en ont besoin. Injectez la collection dans un éditeur afin qu'il puisse publier dans la collection. Injectez la collection dans les écouteurs afin qu'ils puissent s'ajouter à la collection. La collection recoupe tous les objets de la chaîne de composition.
la source