Programmation fonctionnelle vs programmation orientée objet [fermé]

784

Jusqu'à présent, j'ai été principalement exposé à la programmation OO et j'ai hâte d'apprendre un langage fonctionnel. Mes questions sont:

  • Quand choisissez-vous la programmation fonctionnelle plutôt que orientée objet?
  • Quelles sont les définitions de problèmes typiques où la programmation fonctionnelle est un meilleur choix?
Olivier Lalonde
la source
1
une question similaire cs.se a également fermé ce qui est un exemple où la programmation fonctionnelle donne de meilleurs résultats que le style impératif . la sagesse conventionnelle semble être que l'un n'est pas supérieur à l'autre, ou qu'ils ne sont pas comparables sur des critères simples, ou qu'ils sont utilisés à des fins différentes ... la programmation fonctionnelle a plus d'origines et d'utilisations scientifiques / universitaires et est moins courante dans l'industrie , de sorte que la question met également en place un pov / conflit insoluble "industrie vs milieu universitaire". une référence classique qui montre OOP sytle en programmation fonctionnelle, livre SICP / MIT
vzn
" OO rend le code compréhensible en encapsulant les pièces mobiles. FP rend le code compréhensible en minimisant les pièces mobiles. " --Micheal Feathers, 2010
jaco0646

Réponses:

1193

Quand choisissez-vous la programmation fonctionnelle plutôt que orientée objet?

Lorsque vous prévoyez un autre type d'évolution logicielle:

  • Les langages orientés objet sont bons lorsque vous avez un ensemble fixe d' opérations sur des choses , et que votre code évolue, vous ajoutez principalement de nouvelles choses. Cela peut être accompli en ajoutant de nouvelles classes qui implémentent des méthodes existantes, et les classes existantes sont laissées seules.

  • Les langages fonctionnels sont bons lorsque vous avez un ensemble fixe de choses et que votre code évolue, vous ajoutez principalement de nouvelles opérations sur des choses existantes. Cela peut être accompli en ajoutant de nouvelles fonctions qui calculent avec les types de données existants, et les fonctions existantes sont laissées seules.

Lorsque l'évolution va dans le mauvais sens, vous avez des problèmes:

  • L'ajout d'une nouvelle opération à un programme orienté objet peut nécessiter la modification de nombreuses définitions de classe pour ajouter une nouvelle méthode.

  • L'ajout d'un nouveau type de chose à un programme fonctionnel peut nécessiter la modification de nombreuses définitions de fonction pour ajouter un nouveau cas.

Ce problème est bien connu depuis de nombreuses années; en 1998, Phil Wadler l'a surnommé le «problème d'expression» . Bien que certains chercheurs pensent que le problème d'expression peut être résolu avec des fonctionnalités de langage telles que les mixins, une solution largement acceptée n'a pas encore atteint le courant dominant.

Quelles sont les définitions de problèmes typiques où la programmation fonctionnelle est un meilleur choix?

Les langages fonctionnels excellent dans la manipulation de données symboliques sous forme d'arbre. Un exemple préféré est les compilateurs, où les langages source et intermédiaire changent rarement (principalement les mêmes choses ), mais les rédacteurs du compilateur ajoutent toujours de nouvelles traductions et des améliorations ou optimisations de code (nouvelles opérations sur les choses). Plus généralement, la compilation et la traduction sont des "applications tueuses" pour les langages fonctionnels.

Norman Ramsey
la source
119
Il y a un sérieux zen derrière cette réponse. Je pense que cela illumine le fait que certains modèles de conception OOP (Visitor) sont en fait des hacks qui tentent de surmonter le problème de l'ajout de nouvelles opérations.
Jacobs Data Solutions
54
En JavaScript, vous pouvez avoir toutes les choses.
Erik Reppen du
61
@ErikReppen à quel moment la question se pose, quand choisissez-vous d'utiliser les fonctionnalités et quand choisissez-vous d'utiliser les fonctionnalités orientées objet?
Norman Ramsey
7
@NormanRamsey Il n'est pas du tout rare de le mélanger dans JS et les fonctions de première classe sont liées à de nombreuses fonctionnalités liées à JS OOP. Le tri de tableaux de JS prend les fonctions comme un argument qui peut produire des structures de données puissantes. Closures + une fonction passée est utilisée pour garder les objets jquery très légers en mémoire car la plupart des méthodes ne sont que des références. Etc ...
Erik Reppen
9
@NormanRamsey: Très bonne réponse, dans le sens du SICP. Selon cette classification, la programmation fonctionnelle et procédurale sont regroupées du côté opposé de la programmation orientée objet. Cela pourrait expliquer l'essor de la POO à la fin des années 80 et au début des années 90: lorsque les interfaces utilisateur graphiques sont devenues courantes, la POO s'est révélée être une bonne approche pour les modéliser parce que vous avez normalement un ensemble fixe d'opérations (peindre, ouvrir, fermer, redimensionner) et un nombre croissant de widgets. Bien sûr, cela ne signifie pas que la POO est meilleure que procédurale pour toute application, comme vous l'avez illustré.
Giorgio
177

