Lisibilité de la programmation fonctionnelle [fermé]


13

Je suis curieux de cela parce que je me souviens avant d'apprendre des langages fonctionnels, je les pensais tous horriblement, terriblement, terriblement illisibles. Maintenant que je connais Haskell et f #, je trouve qu'il faut un peu plus de temps pour lire moins de code, mais ce petit code fait bien plus qu'un montant équivalent dans un langage impératif, donc cela ressemble à un gain net et je ne suis pas extrêmement pratiqué en fonctionnel.

Voici ma question, j'entends constamment des gens de la POO que le style fonctionnel est terriblement illisible. Je suis curieux de savoir si tel est le cas et que je me fais des illusions, ou s'ils ont pris le temps d'apprendre un langage fonctionnel, l'ensemble du style ne serait plus plus illisible que la POO?

Quelqu'un a-t-il vu des preuves ou obtenu des anecdotes où il a vu cela aller d'une manière ou d'une autre avec une fréquence suffisante pour éventuellement le dire? Si l'écriture fonctionnelle est vraiment de moindre lisibilité, je ne veux pas continuer à l'utiliser, mais je ne sais vraiment pas si c'est le cas ou non ..


1
Je me souviens avoir regardé le code de "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/nario quand je connaissais à peine quoi que ce soit sur la programmation fonctionnelle et je me souviens avoir pensé 'Wow. Cela semble vraiment lisible '
WuHoUnited



