La programmation fonctionnelle ajoute-t-elle de la complexité au code? [fermé]


17

Pendant toute l'année écoulée, j'ai été écrit du code Scala (provenant d'un arrière-plan Java). J'ai vraiment aimé la façon dont vous pouvez créer du code plus simple et plus propre, avec des valeurs, des classes de cas, des fonctions map / filter / lambda, des implicits et l'inférence de type. Je l'ai utilisé principalement pour une application basée sur Akka .

Cette année, je suis sur un projet Scala avec une nouvelle équipe, qui aime vraiment la programmation fonctionnelle. Ils utilisent beaucoup Scalaz , et le code est rempli partout avec des applicatifs, des limites de contexte, une monade lecteur / écrivain / état, même la méthode principale est "enveloppée" dans une monade d'E / S. Leur raisonnement est que cela fait que le compilateur "travaille pour nous" en affirmant que le code est correct et que chaque fonction est exempte d'effets secondaires.

Malgré tout, de mon point de vue, toute cette syntaxe gêne vraiment la logique métier. Par exemple, un type de "MyBusinessObject" est très bien, ainsi que des types comme "List [MyBusinessObject]", "Option [MyBusinessObject]" ou même "Future [MyBusinessObject]". Ils ont tous un sens et un objectif clairs. D'un autre côté, un code comme:

def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}

cela ajoute-t-il de la complexité au programme, ou est-ce juste moi que je n'ai pas l'habitude de cette façon de programmer?


6
Quelle est votre question objectivement répondable?
Deer Hunter

1
On dirait que cela conduit à une tonne de code avec des noms de variables à une ou deux lettres. On dirait un peu APL. Ce n'est pas un complément.
user949300

3
J'ai commencé à jouer avec Haskell l'année dernière. Il avait l' air incroyablement complexe à l'époque, quand je ne comprenais pas des concepts comme curryfication, foncteurs, monades, etc .. Haskell est similaire à Scalaz en ce sens qu'elle a beaucoup de court, les fonctions symboliques, comme >>=et <$>qui ne voudraient rien dire jusqu'à ce que vous savent ce qu'ils font. Après avoir appris ce qu'ils signifient, cependant, ils m'ont lu très naturellement et rapidement maintenant. Pas vraiment une réponse, juste mon expérience objective avec des choses comme ça. J'utilise également Scala, mais je n'ai aucune expérience avec la bibliothèque Scalaz.
KChaloux

3
Vous n'êtes tout simplement pas familier avec les idiomes. @ Les variables courtes user949300 ne sont pas vraiment un problème pour beaucoup de code fonctionnel (pensez aux conventions de style mathématique!). Lisez également le blog de Tony Morris pour une discussion plus approfondie de ce qui transmet le mieux le sens, les types ou les noms de variables verbeux.
Andres F.

3
@ user949300: les noms de variables courts sont préférés localement, c'est la même chose dans les mondes fonctionnels et impératifs (vous n'écririez pas for(i=0; i<7; ++i) { trivialOperation(i); }avec une trivialOperationCountvariable maladroite , n'est-ce pas?) 'écrirais simplement les appels de méthode d'accesseur en OO. Le résultat est généralement plus concis; peut-être un peu moins explicite, mais la recherche de la déclaration de données le rend normalement clair rapidement. La saisie statique aide beaucoup, ce n'est pas comme dans APL.
leftaroundabout

Réponses:


37

Cela n'a rien à voir avec la programmation fonctionnelle - vous pouvez trouver ce genre de situation dans le contexte de tout autre langage de programmation - les développeurs qui aiment tellement les constructions avancées de "leur" langage qu'ils ignorent tout bon sens sur la lisibilité et la simplicité. J'ai rencontré une telle situation en C, C ++, Perl, Java, C #, Basic et d'autres langages non fonctionnels. Ce n'est pas la programmation fonctionnelle qui ajoute de la complexité au code - les programmeurs le font.

