Question La programmation fonctionnelle remplace-t-elle les modèles de conception du GoF?


Depuis que j'ai commencé à apprendre F # et OCaml l'année dernière, j'ai lu un grand nombre d'articles qui insistent sur le fait que les modèles de design (spécialement en Java) sont des solutions de contournement pour les fonctionnalités manquantes dans les langages impératifs. Un article trouvé fait une réclamation assez forte:

La plupart des gens que j'ai rencontrés ont lu   Design Patterns livre par le Gang of   Quatre. Tout programmeur respectueux de soi   vous dira que le livre est   langue agnostique et les modèles   appliquer à l'ingénierie logicielle dans   général, quelle que soit la langue   tu utilises. C'est une revendication noble.   Malheureusement, il est loin de   la vérité.

Les langues fonctionnelles sont extrêmement   expressif. Dans un langage fonctionnel   on n'a pas besoin de modèles de conception   parce que la langue est probablement si élevée   niveau, vous finissez par programmer dans   concepts qui éliminent la conception   modèles tous ensemble.

Les principales caractéristiques de la programmation fonctionnelle comprennent des fonctions telles que des valeurs de première classe, des valeurs immuables, des valeurs immuables, etc. Il ne me semble pas évident que les modèles de conception OO se rapprochent de ces caractéristiques.

