Funktionale Programmierbarkeit [geschlossen]

13

Ich bin neugierig, weil ich mich erinnere, bevor ich funktionierende Sprachen lernte, fand ich sie alle schrecklich, schrecklich, schrecklich unlesbar. Jetzt, da ich Haskell und f # kenne, dauert es etwas länger, weniger Code zu lesen, aber dieser kleine Code ist weit mehr als eine entsprechende Menge in einer imperativen Sprache. Es fühlt sich also wie ein Nettogewinn an und ich bin nicht extrem in funktionalen geübt.

Hier ist meine Frage, ich höre ständig von OOP-Leuten, dass funktionaler Stil schrecklich unlesbar ist. Ich bin neugierig, ob dies der Fall ist und ich mich selbst täusche, oder ob sie sich die Zeit genommen haben, eine funktionale Sprache zu lernen, der ganze Stil wäre nicht länger unleserlicher als OOP?

Hat jemand irgendwelche Beweise gesehen oder Anekdoten bekommen, bei denen sie sahen, dass dies in die eine oder andere Richtung ging, mit der Häufigkeit, die sie möglicherweise sagen könnten? Wenn das funktionale Schreiben wirklich schlechter lesbar ist, möchte ich es nicht weiter verwenden, aber ich weiß wirklich nicht, ob das der Fall ist oder nicht.

Jimmy Hoffa
quelle
1
Ich erinnere mich an den Code für "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/nario, als ich kaum etwas über funktionale Programmierung wusste, und erinnere mich, dass ich "Wow" gedacht habe. Dies scheint wirklich lesbar '
WuHoUnited
3
@BlackICE Linq und Lambdas sind weit davon entfernt, "funktionale Programmierung" zu definieren. Bei der funktionalen Programmierung handelt es sich häufig um Typsysteme, denn wenn Sie beginnen, Funktionen als Typen zu erkennen, anstatt nur Objekte / Klassen / Datensätze als Typen, werden Sie mit einer Vielzahl neuer Fähigkeiten und Techniken konfrontiert. LINQ- und Lambda-Ausdrücke (oder die Funktionen der Listenmonade und höherer Ordnung) sind nur zwei spezifische resultierende Techniken, von denen es viele mehr gibt.
Jimmy Hoffa

Antworten:

15

Die Lesbarkeit des Codes ist sehr subjektiv . Aus diesem Grund betrachten verschiedene Personen denselben Code als lesbar oder nicht lesbar.

Eine Zuweisung, x = x + 1 klingt für einen Mathematiker seltsam, weil eine Aufgabe einem Vergleich irreführend ähnlich sieht.

Ein einfaches OOP-Entwurfsmuster wäre für jemanden, der mit diesen Mustern nicht vertraut ist, völlig unklar. Betrachten Sie Singleton . Jemand fragte: "Warum brauche ich einen privaten Konstruktor? Was ist die mysteriöse Methode? getInstance() ? Warum erstellen wir keine globale Variable und weisen dort ein Objekt zu?"

Gleiches gilt für einen FP-Code. Es sei denn, Sie kennen die logischen Muster hinter den Kulissen , wird es sehr schwierig sein, etwas sehr Grundlegendes zu verstehen, z. B. wie man eine Funktion als Argument an eine andere Funktion übergibt.

Vor diesem Hintergrund sollte man verstehen, dass FP keine Wunderwaffe ist. Es gibt viele Anwendungen, bei denen die Anwendung von FP schwierig ist und daher zu einem schlechter lesbaren Code führt .

Bytebuster
quelle
Menschen sollten etwas erschaffen, das sich selbst ähnlich ist (Menschlichkeit). ZB haben wir jetzt sogar in der Computer Vision neuronale Netze. Der menschliche Körper besteht aus Objekten, Attributen, Methoden und wir beschreiben andere Dinge mit Objekten, Attributen, Methoden. Funktionale Programmierung macht also keinen Sinn
user25 30.12.18
12

Kurze Antwort:

Eines der Elemente, die die Leute sagen lassen, dass funktionaler Programmcode schwer zu lesen ist, ist die Bevorzugung einer kompakteren Syntax.

Lange Antwort:

Die funktionale Programmierung selbst kann nicht lesbar oder unlesbar sein, da es sich um ein Paradigma handelt und nicht um eine Art, Code zu schreiben. In C # sieht die funktionale Programmierung beispielsweise folgendermaßen aus:

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)));

und wird von jeder Person mit ausreichender Erfahrung in Java, C # oder ähnlichen Sprachen als lesbar angesehen.