Ne vous méprenez pas, je ne recommande pas d'éviter les fonctionnalités avancées du langage - mais il est important de trouver le bon équilibre dans le contexte donné. Lorsque vous écrivez une bibliothèque générique pour plus de 100 000 développeurs à travers le monde, il existe différentes mesures à appliquer comme lorsque vous écrivez un générateur de rapport individuel uniquement pour votre bureau local.


7
Cela a aussi beaucoup à voir avec la communauté. Pour un développeur avec une expérience Java ou C #, le code est à peine compréhensible (et sa communauté ne le comprendrait pas non plus). Mais si vous écrivez Haskell, par exemple, et que vous n'utilisez pas de monades, d'applicatifs, de foncteurs et ainsi de suite, vous déroutez la communauté de cette langue. La «naturalité» du code n'est pas inhérente, mais relative à sa communauté et à ses pratiques établies.
Andres F.

1
C'est difficile à voir parce que la plupart d'entre nous viennent de milieux impératifs, ce qui nous conduit parfois à faire de fausses hypothèses sur ce qui est naturel.
Andres F.

il suffit de regarder la bibliothèque SLT C ++, qui pourrait être écrite pour être beaucoup plus lisible pour l'amateur
ratchet freak

@ratchetfreak: Je suppose que vous voulez dire STL. Je pense que c'est un très bon exemple (et en effet, je pensais à cela dans ma réponse). L'utilisation de la méta-programmation de modèles a beaucoup de sens lorsque vous êtes un programmeur STL, car elle rend la STL plus réutilisable. Et les personnes devant maintenir ce code sont normalement utilisées pour créer des modèles de métaprogrammation. L'utilisation d'une métaprogrammation de modèle à la manière d'une STL dans votre application commerciale standard peut facilement conduire à un code trop compliqué et difficile à maintenir. On peut sûrement trouver des cas (rares) où le TMP est bien même dans une application commerciale, bien sûr.
Doc Brown

@DocBrown ouais la dyslexie est apparue au mauvais moment, mais honnêtement, si j'avais la moitié de l'esprit (et beaucoup plus de temps que maintenant), je pourrais réécrire de nombreux corps de fonctions pour être beaucoup plus lisible.
ratchet freak

7