3
@BlackICE linq et lambdas sont loin de définir la "programmation fonctionnelle". La programmation fonctionnelle implique le plus souvent des systèmes de types car lorsque vous commencez à reconnaître des fonctions comme types plutôt que simplement des objets / classes / enregistrements comme types, vous vous retrouvez avec beaucoup de nouvelles capacités et techniques. Les expressions LINQ et Lambda (ou la liste des fonctions monade et d'ordre supérieur) ne sont que deux techniques résultantes spécifiques, parmi lesquelles il existe de nombreuses autres.
Jimmy Hoffa

Réponses:


15

La lisibilité du code est très subjective . Pour cette raison, différentes personnes considéreraient le même code comme lisible ou illisible.

Une affectation, x = x + 1semble étrange pour un mathématicien, car une affectation ressemble de manière trompeuse à une comparaison.

Un modèle de conception simple de POO serait totalement flou pour quelqu'un qui ne connaît pas ces modèles. Considérez singleton . Quelqu'un demanderait "Pourquoi ai-je besoin d'un constructeur privé? Quelle est la mystérieuse méthode getInstance() ? Pourquoi ne faisons-nous pas une variable globale et n'y assignons-nous pas un objet?"

Il en va de même pour un code FP. À moins que vous ne connaissiez les schémas logiques dans les coulisses, il sera très difficile même de comprendre quelque chose de très basique, par exemple comment passer une fonction comme argument à une autre fonction.

Cela dit, il faut comprendre que la PF n'est pas une solution miracle. Il existe de nombreuses applications où FP serait difficile à appliquer et, par conséquent, cela conduira à un code plus lisible .


Les gens devraient créer quelque chose qui leur ressemble (l'humanité). Par exemple, même en vision par ordinateur, nous avons maintenant des réseaux de neurones. Le corps humain se compose d'objets, d'attributs, de méthodes et nous décrivons d'autres choses à l'aide d'objets, d'attributs, de méthodes. La programmation fonctionnelle n'a donc aucun sens
user25

12

Réponse courte:

Un des éléments qui font dire que le code de programmation fonctionnel est difficile à lire est qu'il donne la préférence à une syntaxe plus compacte.

Longue réponse:

La programmation fonctionnelle elle-même ne peut pas être lisible ou illisible, car c'est un paradigme, pas un style d'écriture de code. En C # par exemple, la programmation fonctionnelle ressemble à:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

et serait considéré comme lisible par toute personne ayant suffisamment d'expérience en Java, C # ou langages similaires.

La syntaxe du langage, d'autre part, est plus compacte pour de nombreux langages fonctionnels (y compris Haskell et F #) par rapport aux langages OOP populaires, donnant une préférence aux symboles plutôt qu'aux mots en anglais simple.

Cela s'applique également aux langues en dehors de la PF. Si vous comparez les langages OOP populaires à d'autres moins populaires qui ont tendance à utiliser plus de mots anglais, les derniers se sentiraient plus faciles à comprendre pour les personnes sans expérience en programmation.

Comparer:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

à:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

De la même manière:

var a = ((b - c) in 1..n) ? d : 0;

pourrait s'exprimer dans un langage imaginaire comme:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

Quand une syntaxe plus courte est meilleure?

Alors qu'une syntaxe plus verbeuse est plus facile à comprendre pour un débutant, une syntaxe plus compacte est plus facile pour les développeurs expérimentés. Un code plus court signifie moins de caractères à taper, ce qui signifie plus de productivité.

Surtout, cela n'a vraiment aucun sens d'obliger une personne à taper un mot-clé pour indiquer quelque chose qui peut être déduit de la syntaxe.

Exemples:

  • En PHP, vous devez taper functionavant chaque fonction ou méthode, sans raison particulière de le faire.

  • Ada m'a toujours horrifié d'avoir forcé les développeurs à taper beaucoup de mots anglais, d'autant plus qu'il n'y a pas d'IDE correct avec auto-complétion. Je n'ai pas utilisé Ada récemment et leur tutoriel officiel est en panne donc je ne peux pas donner d'exemple; si quelqu'un a un exemple, n'hésitez pas à modifier ma réponse.

  • La syntaxe 1..n, utilisée dans de nombreux FP (et Matlab), pourrait être remplacée par between 1, nou between 1 and nou between (1, n). Le betweenmot-clé le rend beaucoup plus facile à comprendre pour les personnes qui ne connaissent pas la syntaxe du langage, mais néanmoins, deux points sont beaucoup plus rapides à taper.


8
Je suis d'accord avec le sentiment, mais pour différentes raisons. Il ne s'agit pas de la facilité avec laquelle un expert peut écrire du code, car le code est généralement lu beaucoup plus souvent qu'il n'est écrit. Un code plus court peut également aider à la lisibilité, en ne perdant pas de temps précieux, d'espace d'écran et de capacité mentale si quelque chose était déjà évident à partir d'un indicateur plus court (par exemple, les nouvelles lignes au lieu des points-virgules, les deux coïncidences de toute façon). Cela peut également faire mal quand il devient trop cryptique (par exemple, je préfère for x in xsplus for x xs, car cela m'aide à distinguer la variable de boucle et le conteneur).

Beaucoup de gens que je trouve se plaignent de FP se plaignent également de l'extrait C # que vous avez listé comme vous l'avez dit, c'est aussi un exemple de FP. C'est peut-être plus un problème pour mes collègues que la lisibilité si la plupart des gens OOP trouvent cet extrait lisible, bien que je ne sois pas complètement convaincu que la plupart des gens OOP le fassent de mes expériences .. c'est pourquoi je ne suis pas si sûr de ce sujet.
Jimmy Hoffa

@Jimmy Hoffa: Voir programmers.stackexchange.com/a/158721/6605 où je discute exactement l'extrait C # et comment il est perçu par les programmeurs débutants.
Arseni Mourzenko

1
@Sergiy: en Java ou C #, une signature de méthode ne contient pas de methodmot - clé. Exemple: public int ComputePrice(Product product). L'ajout d'un tel mot-clé, comme ce que PHP a fait, ajoute simplement de l'encombrement au lieu de faciliter la lecture. Si un programmeur est incapable de comprendre qu'une fonction est une fonction de sa signature, soit ce programmeur n'a aucune expérience, soit le code est beaucoup plus illisible que le pire code pièce que j'ai jamais vu.
Arseni Mourzenko

1
@Sergiy: il y a des cas où la verbosité peut aider (sinon, nous verrions des langages et du code comme p i ComputePrice(product): _.unitPrice * ~.cart[_]), mais certaines langues vont trop loin. L'exemple du functionmot clé redondant en PHP est un bon exemple.
Arseni Mourzenko du

6

Je pense que l'une des raisons est que la programmation fonctionnelle a tendance à fonctionner avec des concepts beaucoup plus abstraits. Cela rend le code plus court et plus lisible pour les personnes qui connaissent et comprennent les concepts (car ils expriment bien l'essence du problème), mais il est illisible pour les personnes qui ne les connaissent pas.