Die Sprachsyntax hingegen ist für viele funktionale Sprachen (einschließlich Haskell und F #) kompakter als für gängige OOP-Sprachen, da Symbole anstelle von Wörtern in einfachem Englisch bevorzugt werden.

Dies gilt auch für Sprachen außerhalb von FP. Wenn Sie die gängigen OOP-Sprachen mit einigen weniger gängigen vergleichen, bei denen in der Regel mehr englische Wörter verwendet werden, fühlen sich die letzten für Personen ohne Programmiererfahrung leichter verständlich.

Vergleichen Sie:

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;
}

zu:

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;
}

Auf die gleiche Weise:

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

könnte in einer imaginären Sprache ausgedrückt werden als:

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

Wann ist kürzere Syntax besser?

Während eine ausführlichere Syntax für Anfänger einfacher zu verstehen ist, ist eine kompaktere Syntax für erfahrene Entwickler einfacher. Kürzere Codes bedeuten, dass weniger Zeichen eingegeben werden müssen, was eine höhere Produktivität bedeutet.

Insbesondere ist es nicht sinnvoll, eine Person dazu zu zwingen, ein Schlüsselwort einzugeben, um auf etwas hinzuweisen, das aus der Syntax abgeleitet werden kann.

Beispiele:

  • In PHP müssen Sie functionvor jeder Funktion oder Methode etwas eingeben, ohne einen bestimmten Grund dafür anzugeben.

  • Ada hat mich immer entsetzt, weil ich die Entwickler gezwungen habe, viele englische Wörter einzugeben, zumal es keine richtige IDE mit automatischer Vervollständigung gibt. Ich habe Ada in letzter Zeit nicht benutzt und ihr offizielles Tutorial ist nicht verfügbar, daher kann ich kein Beispiel nennen. Wenn jemand ein Beispiel hat, können Sie meine Antwort jederzeit ändern.

  • Die 1..nin vielen FP (und Matlab) verwendete Syntax könnte durch between 1, noder between 1 and noder ersetzt werden between (1, n). Das betweenSchlüsselwort erleichtert das Verständnis für Personen, die mit der Sprachsyntax nicht vertraut sind. Dennoch lassen sich zwei Punkte viel schneller eingeben.

Arseni Mourzenko
quelle
8
Ich stimme dem Gefühl zu, aber aus verschiedenen Gründen. Es geht nicht darum, wie einfach ein Experte Code schreiben kann, da Code in der Regel weitaus häufiger gelesen wird als geschrieben. Kürzere Codes können auch die Lesbarkeit verbessern, indem sie keine kostbare Zeit, keinen Platz auf dem Bildschirm und keine mentale Kapazität verschwenden, wenn anhand eines kürzeren Indikators bereits etwas offensichtlich wäre (z. B. Zeilenumbrüche anstelle von Semikolons, die beiden sind ohnehin Zufälle). Es kann auch schaden , wenn es wird zu kryptisch (zum Beispiel, ziehe ich for x in xsüber for x xs, weil es mir Schleifenvariable zu unterscheiden hilft und Container).
Viele der Leute, die sich über FP beschweren, beklagen sich auch über das C # -Snippet, das Sie, wie Sie sagten, aufgelistet haben. Es ist auch ein Beispiel für FP. Vielleicht ist dies eher ein Problem meiner Kollegen als die Lesbarkeit, wenn die meisten OOP-Benutzer dieses Snippet als lesbar empfinden, obwohl ich nicht ganz davon überzeugt bin, dass die meisten OOP-Benutzer dies aufgrund meiner Erfahrungen tun.
Jimmy Hoffa
@ Jimmy Hoffa: Siehe programmers.stackexchange.com/a/158721/6605, wo ich genau das C # -Snippet diskutiere und wie es von Anfänger-Programmierern wahrgenommen wird.
Arseni Mourzenko
1
@Sergiy: In Java oder C # enthält eine Methodensignatur kein methodSchlüsselwort. Beispiel: public int ComputePrice(Product product). Das Hinzufügen eines solchen Schlüsselworts, wie es PHP getan hat, fügt lediglich Unordnung hinzu, anstatt die Lesbarkeit zu verbessern. Wenn ein Programmierer nicht verstehen kann, dass eine Funktion eine Funktion aus ihrer Signatur ist, hat dieser Programmierer entweder keinerlei Erfahrung oder der Code ist viel unleserlicher als der schlechteste Stückcode, den ich je gesehen habe.
Arseni Mourzenko
1
@Sergiy: Es gibt Fälle, in denen Ausführlichkeit hilfreich sein kann (ansonsten sehen wir Sprachen und Code wie p i ComputePrice(product): _.unitPrice * ~.cart[_]), aber einige Sprachen gehen zu weit. Das Beispiel des redundanten functionSchlüsselworts in PHP ist ein gutes Beispiel.
Arseni Mourzenko
6