De plus, dans les langages fonctionnels qui prennent en charge la POO (comme F # et OCaml), il me semble évident que les programmeurs utilisant ces langages utiliseraient les mêmes modèles de conception que ceux disponibles pour tous les autres langages POO. En fait, maintenant j'utilise F # et OCaml tous les jours, et il n'y a pas de différences frappantes entre les modèles que j'utilise dans ces langages et ceux que j'utilise quand j'écris en Java.

Existe-t-il une vérité à l'affirmation selon laquelle la programmation fonctionnelle élimine le besoin de modèles de conception OOP? Si oui, pourriez-vous poster ou lier un exemple de modèle de conception OOP typique et son équivalent fonctionnel?


941
2017-11-29 20:08


origine


Réponses:


Le billet de blog que vous avez cité exagère un peu sa revendication. FP ne fait pas éliminer le besoin de modèles de conception. Le terme "modèles de conception" n'est tout simplement pas très utilisé pour décrire la même chose dans les langages de la PF. Mais ils existent. Les langages fonctionnels ont beaucoup de règles de bonne pratique de la forme "quand vous rencontrez le problème X, utilisez le code qui ressemble à Y", qui est fondamentalement ce qu'est un modèle de conception.

Cependant, il est correct que la plupart des modèles de conception spécifiques à la POO ne sont pas pertinents dans les langages fonctionnels.

Je ne pense pas qu'il devrait être particulièrement controversé de dire que les modèles de conception en général n'existe que pour combler les lacunes dans la langue. Et si une autre langue peut résoudre le même problème trivialement, cette autre langue n'aura pas besoin d'un modèle de conception pour cela. Les utilisateurs de cette langue peuvent même ne pas être conscients que le problème existe, parce que, eh bien, ce n'est pas un problème dans cette langue.

Voici ce que le Gang of Four a à dire sur cette question:

Le choix du langage de programmation est important car il influence le point de vue de chacun. Nos modèles supposent des fonctionnalités de langage de niveau Smalltalk / C ++, et ce choix détermine ce qui peut et ne peut pas être implémenté facilement. Si nous supposions des langages procéduraux, nous aurions pu inclure des motifs de conception appelés «Héritage», «Encapsulation» et «Polymorphisme». De même, certains de nos modèles sont pris en charge directement par les langages orientés objet les moins courants. CLOS a des méthodes multiples, par exemple, ce qui réduit le besoin d'un modèle tel que Visitor. En fait, il existe suffisamment de différences entre Smalltalk et C ++ pour que certains modèles puissent être exprimés plus facilement dans une langue que dans l'autre. (Voir Iterator par exemple.)

(Ce qui précède est une citation de l'introduction au livre de modèles de conception, page 4, paragraphe 3)

Les principales caractéristiques de la fonctionnalité   la programmation comprennent des fonctions comme   valeurs de première classe, currying,   valeurs immuables, etc. Il ne semble pas   évident pour moi que les modèles de conception OO   sont l'approximation de l'un de ceux   fonctionnalités.

Quel est le modèle de commande, sinon une approximation des fonctions de première classe? :) Dans un langage FP, vous passeriez simplement une fonction comme argument à une autre fonction. Dans un langage OOP, vous devez encapsuler la fonction dans une classe, que vous pouvez instancier et ensuite passer cet objet à l'autre fonction. L'effet est le même, mais dans la POO, cela s'appelle un motif de conception, et il faut beaucoup plus de code. Et quel est le modèle d'usine abstraite, sinon en cours? Transmettez les paramètres à une fonction un peu à la fois, pour configurer le type de valeur qu'il recrache lorsque vous l'appelez enfin.

Alors oui, plusieurs modèles de conception du GoF sont rendus redondants dans les langages FP, car des alternatives plus puissantes et plus faciles à utiliser existent.

Mais bien sûr, il existe encore des modèles de conception qui sont ne pas résolu par les langues FP. Quel est l'équivalent FP d'un singleton? (Sans tenir compte pour un moment que les singletons sont généralement un modèle terrible à utiliser)

Et cela fonctionne dans les deux sens aussi. Comme je l'ai dit, FP a aussi ses modèles de conception, les gens ne les considèrent généralement pas comme tels.

Mais vous avez peut-être couru à travers les monades. Quels sont-ils, sinon un modèle de conception pour "traiter avec l'état global"? C'est un problème si simple dans les langages OOP qu'il n'y a pas de modèle de conception équivalent.

Nous n'avons pas besoin d'un modèle de conception pour "incrémenter une variable statique", ou "lire à partir de cette socket", parce que c'est juste ce que vous faire.

Dans les langages fonctionnels (purs), les effets secondaires et l'état mutable sont impossibles, à moins que vous ne l'utilisiez avec le "motif de conception" de la monade, ou l'une quelconque des autres méthodes permettant la même chose.

De plus, dans les langues fonctionnelles   qui soutiennent OOP (tels que F # et   OCaml), il me semble évident que   les programmeurs utilisant ces langues   utiliserait les mêmes modèles de conception   trouvé disponible pour tous les autres POO   la langue. En fait, en ce moment j'utilise F #   et OCaml tous les jours, et il n'y a pas   différences frappantes entre le   modèles que j'utilise dans ces langues vs   les modèles que j'utilise quand j'écris   Java.

Peut-être parce que vous pensez toujours impérativement? Beaucoup de gens, après avoir traité des langues impératives toute leur vie, ont du mal à abandonner cette habitude quand ils essaient un langage fonctionnel. (J'ai vu quelques tentatives assez drôles à F #, où littéralement chaque La fonction était juste une chaîne d'instructions 'let', essentiellement comme si vous aviez pris un programme C, et remplacé tous les points-virgules par 'let'. :))

Mais une autre possibilité pourrait être que vous n'avez tout simplement pas réalisé que vous résolvez les problèmes de manière triviale, ce qui nécessiterait des modèles de conception dans un langage OOP.

Lorsque vous utilisez currying, ou passez une fonction comme argument à un autre, arrêtez-vous et réfléchissez à la façon dont vous le feriez dans un langage OOP.

Y a-t-il une vérité à l'affirmation   la programmation fonctionnelle élimine le   besoin de modèles de conception OOP?

Oui. :) Lorsque vous travaillez dans un langage FP, vous n'avez plus besoin des modèles de conception spécifiques à la POO. Mais vous avez toujours besoin de modèles de conception généraux, tels que MVC ou d'autres éléments non spécifiques à la POO, et vous avez besoin de quelques nouveaux "modèles de conception" spécifiques à FP à la place. Toutes les langues ont leurs défauts, et les modèles de conception sont généralement comment nous travaillons autour d'eux.

