[Design-patterns] La programmation fonctionnelle remplace-t-elle les modèles de conception du GoF?


Answers

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.

La programmation fonctionnelle (comme tous les 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 un moyen de construction intemporel, indépendamment de la technologie ou du domaine du 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.

Question

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 que j'ai trouvé fait une affirmation assez forte :

La plupart des gens que j'ai rencontrés ont lu le livre Design Patterns du Gang of Four. Tout programmeur respectueux de soi vous dira que le livre est agnostique et que les schémas s'appliquent au génie logiciel en général, quelle que soit la langue que vous utilisez. C'est une revendication noble. Malheureusement, c'est loin de la vérité.

Les langages fonctionnels sont extrêmement expressifs. Dans un langage fonctionnel, on n'a pas besoin de modèles de design parce que la langue est probablement de si haut niveau, on finit par programmer dans des concepts qui éliminent tous les modèles de design.

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?




Je voudrais ajouter deux excellents articles de Jeremy Gibbons, mais assez denses: «Les patrons de design en tant que programmes génériques de type supérieur» et «L'essence du modèle Iterator» (tous deux disponibles ici: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/ ).

Tous deux décrivent comment les constructions fonctionnelles idiomatiques couvrent le terrain couvert par des modèles de conception spécifiques dans d'autres contextes (orientés objet).




Et même les solutions OO Design Pattern sont spécifiques à la langue. Les modèles de conception sont des solutions aux problèmes courants que votre langage de programmation ne résout pas pour vous. En Java, le pattern Singleton résout le problème un-de-quelque chose (simplifié). Dans Scala, vous disposez d'une construction de niveau supérieur appelée Object en plus de Class. C'est paresseusement instancié et il n'y en a qu'un. Vous n'avez pas besoin d'utiliser le motif Singleton pour obtenir un Singleton. Cela fait partie de la langue.




Le livre GOF se rattache explicitement à OOP - le titre est Design Patterns - Éléments de logiciels orientés objet réutilisables (emphase mienne.)




OOP et FP ont des objectifs différents, OOP vise à encapsuler les complexités / parties mobiles des composants logiciels et FP vise à minimiser la complexité et les dépendances des composants logiciels mais ces 2 paradigmes ne sont pas nécessairement contradictoires à 100% et pourraient être appliqués ensemble pour obtenir le bénéfice des deux mondes. Même avec un langage qui ne supporte pas nativement la programmation fonctionnelle comme C #, vous pouvez écrire du code fonctionnel si vous comprenez les principes FP, de même vous pouvez appliquer les principes PO en utilisant F # si vous comprenez les principes, les modèles et les meilleures pratiques. Vous feriez le bon choix en fonction de la situation et du problème que vous essayez de résoudre, quel que soit le langage de programmation que vous utilisez.




Comme d'autres l'ont dit, il existe des modèles spécifiques de programmation fonctionnelle. Je pense que la question de se débarrasser des modèles de conception n'est pas tellement de passer à fonctionnel, mais une question de fonctionnalités linguistiques .

Jetez un oeil à la façon dont Scala supprime le "modèle singleton": vous déclarez simplement un objet au lieu d'une classe. Une autre caractéristique, l'appariement de modèles, permet d'éviter le clunkiness du modèle de visiteur. Voir la comparaison ici: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html

Et Scala, comme F #, est une fusion de OO-fonctionnelle. Je ne sais pas sur F # mais il a probablement ce genre de fonctionnalités.

Les fermetures sont présentes dans un langage fonctionnel, mais ne doivent pas nécessairement leur être limitées. Ils aident avec le modèle de délégant.

Une observation de plus. Ce morceau de code implémente un motif: c'est un classique et c'est tellement élémentaire qu'on ne le considère généralement pas comme un "pattern", mais c'est sûr:

for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }

Les langages impératifs comme Java et C # ont adopté ce qui est essentiellement une construction fonctionnelle pour faire face à cela: "foreach".




Je pense que seuls deux motifs de conception GoF sont conçus pour introduire la logique de programmation fonctionnelle dans le langage OO naturel. Je pense à la stratégie et au commandement. Certains des autres motifs de conception du GoF peuvent être modifiés par programmation fonctionnelle pour simplifier la conception et conserver le but.




Essentiellement, oui !

  • Lorsqu'un pattern contourne les fonctionnalités manquantes (fonctions d'ordre supérieur, gestion de flux ...), ultimalty facilite la composition .
  • La nécessité de réécrire encore et encore la mise en œuvre des modèles peut elle-même être perçue comme une odeur de langage .

En outre, cette page (AreDesignPatternsMissingLanguageFeatures) fournit une table de traduction "pattern / feature" et de belles discussions, si vous êtes prêt à creuser.







Dans le nouveau livre de 2013 intitulé "Functional Programming Patterns - in Scala and Clojure", l'auteur Michael.B. Linn fait un travail décent en comparant et fournissant des remplacements dans de nombreux cas pour les modèles du GoF et discute aussi des modèles fonctionnels plus récents comme «récursivité de la queue», «mémoisation», «séquence paresseuse», etc.

Ce livre est disponible sur Amazon. Je l'ai trouvé très instructif et encourageant quand je viens d'un arrière-plan OO de quelques décennies.




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.

Un de mes patrons préférés est le pattern Null Object: représente l'absence de quelque chose en tant qu'objet qui fait un genre 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.