Ich denke, einer der Gründe ist, dass funktionale Programmierung dazu neigt, mit viel abstrakteren Konzepten zu arbeiten. Dies macht Code kürzer und besser lesbar für Leute, die die Konzepte kennen und verstehen (weil sie das Wesentliche des Problems treffend zum Ausdruck bringen), aber es ist nicht lesbar für Leute, die mit ihnen nicht vertraut sind.

Beispielsweise ist es für einen funktionalen Programmierer selbstverständlich, einen Code zu schreiben, der an verschiedenen Stellen innerhalb der MaybeMonade oder EitherMonade fehlschlagen kann . Oder um mit Hilfe der StateMonade eine zustandsbezogene Berechnung zu schreiben . Aber für jemanden, der das Konzept der Monaden nicht versteht, scheint dies alles eine Art schwarze Zauberei zu sein.

Also ich denke , es sinnvoll sein würde Bits der funktionalen Programmierung zu verwenden , selbst in einem Team von OOP Menschen, so lange wie ein Nutzungskonzept , die einfach zu verstehen sind oder zu lernen, wie Mapping über eine Sammlung mit einer Funktion oder Verschlüssen .

(Und natürlich hängt es auch von dem Programmierer ab, der einen Teil des Codes geschrieben hat. Sie können schrecklich unlesbaren Code in jeder Sprache schreiben und Sie können in einem schönen und sauberen Stil schreiben.)

Petr Pudlák
quelle
2

Die Lesbarkeit hat nichts mit den Paradigmen, Modellen und dergleichen zu tun. Je mehr Code die Semantik Ihrer Problemdomäne widerspiegelt, desto besser lesbar ist die Terminologie und die Redewendungen einer solchen Problemdomäne.

Dies ist der Grund, warum OOP-Code überhaupt nicht so gut lesbar ist: Nicht viele Probleme der realen Welt werden natürlich in Form hierarchischer Taxonomien ausgedrückt. Objekte, die sich gegenseitig Nachrichten übermitteln, sind ein seltsames Konzept, und es ist weit entfernt von allem, was "real" ist. Überraschenderweise gibt es viel mehr Konzepte der realen Welt, die auf natürliche Weise auf die funktionalen Redewendungen abgebildet werden können. Probleme werden in der Regel deklarativ definiert, daher ist eine deklarative Lösung natürlicher.

Obwohl es viele andere Semantiken gibt, die der realen Welt näher sein könnten als ein rein funktionales, reines OOP, ein reiner Datenfluss oder was auch immer. Aufgrund dieser Tatsache liefert ein sprachorientierter Ansatz zur Problemlösung den lesbarsten Code, der alle vorhandenen "reinen" Paradigmen übertrifft. Bei den domänenspezifischen Sprachen wird jedes Problem in einer eigenen natürlichen Terminologie ausgedrückt. Und funktionale Sprachen sind bei der Erleichterung der DSL-Implementierung etwas besser als das OOP-Mainstream-Zeug (obwohl viel bessere Ansätze verfügbar sind).

SK-Logik
quelle
1

Die Lesbarkeit des Codes ist subjektiv. Ich bin sicher, dass manche Leute es wegen Unverständnis kritisieren. Es gibt natürlich unterschiedliche Redewendungen in der Art und Weise, wie gemeinsame Muster implementiert werden. Zum Beispiel ist das Besuchermuster in einer Sprache mit Mustervergleich nicht wirklich sinnvoll .

Typinferenz kann eine schwierige Funktion sein. In der Regel ist dies ein großer Entwicklungsbeschleuniger. Es kann jedoch manchmal schwierig sein, herauszufinden, um welche Typen es sich handelt, da der Kontext nicht ausreicht, um verwirrende Fehler zu verursachen. Dies ist nicht auf die funktionalen Programmiersprachen beschränkt - ich habe es auch in C ++ - Vorlagen gesehen!

Moderne Sprachen sind in der Regel ein Multiparadigma . Dies schließt sowohl C # als auch F # ein. Es ist möglich, einen funktionalen Stil in C # und einen imperativen Stil in F # zu schreiben. Die gleichen Leute, die funktionale Sprachen kritisieren, schreiben wahrscheinlich funktionalen Code in ihrer objektorientierten Sprache.

Die kommerzielle Entwicklung in funktionalen Sprachen ist noch relativ unausgereift. Ich habe eine Reihe von Fehlern gesehen, die in jeder Sprache als schlecht empfunden werden. Sowie:

  1. Ändern Sie den Stil, während Sie die Sprache lernen (und nicht umgestalten), was zu Inkonsistenzen führt.
  2. Zu viel in einer Datei.
  3. Zu viele Anweisungen in einer Zeile.
Dave Hillier
quelle
Zu Fehlern möchte ich noch hinzufügen: 4. Übermäßiger Gebrauch von Symbolen, zB: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Implizite Merkmale: optionale Deklarationen / Schlüsselwörter / Anweisungen, implizite Konvertierungen usw .;
Sergiy Sokolenko