Quels modèles de conception sont les pires ou les plus étroitement définis? [fermé]

28

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 proxys, des observateurs et des modèles 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 une pure surcharge.

Donc, ma question concerne ma future carrière et ma réponse aux types de gestionnaires qui lancent des noms de modèle 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 un 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 modèles 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.

Akku
la source
La plupart des modèles facilitent les changements futurs sur certains axes de changement, mais ils peuvent rendre les changements plus difficiles sur d'autres axes de changement. Le gang de quatre livres est particulièrement bon pour dire quand un modèle est applicable. Beaucoup de livres ultérieurs sur les modèles manquent ce point. Prenons l'exemple du modèle de visiteur. Il facilite l'ajout de nouveaux algorithmes de traversée d'arbre, mais il est plus difficile d'ajouter de nouveaux types de nœuds à l'arbre. Il permet également aux algorithmes de traversée d'être dans une couche plus élevée que l'arbre. Vous devez considérer quel axe de changement est le moins stable et concevoir pour faciliter les changements le long de cet axe.
Theodore Norvell
Tous ceux du livre «Gang of Four».
Miles Rout du

Réponses:

40

Je ne crois pas aux mauvais schémas, je crois que les schémas peuvent être mal appliqués!

  • À mon humble avis, le singleton est le modèle le plus maltraité et le plus mal appliqué. Les gens semblent attraper une maladie singleton et commencent à voir des possibilités de singletons partout sans envisager d'alternatives.
  • Le modèle de visiteur à mon humble avis a l'utilisation la plus étroite et presque jamais la complexité supplémentaire ne sera justifiée. Un joli pdf peut être obtenu ici . Vraiment seulement lorsque vous avez une structure de données que vous savez que vous allez parcourir tout en effectuant différentes opérations sur la structure de données sans connaître toutes les façons à l'avance, donnez au modèle de visiteur une chance de se battre. C'est joli quand même :)

Pour cette réponse, je n'ai considéré que les modèles GOF. Je ne connais pas assez bien tous les schémas possibles pour les prendre en considération également.

KeesDijk
la source
Je vois très peu d'utilisations pour les visiteurs. Singletons ... ne me lancez pas. Si la situation n'est pas parfaite pour l'un, ne l'utilisez pas.
Michael K
1
Il peut y avoir très peu d'utilisations pour Visitor, mais quand il est, il résout certainement les problèmes. Ma compréhension est que Vistor est essentiel à LINQ.
quentin-stardu
12
Le modèle de visiteur est essentiel pour réduire (ou éliminer) la complexité cyclomatique dans un programme logiciel. Chaque fois que vous avez une arborescence if / else ou une instruction switch, les chances sont élevées qu'un visiteur puisse les remplacer, offrant une exécution garantie et une vérification au moment de la compilation. Le Visitor est l'un des modèles les plus puissants que je connaisse, et nous l'utilisons régulièrement avec beaucoup d'effet. Cela fait aussi du test un rêve.
Les Hazlewood
@LesHazlewood n'est-il donc pas seulement une solution de contournement pour les langages de programmation inadéquats? Les langages de type ML (Haskell, SML, OCaml, etc.) ont des types de données algébriques ("union on steroids") et des correspondances de motifs ("switch on steroids") qui produisent un code plus simple que Visitor, mais entièrement vérifié par le compilateur. Par rapport au visiteur, vous n'avez pas beaucoup de méthodes dont vous devez gérer manuellement l'état de partage via les propriétés de l'objet. Dans les langages de type ML, et toutes les distinctions de casse doivent être complètes, sinon il ne sera pas compilé.
vog
14

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 des 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 paie pour 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.

Péter Török
la source
Absolument. Les modèles ne sont ni bons ni mauvais, ils sont bien appliqués ou mal appliqués.
Je préfère enseigner aux gens la façon dont j'ai appris: OO d'abord, comprendre comment les objets sont liés, puis apprendre les noms des motifs. Il est trop facile de penser en termes de modèles que ce qui doit être fait. Ils sont un outil de communication.
Michael K
Les modèles sont un moyen de communiquer, pas une liste normative. Si vous commencez avec un modèle à l'esprit, vous pouvez l'appliquer de manière erronée. Si vous en trouvez un ou les indices d'un dans votre conception, les catalogues de modèles peuvent vous aider à comprendre ce dont vous pourriez avoir besoin.
Rob Crawford
14

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.

DeadMG
la source
10

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.