Par exemple, pour un programmeur fonctionnel, il est naturel d'écrire un code qui peut échouer à différents points de la Maybemonade ou de la Eithermonade. Ou, pour écrire un calcul avec état à l'aide de la Statemonade. Mais pour quelqu'un qui ne comprend pas le concept des monades, tout cela ressemble à une sorte de sorcellerie noire.

Je pense donc qu'il serait raisonnable d'utiliser des morceaux de programmation fonctionnelle même dans une équipe de personnes OOP, tant que l'on utilise des concepts faciles à comprendre ou à apprendre, comme le mappage d'une collection avec une fonction ou des fermetures .

(Et bien sûr, cela dépend aussi du programmeur qui a écrit un morceau de code. Vous pouvez écrire du code horriblement illisible dans n'importe quelle langue, ainsi que vous pouvez écrire dans un style agréable et propre.)


2

La lisibilité n'a rien à voir avec les paradigmes, les modèles et autres. Plus le code reflète la sémantique de votre domaine problématique, plus il utilise une terminologie et des idiomes d'un tel domaine problématique, plus il est lisible.

C'est la raison pour laquelle le code POO n'est pas du tout lisible: pas beaucoup de problèmes du monde réel sont naturellement exprimés en termes de taxonomies hiérarchiques. Les objets qui se transmettent des messages est un concept étrange et très éloigné de tout ce qui est "réel". Étonnamment, il existe bien plus de concepts du monde réel qui peuvent être naturellement associés aux idiomes fonctionnels. Les problèmes ont tendance à être définis de manière déclarative, donc une solution déclarative est plus naturelle.

Bien qu'il existe de nombreuses autres sémantiques qui pourraient être plus proches du monde réel qu'un pur fonctionnel, purement POO, pur flux de données ou pur quoi que ce soit. Et de ce fait, une approche orientée langage de résolution de problèmes produit le code le plus lisible, battant tous les paradigmes "purs" existants. Avec les langages spécifiques au domaine, chaque problème est exprimé dans sa propre terminologie naturelle. Et les langages fonctionnels sont légèrement meilleurs que les trucs OOP traditionnels pour faciliter la mise en œuvre des DSL (bien que de bien meilleures approches soient disponibles).


1

La lisibilité du code est subjective. Je suis sûr que certaines personnes le critiquent par manque de compréhension. Il existe naturellement des idiomes différents dans la façon dont les modèles communs sont mis en œuvre. Par exemple, le modèle Visitor n'a pas vraiment de sens dans une langue avec correspondance de modèle .

L'inférence de type peut être une fonction délicate. Habituellement, c'est un excellent accélérateur de développement, cependant, il peut parfois être difficile de comprendre quels types sont impliqués en raison du manque de contexte conduisant à des erreurs confuses. Cela ne se limite pas à quels langages de programmation fonctionnelle - je l'ai vu aussi dans les modèles C ++!

Les langues modernes ont tendance à être multi-paradigmes . Cela inclut à la fois C # et F #. Il est possible d'écrire un style fonctionnel en C # et un style impératif en F #. Les mêmes personnes qui critiquent les langages fonctionnels écrivent probablement du code fonctionnel dans leur langage orienté objet.

Le développement commercial dans les langages fonctionnels est encore relativement immature. J'ai vu un certain nombre d'erreurs commises qui seraient considérées comme une mauvaise forme dans n'importe quelle langue. Tel que:

  1. Changement de style à mesure que vous apprenez la langue (et non refactorisation) conduisant à des incohérences.
  2. Trop dans un seul fichier.
  3. Trop de déclarations sur une seule ligne.

Concernant les erreurs, j'ajouterais également: 4. Surutilisation des symboles, par exemple: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Caractéristiques implicites: déclarations / mots-clés / déclarations facultatifs, conversions implicites, etc.;
Sergiy Sokolenko
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.