Quand les modèles de conception sont-ils le problème au lieu de la solution?

Je n’ai jamais travaillé sur des logiciels où je devais utiliser des modèles de conception. Selon l’ essai de Paul Graham intitulé Revenge of the Nerds , les modèles de conception sont le signe d’un manque d’abstraction.

Pour le citer directement: «Par exemple, dans le monde des OO, vous entendez beaucoup parler de« modèles ». Je me demande si ces modèles ne sont pas parfois des preuves du cas (c), le compilateur humain, au travail. Quand je vois des modèles dans mes programmes, je considère que c’est un problème. La forme d’un programme ne doit refléter que le problème à résoudre. Toute autre régularité dans le code est pour moi au moins un signe que j’utilise des abstractions qui ne sont pas assez puissantes – souvent que je génère à la main les extensions d’une macro que j’ai besoin d’écrire.

Je me demandais si tout le monde pensait que les modèles de conception sont surutilisés et sont des symptômes de ne pas avoir assez d’abstraction dans votre code.

Je ne pense pas que les modèles en eux-mêmes constituent le problème, mais plutôt le fait que les développeurs peuvent apprendre des patterns puis les remplacer, ou les appliquer de manière totalement inappropriée.

L’utilisation de modèles est quelque chose que les programmeurs expérimentés apprennent simplement naturellement. Vous avez résolu plusieurs problèmes X, vous savez quelle approche fonctionne, vous utilisez cette approche parce que vos compétences et votre expérience vous disent que c’est approprié. C’est un modèle, et ça va.

Mais il est également possible pour un programmeur moins qualifié de trouver un moyen de faire les choses et d’essayer de résoudre tous les problèmes qu’il rencontre, car il ne connaît pas d’autre manière. C’est un modèle aussi, et c’est mal.

Venez, s’il vous plaît, lisez la citation en entier, lisez-la attentivement. Ou mieux encore, lisez l’essai.

Paul Graham critique, entre autres choses, les langages de type C pour ne pas fournir de moyens d’abstraction adéquats. Dans le cadre de l’essai, sa critique des modèles est une reflection après coup, ou plutôt un cas particulier pour son argument principal. Son raisonnement va comme ceci:

Il est logique d’utiliser des stratégies communes pour résoudre des problèmes récurrents. Dans des langages vraiment abstraits, il est possible de formaliser ces stratégies et de les placer dans une bibliothèque. Chaque fois que vous devez les utiliser, vous les incluez simplement, les instanciez, les développez, etc. En revanche, les langages de type C ne fournissent pas les moyens d’abstraction nécessaires. Cela se voit par le fait qu’il existe quelque chose comme “modèles”. Un modèle est une stratégie commune qui ne peut pas être exprimée par le code de la bibliothèque et doit donc être écrite expressément chaque fois qu’elle est appliquée.

Paul Graham ne pense pas que les modèles sont mauvais en eux-mêmes. Ils sont un symptôme de langues qui ne fournissent pas de moyens d’abstraction. À cet égard, il a presque certainement raison. Si nous devons utiliser des langues différentes à cause de cela, c’est bien sûr une autre discussion.

L’affiche originale de la question, en revanche, est erronée: les modèles ne sont pas des «symptômes de ne pas avoir assez d’abstraction dans votre code», mais sont des symptômes de l’absence de moyens d’abstraction dans votre langue.

Les patterns ne sont en réalité qu’un moyen de décrire le fonctionnement des choses. C’est un moyen de les classer. Y a-t-il des programmes qui les abusent? Sûr. Le plus grand avantage d’avoir des patterns est qu’en classant quelque chose comme ceci ou cela, tout le monde est sur la même page (en supposant qu’ils possèdent le niveau de connaissance nécessaire pour savoir de quoi on parle). Lorsque vous avez un système avec 10 000 lignes de code, il devient nécessaire de pouvoir déterminer rapidement comment cela fonctionnera.

Est-ce que cela signifie que vous devez toujours utiliser des patterns, non. Cela conduira à des problèmes pour forcer les choses dans une classification, mais vous ne devriez pas vous en détourner non plus.

