Pour chaque projet de programmation, les gestionnaires ayant une expérience de programmation passée essaient de briller lorsqu'ils recommandent des modèles de conception pour votre projet. J'aime les modèles de conception lorsqu'ils ont du sens ou si vous avez besoin d'une solution évolutive. J'ai utilisé des modèles de proxys, d'observateurs et de commandement de manière positive par exemple, et je le fais tous les jours. Mais j'hésite vraiment à utiliser, par exemple, un modèle Factory s'il n'y a qu'une seule façon de créer un objet, car une usine pourrait rendre tout cela plus facile à l'avenir, mais complique le code et est un pur surcharge.
Donc, ma question concerne ma future carrière et ma réponse aux types de managers qui lancent des noms de motifs aléatoires:
Quels modèles de conception avez-vous utilisés, qui vous ont repoussé dans l'ensemble? Quels sont les pires modèles de conception, ceux que vous devriez considérer, sauf dans la seule situation où ils ont du sens (lire: quels modèles de conception sont définis de manière très étroite)? (C'est comme si je cherchais les critiques négatives d'un bon produit global d'Amazon pour voir ce qui dérangeait le plus les gens dans l'utilisation des modèles de conception.) Et je ne parle pas ici des anti-modèles, mais des modèles qui sont généralement considérés comme "bons" modèles.
Edit: Comme certains l'ont répondu, le problème est le plus souvent que les motifs ne sont pas "mauvais" mais "mal utilisés". Si vous connaissez des modèles, qui sont souvent mal utilisés ou même difficiles à utiliser, ils conviendraient également comme réponse.
Je ne crois pas aux mauvais schémas, je crois que les schémas peuvent être mal appliqués!
Pour cette réponse, je n'ai considéré que les modèles GOF. Je ne connais pas assez bien tous les modèles possibles pour les prendre en considération également.
Je vais sortir sur un membre ici et suggérer une utilisation excessive de l'héritage. Certainement plus applicable dans les langages sans prise en charge solide du polymorphisme à la compilation, comme Java. L'héritage au moment de l'exécution est un outil, pas une sorte de merveille à fonctionnalité unique.
D'autres personnes ont déjà exprimé une similitude avec ma haine personnelle des singletons, donc je ne vais pas m'étendre là-dessus.
Mis à part Singleton et Visitor déjà mentionnés par les autres répondeurs, je ne connais pas de modèles de conception "notoires". À mon humble avis, les plus gros problèmes ne sont pas dus au fait qu'un modèle de conception spécifique est "incorrect", mais plutôt aux développeurs qui appliquent trop volontiers les modèles.
Presque tout le monde passe par la phase de la "fièvre des schémas" en se familiarisant avec les schémas. Pensant que les motifs sont la meilleure chose depuis le pain tranché, on essaie d'abord de les appliquer chaque fois qu'il voit une possibilité. Il en résulte que le code est enterré sous les modèles, où les modèles eux-mêmes ne sont plus utiles, rendent le code plus difficile à comprendre et à maintenir à long terme.
Finalement, la plupart d'entre nous franchissent cette phase et commencent à apprendre à utiliser les modèles pour résoudre de vrais problèmes, pas pour leur propre bien. Les modèles ont leur prix, qui est une complexité supplémentaire, et l'application d'un modèle spécifique n'est justifiée que lorsqu'elle rembourse la complexité supplémentaire en aidant à simplifier une autre partie du système, ce qui rend le code/la configuration globalement plus facile à comprendre et à maintenir. Si ce n'est pas le cas, il est souvent préférable de rester à l'écart des modèles, en conservant la solution la plus simple qui pourrait éventuellement fonctionner.
Singleton. C'est l'un des modèles GOF qui est maintenant plus souvent appelé anti-modèle. L'une des raisons à cela est que Singleton rend le code plus difficile à tester.
Si vous connaissez des modèles, qui sont souvent mal utilisés ou même difficiles à utiliser, ils conviendraient également comme réponse.
Suivre le modèle MVVM pour [~ # ~] wpf [~ # ~] trop strictement, comme indiqué par exemple - par cette question . Certaines personnes essaient de suivre la directive selon laquelle aucun code ne doit être inséré de manière trop stricte dans le code et proposent toutes sortes de hacks exotiques.
Et bien sûr, MVVM est difficile comme l'enfer, et n'en vaut pas la peine pour les petits projets à court terme.
Le Dr WPF a fait un post ironique à ce sujet dans son article M-V-poo .
Factory. J'ai vu du code l'implémenter qui ne crée qu'un seul type. C'est le code IMO complètement inutile. Cela n'aide pas que de nombreux exemples en ligne soient complètement artificiels. Usine de pizza?
Peut-être que l'usine est plus facile à tester en raison de l'injection de dépendance. Mais ajouter ce code quand vous n'en aurez pas besoin est inutile pour moi, et l'argument de test disparaît lorsque vous pouvez utiliser des frameworks factices comme JMockit. Le plus simple vous pouvez créer un programme, mieux c'est. Les usines n'ont vraiment de sens qu'avec un plus grand nombre de types (par plus grand, je veux dire au moins plus de 2).
Certains des modèles du livre GOF sont spécifiques au C++, dans le sens où ils sont moins applicables dans les langages avec réflexion, par ex. le modèle Prototype est moins significatif en Java.
Je considère le modèle Interpreter comme un modèle "étroit". Vous devez avoir un problème général qui vaut la peine de développer un solutionneur de problèmes général. Cela ne fonctionne que pour les problèmes spéciaux pour lesquels vous pouvez inventer une langue, définir une grammaire et écrire un interprète. Les instances de problème doivent être représentables sous forme de phrase dans la grammaire. Je ne pense pas que vous rencontriez de telles situations souvent.
Celui que je regrette le plus souvent (mais pas avec véhémence): Quand j'aurais dû créer une fonction mais j'ai implémenté une solution OOP.
Singleton
Je suis d'accord avec les autres sur Singleton. Non pas que vous ne devriez jamais les utiliser, mais simplement que cela devrait être limité à très peu de cas. Ils sont utilisés comme des globaux paresseux la plupart du temps.
La sécurité des threads est un problème avec les singletons. La gestion des exceptions en est une autre - si le singleton ne parvient pas à créer correctement - vous ne savez pas toujours si vous pouvez intercepter l'erreur en toute sécurité, en particulier s'il s'agit de l'un de ces objets créés "avant principal". Et puis il y a la question du nettoyage après.
J'ai tendance à préférer utiliser un seul singleton et à ce que tous les autres singletons "en herbe" "souscrivent" à votre seul. Mon utilisation singleton la plus courante est la gestion des "événements de crier": vous venez de "diffuser au monde" qu'un événement a eu lieu et quiconque écoute qui va gérer l'événement le fait. De cette façon, vous dissociez les événements qui se produisent réellement avec ce qui les écoute. (Enregistrement, signaux, etc.)
Visiteur
La chose laide que je trouve à ce sujet, à part le fait que les développeurs ne peuvent pas penser à des noms significatifs et simplement appeler des méthodes visit (), c'est qu'il ajoute de l'extensibilité dans un sens tout en le supprimant dans un autre, c'est-à-dire qu'il ajoute des fonctionnalités supplémentaires mais restreint le nombre d'objets que vos visiteurs doivent connaître sur tous les types d'objets qu'il peut visiter.
Il est possible, bien que désordonné, d'autoriser l'extension dans les deux sens, mais cela n'utilise pas totalement le modèle de visiteur dans sa forme régulière. L'application la plus courante pour cela est l'impression d'objets: vous avez différentes façons d'imprimer des objets et différents objets qui doivent être imprimés. Vous devriez pouvoir l'étendre dans les deux sens. (L'impression signifie tout type de transformation d'objets en un flux: stockage dans un fichier/écriture sur une console/interface graphique, etc.).
(Remarque: vous ne devez pas confondre cela avec l'architecture de visualisation de document, qui est un modèle légèrement différent).
Je pense que le problème avec certains des modèles les plus complexes est qu'ils sont tellement variés qu'ils perdent une grande partie de leur valeur en tant que dispositif de communication.
Le pire délinquant auquel je puisse penser dans cette catégorie est le modèle MVC. Même si nous ignorons MVP, il y a tellement de variations dans les rôles de chacun de ces éléments que vous devez passer une heure dans chaque nouveau cadre pour déterminer où se situent les limites.
Il n'y a pas de mauvais schémas seulement des mauvaises personnes.
Je préfère de loin hériter du code facilement lisible qui fait quelque chose de clair mais qui est un peu verbeux ou non (file d'attente de la méchante musique des méchants) réutilisable (halètement!) Plutôt que de la purée de InheritAbstractTemplateFaucetSink<Kitchen>
.
Le code réutilisable est génial! Il est probable que vous n'écrivez pas du code qui sera réutilisé ou que la réécriture d'une logique similaire pour une autre application vous prenne moins de temps qu'une tentative insensée de réutiliser le code d'une autre application.
Pour une lecture plus approfondie, ouvrez une partie du code C dans les implémentations sensées des en-têtes posix ou des clibs et jouez le motif. Ce code a été écrit par certains des programmeurs les plus intelligents et les plus dévoués au monde. Savez-vous combien de Patterns Abstract Factory vous allez voir? ... AUCUN!. Encore plus de chances sont si vous comprenez les autres parties de ce qui se passe, vous trouverez la logique très facile à comprendre et à tracer.
Mon point est que la plupart des "modèles" n'ont pas été créés pour améliorer le code, ils ont été créés pour vendre des livres et des logiciels de modélisation. Si vous êtes bon en programmation, vous éviterez probablement la plupart d'entre eux et rédigerez un code clair, concis et intelligemment conçu qui résout votre problème. Lorsque vous avez un autre problème, vous écrirez un code clair, concis et intelligemment conçu pour résoudre ce problème. Si votre objectif est d'écrire moins de code que je ne le pense, vous n'êtes pas fait pour être programmeur. J'adore écrire du code et je veux l'écrire autant que possible. Quand je réécris quelque chose que j'ai déjà écrit, je le fais des dizaines de fois plus vite et je me débarrasse de toutes les choses dont je n'étais pas satisfait la première fois. En prime, je peux le faire sans aucune des limitations du premier problème car c'est un nouveau problème (j'ai probablement 15 scripts dans 5 langues différentes qui font flotter Tomcat).
Sur ce, je vous laisse probablement la meilleure (pertinente) citation en informatique.
"Il y a deux façons de construire une conception logicielle: l'une consiste à la rendre si simple qu'il n'y a évidemment pas de lacunes, et l'autre consiste à la rendre si compliquée qu'il n'y a pas de lacunes évidentes. La première méthode est beaucoup plus difficile. "
Je suis tout à fait d'accord pour dire qu'il y a un temps pour la plupart des modèles et que vous pouvez abuser de nombreux modèles. Je sais que celui dont j'ai le plus abusé par le passé est le modèle de modèle abstrait. Pris dans sa pleine mesure, il est connu sous le nom de formulaires Web ASP.NET.