Quoi qu'il en soit, vous trouverez peut-être intéressant de vous initier aux langages FP "plus propres", comme ML (mon préféré, au moins à des fins d'apprentissage), ou Haskell, où vous n'avez pas besoin de la béquille OOP quand vous sommes confrontés à quelque chose de nouveau.


Comme prévu, quelques personnes se sont opposées à ma définition des modèles de conception comme «réparer les lacunes dans une langue», alors voici ma justification: Comme déjà dit, la plupart des modèles de conception sont spécifiques à un paradigme de programmation, ou parfois même à un langage spécifique. Souvent, ils résolvent des problèmes uniquement exister dans ce paradigme (Voir monades pour FP, ou les usines abstraites pour POO). Pourquoi le modèle d'usine abstraite n'existe-t-il pas dans FP? Parce que le problème qu'il essaie de résoudre n'existe pas là. Ainsi, si un problème existe dans les langages POO, qui n'existe pas dans les langages FP, il est clair que cela constitue une lacune des langages POO. Le problème peut être résolu, mais votre langage ne le fait pas, mais nécessite un tas de code standard de votre part pour contourner ce problème. Idéalement, nous aimerions que notre langage de programmation fasse magiquement tout les problèmes disparaissent. Tout problème qui existe encore est en principe une lacune de la langue. ;)


950
2017-11-29 23:06



Existe-t-il une vérité à l'affirmation selon laquelle la programmation fonctionnelle élimine le besoin de modèles de conception OOP?

La programmation fonctionnelle n'est pas la même que la programmation orientée objet. Les modèles de conception orientés objet ne s'appliquent pas à la programmation fonctionnelle. Au lieu de cela, vous avez des modèles de conception de programmation fonctionnelle.

Pour la programmation fonctionnelle, vous ne lirez pas les livres de modèles de conception OO, vous lirez d'autres livres sur les modèles de conception de FP.

langage agnostique

Pas totalement. Seul langage-agnostique par rapport aux langues OO. Les modèles de conception ne s'appliquent pas du tout aux langages procéduraux. Ils ont à peine du sens dans un contexte de conception de base de données relationnelle. Ils ne s'appliquent pas lors de la conception d'une feuille de calcul.

un modèle de conception OOP typique et son équivalent fonctionnel?

Ce qui précède ne devrait pas exister. C'est comme demander un code de procédure réécrit comme code OO. Ummm ... Si je traduis l'original Fortran (ou C) en Java, je n'ai rien fait de plus que de le traduire. Si je le réécris totalement dans un paradigme OO, il ne ressemblera plus à l'original Fortran ou C - il sera méconnaissable.

Il n'y a pas de correspondance simple entre OO Design et Functional Design. Ce sont des façons très différentes de regarder le problème.

Programmation fonctionnelle (comme tout styles de programmation) a des motifs de conception. Les bases de données relationnelles ont des modèles de conception, OO a des modèles de conception, la programmation procédurale a des modèles de conception. Tout a des motifs de design, même l'architecture des bâtiments.

Les modèles de conception - en tant que concept - sont une manière intemporelle de construire, indépendamment de la technologie ou du domaine de problème. Cependant, des modèles de conception spécifiques s'appliquent à des domaines et à des technologies spécifiques.

Tous ceux qui pensent à ce qu'ils font découvriront des modèles de design.


135
2017-11-29 20:15



Les commentaires de Brian sur le lien étroit entre le langage et le modèle sont justes,

La partie manquante de cette discussion est le concept d'idiome. Le livre de Coplien, "Advanced C ++" a eu une énorme influence ici. Bien avant de découvrir Christopher Alexander et le Colonne sans nom (et vous ne pouvez pas parler de façon sérieuse des modèles sans lire Alexandre non plus), il a parlé de l'importance de maîtriser l'idiome dans l'apprentissage réel d'une langue. Il a utilisé la copie de chaîne en C comme exemple, tandis que (* de ++ = * à ++); Vous pouvez le voir comme un bandaid pour un élément de langage manquant (ou une fonction de bibliothèque), mais ce qui compte vraiment, c'est que c'est une unité de pensée ou d'expression plus grande que n'importe laquelle de ses parties.