SiberianGuy
la source
4
Il y a de nombreux défauts fondamentaux dans le modèle singleton, la plupart sont bien illustrés dans cet article par Steve Yegge - Singleton Considéré comme stupide
ocodo
Slomojo: Bel article. Je vais l'appeler "modèle simpleton" à partir de maintenant:-)
Personne
2
Oui, parce que certains imbéciles abusent d'un modèle et manquent totalement le bateau sur ce qu'est OO (à en juger par toutes les classes de manager qu'il a imaginées), bien sûr, c'est la faute du modèle et non les développeurs.
Dunk
Pourquoi tout le monde associe l'implémentation commune (et gênante) de Singleton au modèle Singleton? L'un est presque toujours mauvais, l'autre non.
quentin-stardu
1
@qes> Singleton pose des problèmes d'implémentation importants (en particulier avec le filetage). C'est déjà un mauvais point. Mais, vous découvrirez également que le singleton est un modèle sur la façon dont la classe est poursuivie, et non sur son fonctionnement. La façon dont la classe est utilisée doit être gérée par le code utilisant la classe, donc Singleton est une rupture de séparation des préoccupations.
deadalnix
7

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 MV-poo .

Steven Jeuris
la source
@Akku: Vous devez bien sûr savoir comment l'utiliser, afin de pouvoir décider s'il convient à votre projet. Alors oui, c'est essentiel pour le développement WPF, et très utile.
Steven Jeuris
L'un des problèmes est que les gens comprennent mal le modèle MVVM. Ce n'est pas "difficile comme l'enfer". Les gens le font de cette façon en pensant que tous les autres modèles tels que le modèle de commande et le modèle de médiateur en font partie. À lui seul, MVVM est l'un des modèles les plus simples, à mon avis. Je suis d'accord, que suivre quoi que ce soit au t est tout simplement stupide.
BK
5

Certains modèles du livre GOF sont spécifiques au C ++, en ce sens qu'ils sont moins applicables dans les langages avec réflexion, par exemple 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.

Karl
la source
1
la plupart de GOF ne s'applique qu'aux POO basés sur une classe statique. s'éloigner un peu de ce genre de langues et le livre devient juste une anecdote de divertissement.
Javier
5

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.

C SD
la source
1
Pourquoi? Qu'est-ce qui vous a fait le regretter? Veuillez développer votre réponse et ajouter votre expérience.
Walter
En effet, je pense qu'une classe avec des variables locales et des méthodes claires est BEAUCOUP plus facile à réutiliser qu'une seule fonction de 200 lignes qui ne peut être réappliquée que par copier-coller et n'a donc pas qu'un seul endroit pour paraître moche et peu complet.
Akku
2
KISS implique que vous en fassiez d'abord une fonction, puis refactorisez une classe si nécessaire.
Eva
5

Usine. 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 lorsque 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).

Michael K
la source
Oui, usine de pizza, merci pour le modèle de conception Head First ~
Niing
2

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 "diffusez au monde" simplement qu'un événement a eu lieu et que toute personne qui l'écoutera le fera. 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).

Vache à lait
la source
2
Votre solution utilise l'ancien argument de découplage des choses. En particulier, vous postez un événement et un autre type gère l'événement et le consigne. C'est une bonne chose, car tout le monde est découplé! FAUX! J'avais l'habitude de faire ça, quelle douleur royale c'était devenu. J'ai réalisé que si je veux que quelque chose soit enregistré, je veux dire explicitement enregistrer cette chose exacte, ici, en ce moment, dans le code au moment où cela s'est produit. Ne pas avoir un autre objet pour déterminer ce qui devrait être enregistré, avec d'autres événements possibles interjectés par d'autres gestionnaires, s'il est même enregistré. Ce n'est rien d'autre qu'une conception compliquée.
Dunk
2

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.

Uri
la source
Je pense également que MVC devrait être utilisé partout, mais pas implémenté de la même manière partout. Et beaucoup de gens ne le comprennent pas. Quand j'ai voulu l'utiliser pour la première fois, j'ai créé trois classes nommées Model, View (un formulaire Windows) et Controller. C'était un gâchis, car les formulaires n'étaient pas faits pour MVC.
Akku
1

Il n'y a pas de mauvais schémas seulement de mauvaises personnes.

Je préfère de beaucoup 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 méli-mélo InheritAbstractTemplateFaucetSink<Kitchen>.

Le code réutilisable est génial! Il est probable que vous n'écrivez pas de 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 rencontrez 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.

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 . "

  • Tony Hoare (inventeur du quicksort, père de la conception d'OS moderne, créateur de la logique Hoare et récipiendaire du prix Turing)
nsfyn55
la source
0

Je suis définitivement d'accord qu'il y a un temps pour la plupart des modèles et que vous pouvez en abuser. 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.

Wyatt Barnett
la source