Je dirais que vous n'êtes pas habitué à la façon dont ils codent fait au moins partie de l'image. Je suis dans une situation similaire à la vôtre (venant de C # en F # et travaillant avec des personnes ayant des antécédents Haskell), et même si je trouve que c'est une expérience intéressante, j'ai des moments où je me tape la tête contre le mur, démêlant un en particulier la composition de fonction sans point alambiqué juste pour avoir une idée de ce qui se passe là-bas. C'est une chose culturelle.

Quant à savoir si ce code particulier ajoute de la complexité au programme - je ne sais pas. Convenu qu'un morceau générique de code peut être lui-même complexe. Mais c'est un utilitaire, pas une partie de la logique métier. Si vous voulez savoir si cela rend la base de code plus complexe ou plus simple, vous devez imaginer à quoi elle devrait ressembler sans ce morceau de code. C'est souvent le cas avec des constructions génériques telles qu'elles sont elles-mêmes complexes, mais c'est une complexité que vous pouvez adapter sur un seul écran. En même temps, ils rendent la base de code entière un peu plus simple. C'est particulièrement le cas des monades.

Là encore, il peut également s'agir d'un `` art pour l'art '', comme le suggère @Doc Brown. Je ne peux pas non plus l'exclure.


5

Je dirais que dans la programmation fonctionnelle générale réduit la complexité en éliminant l'état mutable, réduisant ainsi le nombre de cas qui doivent être pris en compte lors de la tentative de comprendre le fonctionnement d'une section de code.

Cependant, la programmation fonctionnelle rend possible des degrés d'abstraction plus élevés, et bien que le code hautement abstrait puisse être extrêmement utile, il peut également être difficile à comprendre car il est par définition séparé du contexte que vous utiliseriez habituellement pour guider votre compréhension. Votre commentaire "Ils ont tous un sens et un objectif clairs" sur les objets métier est sans aucun doute vrai, mais reflète vraiment le fait que cette logique est très spécifique à un besoin et à un contexte que vous comprenez déjà. L'existence d'une construction comme Monad vous permet de faire quelque chose de très utile avec peu d'effort, mais le Web est jonché de pages essayant d'expliquer ce qu'est une Monade. C'est de l'abstraction pour vous.

De plus, Scalaz a été écrit par des gens qui mangeaient et respiraient la PF depuis longtemps; ils voulaient apporter des fonctionnalités disponibles dans Haskell à Scala. Ce faisant, ils n'ont pas cherché à être pédagogiques. Scalaz utilise un vocabulaire et un style qui semblent clairs et simples aux auteurs mais étrangers aux non-initiés. Les méthodes qui sont déroutantes pour le reste d'entre nous semblaient si évidentes pour les auteurs, étant donné leurs antécédents Haskell, qu'elles ne justifiaient même pas un commentaire.

De plus, en tant que langage de programmation fonctionnel, Scala présente certaines lacunes (en partie parce que la JVM a des défauts) qui ont forcé les auteurs de Scalaz à écrire du code plus laid dans certains cas. Par exemple, l'absence d'élimination générale des appels de queue force l'utilisation de trampolines dans certains codes, et l'absence d'un "système type" peut compliquer les signatures de type.

Et enfin, Scalaz fait grand usage de lui-même. Cela pourrait être considéré comme un signe de sa puissance, mais pour les non-initiés, cela peut faire de la source un casse-tête - tout morceau de code aléatoire que vous regardez est susceptible d'utiliser quelque chose d'autre qui vous semble étranger.

Accrochez-vous. Et cela pourrait aider.


-4

Est-ce que cela ajoute de la complexité au programme, ou est-ce simplement que vous n'êtes pas habitué à ce mode de programmation?

Pourquoi pensez-vous que ces possibilités ne sont pas la même chose?

Un code bien écrit peut être lu par des personnes qui ne connaissent pas le langage de programmation spécifique. Certains langages (BASIC, Pascal, etc.) peuvent être lus et compris par des écoliers qui n'ont jamais vu de langages de programmation auparavant.

Si quelqu'un qui a de l'expérience avec d'autres langues et de l'expérience avec Scala (et qui je suppose a travaillé avec Scalaz pendant au moins une semaine et a des collègues pour expliquer les choses les plus délicates) est toujours confus; c'est la preuve qu'il a ajouté de la complexité.


11
Ce n'est tout simplement pas vrai:"Well written code can be read by people who aren't familiar with the specific programming language."
Andres F.

@Andres: C'est vrai ... jusqu'à un certain point. Un code bien écrit séparera la logique métier des détails d'implémentation, et la logique métier devrait être lisible, car la plupart de ce qu'il fait consiste à appeler directement des fonctions d'assistance bien nommées. Bien entendu, ces assistants peuvent utiliser toutes sortes de fonctionnalités linguistiques et nécessitent une solide expérience de la langue et des bibliothèques pour comprendre.
Ben Voigt

4
Je crois que ce qui suit est idiomatiques APL: x[⍋x←6?40]. Que pensez-vous que cela fait? Je n'aurais sûrement pas su…
bdesham

3
@Brendan Seulement dans le même paradigme (et même alors, parfois non). Par exemple, Prolog, Java et APL sont si différents que je dirais que si vous ne connaissez qu'un seul de ceux-ci (et pas d'autres langues), vous ne pouvez pas lire les deux autres, peu importe la façon dont vous connaissez le premier. (Sérieusement, dans l'exemple de bdesham, comment diable êtes-vous censé interpréter "arbre de Noël" si vous ne connaissez aucun APL?)
Izkata

1
Brendan, votre définition de bien écrit n'est pas standard. Bien écrit est toujours relatif à la langue et à sa communauté. Un programme en langage X est bien écrit s'il n'est pas buggé, c'est efficace et clair ... pour le public donné! Cela s'applique à la langue écrite en général, soit dit en passant: sachez toujours votre public. Ce qui convient (par exemple) à un article scientifique ne convient probablement pas à un e-mail à votre maman.
Andres F.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.