Vous n'avez pas nécessairement à choisir entre les deux paradigmes. Vous pouvez écrire des logiciels avec une architecture OO en utilisant de nombreux concepts fonctionnels. FP et OOP sont de nature orthogonale .

Prenons par exemple C #. On pourrait dire qu'il s'agit principalement de POO, mais il existe de nombreux concepts et constructions FP. Si vous considérez Linq , les constructions les plus importantes qui permettent à Linq d'exister sont de nature fonctionnelle: les expressions lambda .

Un autre exemple, F #. On pourrait dire qu'il s'agit principalement de FP, mais il existe de nombreux concepts et constructions de POO disponibles. Vous pouvez définir des classes, des classes abstraites, des interfaces, gérer l'héritage. Vous pouvez même utiliser la mutabilité lorsqu'elle rend votre code plus clair ou lorsqu'elle augmente considérablement les performances.

De nombreuses langues modernes sont multi-paradigmes.

Lectures recommandées

Comme je suis dans le même bateau (formation OOP, apprentissage de la PF), je vous suggère quelques lectures que j'ai vraiment appréciées:

Bruno Reis
la source
8
@duffymo: votre commentaire, comme vous le dites, est surtout inutile. Personne ne veut une comparaison des langages, des machines virtuelles ou des plates-formes, merci.
Bruno Reis
6
@Bruno - une réponse à la "puissance de .NET". Se détendre.
duffymo
6
Drôle, je ne vous vois pas réprimander Dykam à propos de son commentaire inutile. Avez-vous été nommé modérateur alors que je ne regardais pas? Personne ne flamboie ici, sauf vous. Je le répète - détendez-vous.
duffymo
4
Hé, désolé si j'ai commencé à enflammer. Je ne voulais pas dire que les autres plates-formes sont moins puissantes, juste que .NET ne prend pas seulement en charge la POO. Par exemple, il a une optimisation des appels de queue.
Dykam
5
@nawfal, jusqu'à ce que vous puissiez pointer certaines caractéristiques intrinsèques dans les deux paradigmes et dire qu'elles sont incompatibles, elles sont orthogonales: c'est le cœur de la discussion. FP est incompatible avec la programmation impérative par définition, mais la POO n'est pas limitée à la programmation impérative. La raison pour laquelle nous avons des mots différents pour ces concepts est pour que nous puissions en parler: lorsque vous les regroupez, vous nous forcez à trouver inutilement de nouveaux mots.
DavidS
31

La programmation orientée objet offre:

  1. Encapsulation, à
    • contrôler la mutation de l'état interne
    • limiter le couplage à la représentation interne
  2. Sous-typage, permettant:
    • substitution de types compatibles (polymorphisme)
    • un moyen grossier de partager l'implémentation entre les classes (héritage d'implémentation)

La programmation fonctionnelle, dans Haskell ou même dans Scala, peut permettre la substitution par un mécanisme plus général des classes de types. L'état interne mutable est soit découragé, soit interdit. L'encapsulation de la représentation interne peut également être réalisée. Voir Haskell vs OOP pour une bonne comparaison.

L'affirmation de Norman selon laquelle «l'ajout d'un nouveau type de chose à un programme fonctionnel peut nécessiter la modification de nombreuses définitions de fonction pour ajouter un nouveau cas». dépend de la façon dont le code fonctionnel a utilisé les classes de type. Si la correspondance de motifs sur un type de données abstrait particulier est répartie dans une base de code, vous souffrirez en effet de ce problème, mais c'est peut-être une mauvaise conception pour commencer.

EDITED Suppression de la référence aux conversions implicites lors de la discussion des classes de type. Dans Scala, les classes de types sont codées avec des paramètres implicites, pas des conversions, bien que les conversions implicites soient un autre moyen de parvenir à la substitution de types compatibles.

2 tours
la source
3
Les classes de types ne sont pas un mécanisme de conversion implicite vers d'autres types. Ils sont une description d'un ensemble de fonctions définies pour un type afin de fournir une forme de polymorphisme. La chose la plus proche de la POO de style Java serait les interfaces, bien que les classes de types Haskell présentent des différences importantes.
Zak
25
  1. Si vous êtes dans un environnement fortement concurrent, une programmation fonctionnelle pure est utile. L'absence d'état mutable rend la concurrence presque insignifiante. Voir Erlang.

  2. Dans un langage multiparadigm, vous voudrez peut-être modéliser certaines choses fonctionnellement si l'existence d'un état mutable est un détail d'implémentation, et donc FP est un bon modèle pour le domaine problématique. Par exemple, consultez la liste des compréhensions en Python ou std.range dans le langage de programmation D. Ceux-ci s'inspirent de la programmation fonctionnelle.

dsimcha
la source