C'est ce que tentent de faire les schémas et les langages pour nous permettre d'exprimer nos intentions plus succinctement. Plus les unités de pensée sont riches, plus les pensées que vous pouvez exprimer sont complexes. Avoir un vocabulaire riche et partagé à différentes échelles - de l'architecture du système à la manipulation des bits - nous permet d'avoir des conversations plus intelligentes et des réflexions sur ce que nous devrions faire.

Nous pouvons aussi, en tant qu'individus, apprendre. Quel est le point entier de l'exercice. Nous pouvons chacun comprendre et utiliser des choses que nous ne serions jamais capables de penser à nous-mêmes. Les langues, les cadres, les bibliothèques, les modèles, les idiomes, etc. ont tous leur place dans le partage de la richesse intellectuelle.


40
2018-01-01 20:59



Le livre GOF se rattache explicitement à OOP - le titre est Design Patterns - Elements of Reusable Orienté objet Logiciel (emphase le mien.)


35
2017-11-24 15:49



Modèles de conception dans la programmation dynamique par Peter Norvig a une couverture réfléchie de ce thème général, mais sur les langues «dynamiques» au lieu de «fonctionnel» (il y a chevauchement).


32
2017-11-29 20:23



Voici un autre lien, discutant de ce sujet: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

Dans son blog, Edward décrit les 23 motifs originaux du GoF en termes de Haskell.


24
2017-10-19 08:15



Lorsque vous essayez de regarder cela au niveau des «modèles de conception» (en général) et de «FP versus OOP», les réponses que vous trouverez seront au mieux obscures.

Aller un niveau plus profond sur les deux axes, cependant, et considérez modèles de conception spécifiques et caractéristiques spécifiques du langage et les choses deviennent plus claires.

Ainsi, par exemple, certains modèles spécifiques, comme Visiteur, Stratégie, Commander, et Observateur définitivement changer ou disparaître lors de l'utilisation d'une langue avec types de données algébriques et appariement de formes, fermetures, fonctions de première classeMais d'autres modèles du livre du GoF restent toujours en place.

En général, je dirais que, au fil du temps, les modèles spécifiques sont éliminés par de nouvelles caractéristiques du langage (ou simplement de la popularité croissante). C'est le cours naturel de la conception de la langue; Au fur et à mesure que les langues deviennent de plus haut niveau, les abstractions qui auparavant ne pouvaient être mentionnées que dans un livre en utilisant des exemples deviennent maintenant des applications d'une caractéristique ou d'une bibliothèque particulière.

(A part: voici un blog récent J'ai écrit, qui a d'autres liens vers d'autres discussions sur la PF et les modèles de conception.)


17
2017-11-29 23:15



La présentation de Norvig fait allusion à une analyse qu'ils ont faite de tous les modèles du GoF, et ils disent que 16 des 23 modèles avaient des implémentations plus simples dans les langages fonctionnels, ou faisaient simplement partie de la langue. Donc, vraisemblablement, au moins sept d'entre eux étaient a) tout aussi compliqués ou b) pas présents dans la langue. Malheureusement pour nous, ils ne sont pas énumérés!

Je pense qu'il est clair que la plupart des patterns «créationnels» ou «structurels» dans le GoF sont simplement des astuces pour faire en sorte que les systèmes de type primitif en Java ou en C ++ fassent ce que vous voulez. Mais le reste est digne de considération, peu importe la langue que vous programmez.

On pourrait être Prototype; Bien qu'il s'agisse d'une notion fondamentale de JavaScript, il doit être mis en œuvre à partir de zéro dans d'autres langues.

L'un de mes modèles préférés est le pattern Null Object: représente l'absence de quelque chose en tant qu'objet qui fait un type approprié de rien. Cela peut être plus facile à modéliser dans un langage fonctionnel. Cependant, la véritable réalisation est le changement de perspective.


15
2017-11-30 07:11