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?
la source
>>=
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.for(i=0; i<7; ++i) { trivialOperation(i); }
avec unetrivialOperationCount
variable 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.Réponses:
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.
la source
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.
la source
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.
la source
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é.
la source
"Well written code can be read by people who aren't familiar with the specific programming language."
x[⍋x←6?40]
. Que pensez-vous que cela fait? Je n'aurais sûrement pas su…