Mon problème avec les modèles est qu’il semble y avoir un mensonge central au cœur du concept: L’idée que si vous pouvez classer les experts en code, vous pouvez écrire du code expert en reconnaissant et en appliquant simplement les catégories. Cela semble bien pour les gestionnaires, car les concepteurs de logiciels experts sont relativement rares.

Le problème est que ce n’est pas vrai. Vous ne pouvez pas écrire un code de qualité expert avec uniquement des «modèles de conception», pas plus que vous ne pouvez concevoir vos propres vêtements de qualité professionnelle en utilisant uniquement des motifs de couture .

La forme d’un programme ne doit refléter que le problème à résoudre.

Et que se passe-t-il lorsque les exigences changent et que votre module n’a pas été extrait à l’aide d’une façade ou d’un médiateur, ce qui rend trop difficile le remplacement?

les motifs de conception sont un signe d’abstraction insuffisante

Les chances sont, si vous avez tout résumé correctement, alors vous avez un modèle de conception quelque part.

Que se passe-t-il s’il y a un object extrêmement lourd qui ne doit pas être chargé? Le modèle de proxy évite à l’utilisateur d’attendre pour toujours.

Je pourrais continuer, mais je pense en avoir assez dit. Les modèles de conception sont d’excellents outils lorsqu’ils sont utilisés correctement. Le problème vient quand ils sont mal utilisés, mais je suppose que c’est pourquoi les modèles mal utilisés sont appelés anti-patterns.

Je crois que cette partie de la citation de Paul Graham est importante:

[…] J’utilise des abstractions qui ne sont pas assez puissantes – souvent que je génère à la main les expansions de certaines macro que j’ai besoin d’écrire […]

Cela montre que si vous pouvez construire ces abstractions dans votre langue (et que vous pouvez pratiquement tout faire avec Lisp, ce à quoi il pense probablement), vous n’avez pas besoin de les modéliser avec des patterns.

Mais tout le monde n’utilise pas Lisp, vous ne pourrez donc construire que des abstractions là où vous le pouvez et utiliser des patterns là où vous ne pouvez pas. À titre d’exemple, dans les langues sans fonctions d’ordre supérieur , celles-ci sont souvent modélisées à l’aide du modèle de stratégie .

Cela semble être une question de regard: le modèle peut être considéré comme un symptôme d’un problème (par exemple, l’absence de fonctions d’ordre supérieur) ou comme une solution au problème (par exemple, créer quelque chose comme un ordre supérieur). fonctions possibles via le schéma de stratégie).

[soupir] Combien de coups contre les bonnes pratiques devons-nous démystifier avant que les gens commencent à utiliser leur propre jugement?

Réponse courte: si vous faites du vrai travail dans un langage orienté object, il est fort probable que vous ayez implémenté certains des modèles de conception du GoF pour faire le travail. Que vous réalisiez ce que vous avez fait ou non est une question d’éducation, de perspective et d’introspection. Nier que vous ayez déjà fait ceci ou que les modèles n’existent pas ou ne sont pas “nécessaires” ou sont “surutilisés” est ridicule – à moins que vous n’écriviez jamais quelque chose de plus complexe que “Bonjour tout le monde” 😉

Pourquoi, l’autre jour, j’ai dû implémenter une façade de visiteur pour un singleton juste pour que la stratégie de l’adaptateur fonctionne 😛

Le terme Pattern Designs est surchargé et déroutant.

Il y a une manière étroite de penser à cela: fondamentalement comme un nom collectif pour les concepts d’OO énumérés dans le livre de GoF, par exemple, Singleton, Facade, Strategy. Vous utilisez probablement cette définition si vous placez les modèles de conception en tant que compétence sur votre CV.

Un projet peut facilement contenir des dizaines d’objects singleton. Ce modèle profite bien évidemment du fait d’être codé en tant qu’abstraction instanciable, par exemple en tant que macro ou classe abstraite. De même pour de nombreux autres modèles du livre GoF.

Il me semble que la thèse de Paul Graham est la suivante: les modèles de conception, étant des moyens standard de se répéter, devraient être codifiés comme des abstractions instanciables et, par corollaire, vous devez utiliser un langage très flexible pour définir l’abstraction instanciable.

Mais le concept est plus général – je pense qu’il dénature les modèles de conception. Christopher Alexander a inventé le concept afin de l’appliquer au design des pays, des villes et des maisons. Les concepteurs de jeux ont des langages tels que Fog-of-War, Asymmesortingcal-Abilities, etc.

Dans ce sens général, il devient beaucoup moins évident que les modèles de conception doivent tous être codés comme des abstractions instanciables.

Si vous n’avez pas lu A Pattern Language, consultez-en la scope ici . Imaginez quelque chose comme ça pour le monde du logiciel. Les modèles du GoF seraient très bas au bas de la ToC: ce sont des détails de mise en œuvre.

Quels autres modèles pourriez-vous trouver au-dessus d’eux?

Je suppose qu’un chapitre aurait des motifs liés au jeu. Il pourrait incorporer à la fois des schémas de conception de jeu et des techniques d’implémentation – et je pense qu’il ne s’agit pas là d’une distinction claire – comme la boucle de jeu, l’entité mondiale, le hachage spatial, le paysage de hauteur, etc. Ce sont tous des modèles de conception.

Maintenant, dans le cadre d’un projet de jeu, vous n’aurez probablement qu’une seule implémentation d’entité mondiale. Toute personne travaillant dans n’importe quelle langue aurait le sens de faire de cette entité mondiale une abstraction instanciable comme une classe de base.

Mais ce que le modèle décrit, c’est comment cette abstraction est formée: elle contient une notion de position, elle est rendu, etc. Il n’est pas évident que ce Pattern Design puisse être codé en tant que macro ou classe abstraite en soi – le modèle décrit déjà une abstraction! Feriez-vous une métaclasse pour les implémentations d’entités mondiales? Une macro pour définir des classes d’entités mondiales, avec toutes sortes de parameters impies?

En regardant plus loin la table des matières imaginaire, nous voyons que ces modèles sont subordonnés à un modèle plus général, celui du jeu. Est-ce que cela vaut la peine de coder en tant que macro ou classe abstraite? Peut être. Mais pas évidemment Nous parlons d’une structure de jeu, où vous définissez un jeu d’ordinateur en passant des parameters, en remplissant les blancs, etc. Cela pourrait être productif et amusant, mais ce n’est pas la seule façon de faire les choses.

La plate-forme Erlang possède des abstractions instantanées pour les patterns aussi généraux que le serveur, ce qui est cool. Et je suppose qu’un projet Erlang a autant de serveurs qu’un projet Java avec Singletons.

Mais pour vos besoins spécifiques, si vous travaillez dans Lisp, Haskell, ou autre, et que vous écrivez un serveur, il suffit parfois de suivre le modèle du serveur, de l’implémenter comme de bons vieux objects et fonctions, sans essayer de le rendre instantané. abstraction de la chose entière.

Tous les modèles de conception ne sont pas des modèles textuels de bas niveau dans votre code source.

Je pense que Paul Graham manque la marque grand temps sur celui-ci. L’utilisation de patterns ne consiste pas à choisir un livre qui les répertorie et à en appliquer certains à votre code. Je conviens que ce serait un mauvais choix mais ce n’est pas ce dont il s’agit.

Les modèles de conception sont simplement une façon de reconnaître “Hé, je reconnais que cela est similaire à un autre problème que j’ai résolu auparavant” et d’apprendre à créer une bonne abstraction de la solution afin qu’elle soit applicable dans des situations appropriées.

En fait, si vous avez programmé quelque chose de taille raisonnable, il est fort probable que vous ayez utilisé des schémas de conception connus et que vous ne saviez pas qu’il y avait un nom. Par exemple, j’ai utilisé le modèle “usine” pendant longtemps avant de me rendre compte qu’il s’agissait d’une “usine”. Le fait de savoir ce que l’on appelle officiellement m’empêche simplement de réinventer la roue.

Bien sûr, certains modèles bien connus sont un peu dingues; Singleton est définitivement suspect. Mais celui-ci constituait une solution claire à une solution trop astucieuse, à la recherche d’un problème à résoudre et à éviter. Mais c’est pourquoi vous pouvez trouver beaucoup de documentation pour et contre elle, car les gens reconnaissent que ce n’est peut-être pas une bonne solution.

Mais les modèles dans leur ensemble sont une très bonne chose, s’ils encouragent l’ abstraction.

Je crois que l’affirmation de Paul Graham est que les modèles de conception doivent être exprimés dans la langue. S’il y a un motif X, cela signifie que les gens sont obligés de réécrire des séquences de code pour le faire, et il devrait y avoir une manière spécifique de la parler. Cela pourrait être intégré dans le langage (bien que ce soit maladroit, et peut créer de nouveaux modèles de conception), ou être automatisable dans le langage (comme les macros Common Lisp; les modèles C ++, en particulier lorsqu’ils sont utilisés de manière étrange) parfois).

Par exemple, considérons un modèle beaucoup plus simple: la boucle d’incrémentation. Avoir à faire quelque chose sur chaque élément d’une séquence est assez courant, et si nous n’avions pas quelque chose correspondant à une déclaration, nous adopterions sans doute une convention de codage commune pour l’exprimer, et quelqu’un (ou un quatuor) mettrait cela ensemble. avec d’autres constructions élémentaires similaires et écrivez un livre à ce sujet.

De même, si vous utilisez un motif Factory, un langage peut inclure une fonctionnalité Factory ou l’automatiser dans la langue. Plus précisément, Paul veut pouvoir écrire une macro Lisp pour l’implémenter, plutôt que d’écrire Factories lui-même encore et encore.

Le danger d’utiliser un modèle de conception est que c’est un cadre de code familier que nous continuons à taper, et que nous avons donc des morceaux de code que nous avons tendance à ne pas lire ni écrire avec une attention toute particulière. L’inconvénient est que le code qu’il faut taper encore et encore, et le sentiment que la réécriture devrait vraiment être automatisée.

Que les modèles jouent un rôle essentiel dans l’utilisation des langages, comme le dit le GoF, ou peut être abstrait, comme le dit PG, est fondamentalement une question empirique, probablement mieux résolue en cherchant des langages où les modèles eux-mêmes sont inutiles. vraiment besoin de nouveaux modèles.

Les motifs de conception sont définis comme suit (à partir de wikipedia, mais j’ai lu la même chose dans certains livres)

En génie logiciel, un modèle de conception est une solution réutilisable générale à un problème courant dans la conception de logiciels. Un motif de conception n’est pas un dessin fini pouvant être transformé directement en code. C’est une description ou un modèle sur la façon de résoudre un problème qui peut être utilisé dans de nombreuses situations différentes.

Si vous envisagez d’appliquer des modèles directement à partir du décalage sans entrer dans le domaine problématique, cela peut entraîner des problèmes. Utilisez des modèles de conception comme guide ou plus comme astuce / conseil pour résoudre un problème. Un motif de conception appliqué avec force ne donnera certainement pas une solution suffisamment abstraite. On voit souvent que dans le logiciel d’entreprise, une variante ou une combinaison de quelques modèles de conception sont utilisés. Si vous dites que vous n’avez jamais utilisé de motifs de conception, vous seriez heureux de savoir que quelque chose comme une boucle foreach est en fait un motif d’interaction et que vous pouvez rechercher des implémentations plus évidentes près de chez vous!

En bref, les modèles ne sont que des moyens formalisés de résoudre des tâches communes dans différentes langues. En tant que tel, il existait des “modèles de conception” avant même que le terme ne soit inventé. Pour chaque langue, il existe des «meilleures pratiques» et les modèles de conception ne sont que cela: un ensemble de meilleures pratiques pour les problèmes qui se produisent régulièrement.

L’un des principaux avantages de l’étiquetage des motifs est que la terminologie partagée nous permet de parler de concepts abstraits.

De toute évidence, les modèles de conception peuvent être mal utilisés ou surexploités dans un contexte donné, mais je ne vois vraiment pas comment les modèles de conception en tant que concept peuvent poser problème.

Il y a un temps et un lieu pour tout. J’ai vu du code avec trop de motifs, ce qui correspondrait à votre propos, mais aussi avec trop peu de motifs, ce qui rend le code difficile à maintenir et sujet aux erreurs lors des modifications.

Généraliser quelque chose comme cela va être logiquement imparfait, mais si vous reformulez votre question à la manière de “peut-il y avoir trop de modèles dans le code qui sont symptomatiques d’un problème plus important, c’est-à-dire des niveaux d’abstraction insuffisants”? la réponse serait oui. Est-ce toujours le cas? Non.

Lorsque je programmais dans LISP, je n’utilisais pas du tout les modèles de conception GoF, cela ne s’appliquait pas aux programmes que j’écrivais. Maintenant, je programme en C # et je traverse des situations où un modèle de conception simplifie réellement l’écriture du programme.

Il y a beaucoup de maximes que nous utilisons (et qui sont communes autour de SO) qui, si vous les retracez à la source, ont été à l’origine affirmées avec des réserves; comme dans “… quand vous développez en utilisant …” C’est l’un de ces cas. Les motifs s’adaptent bien lorsque vous effectuez une POO. YMMV quand vous êtes dans un autre paradigme.

“Refactoring” est un autre cas similaire.

Lorsque j’écris du code SQL, la partie “patterns” de mon cerveau est désactivée.

Notez dans votre citation: “Je génère à la main les extensions de certaines macros que j’ai besoin d’écrire”. Il reconnaît donc les motifs et les résume dans une macro – il ne les recode pas autrement. Juste bon vieux ‘SEC. Ce ne sont pas les modèles, mais le fait de ne pas faire ce qu’il faut avec ceux que nous trouvons. Je dirais que son commentaire pourrait aller dans n’importe quelle entrée de wiki développant les vertus de DRY et comment les posséder. Le GoF serait tout à fait d’accord – reconnaissez les modèles de conception, puis utilisez ce que vous savez à leur sujet pour les mettre en œuvre (ou les restructurer) de manière appropriée.

Au cours de la phase de conception de mes programmes, je mets souvent l’ accent sur le problème , et une fois que je l’ai décomposé, je peux facilement commencer à reconnaître les motifs inhérents à la conception. À ce stade, je peux commencer à appliquer des modèles de conception bien connus pour pouvoir communiquer ou mettre en œuvre la conception en utilisant un langage commun que je peux utiliser pour la communication. J’espère pouvoir réutiliser certains objects génériques précédemment mis en œuvre lors de la mise en œuvre d’un modèle similaire.

Souvent, lorsque les modèles de conception ne sont pas appliqués correctement, c’est parce que le processus se déroule en sens inverse. Le programmeur Joe (mes excuses à vous, Joe) lit un livre sur les Design Patterns et dit: “Ok, je comprends Design Pattern X, maintenant comment puis-je l’appliquer à mon application?” C’est faux.

Les modèles de conception peuvent être une arme puissante, mais comme tout le rest, ils doivent être utilisés de manière appropriée, et le programmeur doit toujours être prêt à incorporer des idées originales dans sa conception.

Je pense que parfois, lorsque vous apprenez un motif, vous ne vous contentez pas d’apprendre le motif. Mais vous obtenez une nouvelle vision du problème que vous n’avez peut-être jamais rencontré auparavant. Et c’est peut-être exactement ce que vous vouliez.

Sans contexte pour le “problème”, nous ne pouvons pas dire si les modèles de conception sont la solution ou non.

Il n’est jamais nécessaire d’utiliser des modèles de conception – vous pouvez toujours écrire du code qui ignore tout ce qui a été appris jusqu’à maintenant – il peut même fonctionner. Mais les modèles de conception peuvent faciliter les choses, vous donnant un langage commun pour discuter du design.

Les motifs de Diesign ne représentent pas trop peu d’abstraction – ils tentent d’augmenter le niveau d’abstraction. Vous pouvez dire que “ce bit est un visiteur” plutôt que “voici un code qui traverse récursivement une arborescence d’objects, effectuant une opération sur eux”.

Les patterns sont le problème s’ils ne sont pas une solution. Je veux dire par là: si un modèle est introduit pour le motif et non pour résoudre un problème de conception existant dans l’application, il risque de poser des problèmes plutôt que de les résoudre ou de les empêcher.
Je continue à dire aux gens ici au travail que le livre Gang of Four (Design Patterns: Elements of Objective-Oriented Software) est une référence, pas un manuel pour un bon design.

Oui, pg est juste là. Si vous voyez un code similaire dans votre application, cela signifie que vous ne disposez pas d’une abstraction de ce code. Moins de code, c’est mieux.

Voici un autre article sur le sujet: http://blog.plover.com/prog/design-patterns.html

Je préférerais travailler avec trop de modèles que pas du tout. Cela dit, le bon équilibre est bien sûr l’objective.

Cette phrase n’a aucun sens: les motifs de conception sont un signe de l’abstraction insuffisante Comme les dessins de conception sont une abstraction! En suivant les réponses ici, je suis d’accord que les langages de programmation devraient avoir un moyen d’exprimer des modèles de conception. Cependant, cela n’est évidemment pas possible pour toutes les situations.

Je me souviens d’une interview avec un membre du GoF où quelqu’un a posé une question sur l’affirmation commune selon laquelle les modèles de conception sont des outils pour remplacer les fonctionnalités qui manquent dans une langue. L’auteur a fait valoir que: A) toute langue a des modèles de conception (pas les mêmes) puisque les modèles de conception sont des outils conçus pour fonctionner avec les idiosynchrasies de langage et B)

Les modèles de conception sont des solutions aux problèmes courants.

Mais d’abord, vous devez savoir quoi ou où est le problème. Et c’est le point où les gens ne parviennent pas à utiliser les modèles correctement.

Je n’ai pas encore trouvé d’utilisation de GoF “Design Patterns” dans mon code. Le coderati semble s’être accroché au livre GoF, et on s’attend maintenant à ce que la plupart des entresockets que vous connaissez et appliquent. Juste aujourd’hui, j’ai eu une entrevue et on m’a demandé quels modèles je connaissais et j’avais utilisés, et comment je les appliquerais à une application d’entreprise pour une grande banque.

L’idée générique d’apprendre de nos projets antérieurs est évidemment logique. Ce qui n’a pas de sens est le battage médiatique et le culte autour des modèles spécifiques du GoF, les gens les prenant pour une bonne pratique de codage, et étant censés les aimer et les emarmser pour être qualifiés de développeurs compétents.

Donc, pour répondre à votre question, je dirais que l’idée des modèles de conception du GoF est mal comprise et trop utilisée par la plupart. Nous devons évoluer vers une utilisation de haut niveau des modèles de conception en tant qu’outil d’apprentissage général qui s’applique à la manière dont nous apprenons et perfectionnons OO – pas seulement en tant que 20 idées révolutionnaires à mémoriser et à imposer aux programmes. Il n’y a pas de solution miracle.

Les langages de programmation, tels que les langages parlés, vous fournissent le vocabulaire pour dire ce que vous voulez. Les patterns décrivent seulement une manière de dire des choses qui permet aux gens de savoir ce dont vous parlez à un niveau plus élevé.

Si vous me permettez une métaphore: écrire de la musique est un «problème» commun et la musique est souvent (de toute évidence pas toujours) composée de manière assez vague comme une sorte de variation de ce qui suit:

verset refrain verset refrain verset chœur choeur

Qui, en effet, est un «modèle». Vous devez quand même écrire la chanson et toutes les chansons écrites ne fonctionneront pas bien avec ce modèle.

Ce que j’essaie de comprendre, c’est que les modèles ne sont pas une solution prête à l’emploi pour la programmation ou la musique. Ils sont un guide pour vous aider à démarrer et un tremplin à partir duquel vous pouvez faire quelque chose qui convient à vos besoins.