Beaucoup de gens semblent d'accord pour dire que le modèle Singleton présente un certain nombre d'inconvénients et certains suggèrent même d'éviter complètement le modèle. Il y a une excellente discussion ici . Veuillez adresser vos commentaires sur le modèle Singleton à cette question.
Ma question : y a-t-il d'autres modèles de conception à éviter ou à utiliser avec beaucoup de soin?
design-patterns
anti-patterns
Brian Rasmussen
la source
la source
Réponses:
Les modèles sont complexes
Tous les modèles de conception doivent être utilisés avec précaution. À mon avis, vous devriez refactoriser vers des modèles lorsqu'il y a une raison valable de le faire au lieu d'implémenter un modèle tout de suite. Le problème général de l'utilisation des modèles est qu'ils ajoutent de la complexité. La surutilisation des modèles rend une application ou un système donné difficile à développer et à maintenir.
La plupart du temps, il existe une solution simple et vous n'aurez pas besoin d'appliquer de modèle spécifique. Une bonne règle de base est d'utiliser un modèle chaque fois que des morceaux de code ont tendance à être remplacés ou doivent être changés souvent et soyez prêt à accepter la mise en garde du code complexe lors de l'utilisation d'un modèle.
N'oubliez pas que votre objectif doit être la simplicité et utiliser un modèle si vous voyez un besoin pratique de prendre en charge le changement dans votre code.
Principes sur les modèles
Il peut sembler inutile d’utiliser des modèles s’ils peuvent de toute évidence conduire à des solutions trop élaborées et complexes. Cependant, il est bien plus intéressant pour un programmeur de se renseigner sur les techniques et principes de conception qui jettent les bases de la plupart des modèles. En fait, l'un de mes livres préférés sur les «modèles de conception» le souligne en rappelant les principes applicables au modèle en question. Ils sont suffisamment simples pour être utiles que les modèles en termes de pertinence. Certains des principes sont suffisamment généraux pour englober plus que la programmation orientée objet (POO), comme le principe de substitution de Liskov , tant que vous pouvez créer des modules de votre code.
Il existe une multitude de principes de conception, mais ceux décrits dans le premier chapitre du livre du GoF sont très utiles pour commencer.
Laissez-les vous envahir pendant un moment. Il convient de noter que lorsque GoF a été écrit, une interface signifie tout ce qui est une abstraction (ce qui signifie également des super classes), à ne pas confondre avec l'interface en tant que type en Java ou C #. Le deuxième principe vient de la surutilisation observée de l'héritage qui est malheureusement encore courante aujourd'hui .
De là, vous pouvez lire sur les principes SOLID qui a été fait connaître par Robert Cecil Martin (alias. Oncle Bob) . Scott Hanselman a interviewé Oncle Bob dans un podcast sur ces principes :
Ces principes sont un bon début pour lire et discuter avec vos pairs. Vous pouvez constater que les principes s'entremêlent les uns avec les autres et avec d'autres processus tels que la séparation des préoccupations et l' injection de dépendances . Après avoir fait du TDD pendant un certain temps, vous pouvez également constater que ces principes viennent naturellement dans la pratique car vous devez les suivre dans une certaine mesure afin de créer des tests unitaires isolés et répétables .
la source
Celui qui préoccupait le plus les auteurs de Design Patterns était le motif "Visiteur".
C'est un «mal nécessaire» - mais il est souvent surutilisé et le besoin d'en révéler souvent une faille plus fondamentale dans votre conception.
Un autre nom pour le modèle "Visiteur" est "Multi-dispatch", car le modèle Visiteur est ce que vous obtenez lorsque vous souhaitez utiliser un langage OO de répartition de type unique pour sélectionner le code à utiliser en fonction du type de deux (ou plus) différents objets.
L'exemple classique est que vous avez l'intersection entre deux formes, mais il y a un cas encore plus simple qui est souvent négligé: comparer l'égalité de deux objets hétérogènes.
Quoi qu'il en soit, vous vous retrouvez souvent avec quelque chose comme ceci:
Le problème avec ceci est que vous avez couplé ensemble toutes vos implémentations de "IShape". Vous avez laissé entendre que chaque fois que vous souhaitez ajouter une nouvelle forme à la hiérarchie, vous devrez également modifier toutes les autres implémentations "Shape".
Parfois, c'est la conception minimale correcte - mais réfléchissez-y. Votre conception exige- t-elle vraiment que vous deviez expédier sur deux types? Êtes-vous prêt à écrire chacune de l'explosion combinatoire des multi-méthodes?
Souvent, en introduisant un autre concept, vous pouvez réduire le nombre de combinaisons que vous allez devoir écrire:
Bien sûr, cela dépend - parfois vous avez vraiment besoin d'écrire du code pour gérer tous ces différents cas - mais cela vaut la peine de prendre une pause et de réfléchir avant de sauter le pas et d'utiliser Visitor. Cela pourrait vous éviter beaucoup de douleur plus tard.
la source
Singletons - une classe utilisant singleton X a une dépendance qui est difficile à voir et à isoler pour les tests.
Ils sont utilisés très souvent car ils sont pratiques et faciles à comprendre, mais ils peuvent vraiment compliquer les tests.
Voir Les singletons sont des menteurs pathologiques .
la source
Je pense que le modèle de méthode de modèle est généralement un modèle très dangereux.
la source
Je ne pense pas que vous devriez éviter les Design Patterns (DP), et je ne pense pas que vous devriez vous forcer à utiliser des DP lors de la planification de votre architecture. Nous ne devrions utiliser les PD que lorsqu'ils émergent naturellement de notre planification.
Si nous définissons dès le départ que nous voulons utiliser un DP donné, nombre de nos futures décisions de conception seront influencées par ce choix, sans aucune garantie que le DP que nous avons choisi est adapté à nos besoins.
Une chose que nous ne devrions pas non plus faire est de traiter un DP comme une entité immuable, nous devons adapter le modèle à nos besoins.
Donc, en résumé, je ne pense pas que nous devrions éviter les PDD, nous devrions les embrasser quand ils prennent déjà forme dans notre architecture.
la source
Je pense qu'Active Record est un modèle surutilisé qui encourage à mélanger la logique métier avec le code de persistance. Il ne fait pas un très bon travail de masquer l'implémentation de stockage de la couche de modèle et lie les modèles à une base de données. Il existe de nombreuses alternatives (décrites dans PoEAA) telles que Table Data Gateway, Row Data Gateway et Data Mapper qui fournissent souvent une meilleure solution et contribuent certainement à fournir une meilleure abstraction au stockage. De plus, votre modèle ne devrait pas avoir besoin d'être stocké dans une base de données; qu'en est-il de les stocker au format XML ou d'y accéder à l'aide de services Web? Serait-il facile de changer le mécanisme de stockage de vos modèles?
Cela dit, Active Record n'est pas toujours mauvais et est parfait pour les applications plus simples où les autres options seraient exagérées.
la source
C'est simple ... évitez les modèles de conception qui ne sont pas clairs pour vous ou ceux avec lesquels vous ne vous sentez pas à l'aise .
Pour en nommer quelques-uns ...
il y a des modèles peu pratiques , comme par exemple:
Interpreter
Flyweight
il y a aussi des plus difficiles à saisir , comme par exemple:
Abstract Factory
- Le motif d'usine abstrait complet avec des familles d'objets créés n'est pas un jeu d'enfant qu'il n'y paraîtBridge
- Peut devenir trop abstrait, si l'abstraction et l'implémentation sont divisées en sous-arbres, mais c'est un modèle très utilisable dans certains casVisitor
- La compréhension du double mécanisme de répartition est vraiment un MUSTet il y a des modèles qui semblent terriblement simples , mais qui ne sont pas un choix aussi clair en raison de diverses raisons liées à leur principe ou à leur mise en œuvre:
Singleton
- motif pas vraiment totalement mauvais, juste trop utilisé (souvent là où il ne convient pas)Observer
- excellent modèle ... rend juste le code beaucoup plus difficile à lire et à déboguerPrototype
- échange des vérifications du compilateur pour le dynamisme (qui peut être bon ou mauvais ... dépend)Chain of responsibility
- trop souvent simplement poussé de force / artificiellement dans la conceptionPour ceux "peu pratiques", il faut vraiment réfléchir avant de les utiliser, car il y a généralement une solution plus élégante quelque part.
Pour les "plus difficiles à saisir" ... ils sont vraiment d'une grande aide, lorsqu'ils sont utilisés à des endroits appropriés et lorsqu'ils sont bien mis en œuvre ... mais ils sont cauchemardesques, lorsqu'ils sont mal utilisés.
Maintenant, quelle est la suite ...
la source
J'espère que je ne serai pas trop battu pour ça. Christer Ericsson a écrit deux articles ( un , deux ) sur le thème des modèles de conception dans son blog de détection de collision en temps réel . Son ton est plutôt dur, et peut-être un peu provocateur, mais l'homme connaît son affaire, donc je ne le considérerais pas comme des délires d'un fou.
la source
Certains disent que le localisateur de services est un anti-pattern.
la source
Je pense que le modèle d'observateur a beaucoup à répondre, cela fonctionne dans des cas très généraux, mais à mesure que les systèmes deviennent plus complexes, cela devient un cauchemar, nécessitant des notifications OnBefore (), OnAfter () et souvent l'affichage de tâches asynchrones pour éviter de entrée. Une bien meilleure solution consiste à développer un système d'analyse automatique des dépendances qui instrumente tous les accès aux objets (avec des barrières de lecture) pendant les calculs et crée automatiquement une arête dans un graphe de dépendances.
la source
Un complément à l'article de Spoike, Refactoring to Patterns est une bonne lecture.
la source
Iterator est un autre modèle GoF à éviter, ou du moins à ne l'utiliser que lorsqu'aucune alternative n'est disponible.
Les alternatives sont:
pour chaque boucle. Cette construction est présente dans la plupart des langages traditionnels et peut être utilisée pour éviter les itérateurs dans la majorité des cas.
sélecteurs à la LINQ ou jQuery. Ils doivent être utilisés lorsque for-each n'est pas approprié car tous les objets du conteneur ne doivent pas être traités. Contrairement aux itérateurs, les sélecteurs permettent de manifester en un seul endroit le type d'objets à traiter.
la source
yield
itérateur. Eric White a de bonnes discussions à ce sujet en C # 3.0: blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . Consultez également la discussion de Jeremy Likness sur les coroutines avec les itérateurs: wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .