Funktionale Programmierung vs objektorientierte Programmierung [geschlossen]

784

Ich war bisher hauptsächlich mit OO-Programmierung vertraut und freue mich darauf, eine funktionale Sprache zu lernen. Meine Fragen sind:

  • Wann wählen Sie funktionale Programmierung gegenüber objektorientiert?
  • Was sind die typischen Problemdefinitionen, bei denen funktionale Programmierung die bessere Wahl ist?
Olivier Lalonde
quelle
Dies ist relevant programmers.stackexchange.com/questions/9730/…
kirill_igum
1
ähnliche Frage cs.se schloss auch, was Beispiel ist, wo funktionale Programmierung bessere Ergebnisse liefert als imperativer Stil . Konventionelle Weisheit scheint zu sein, dass das eine dem anderen nicht überlegen ist oder dass sie nach einfachen Kriterien nicht vergleichbar sind oder dass sie für verschiedene Zwecke verwendet werden ... funktionale Programmierung hat mehr wissenschaftliche / akademische Ursprünge und Verwendungen und ist in der Industrie weniger verbreitet Die Frage führt also auch zu einem unlösbaren Konflikt zwischen Industrie und Wissenschaft. Ein klassischer Ref, der OOP-System in der funktionalen Programmierung zeigt, SICP-Buch / MIT
vzn
" OO macht Code verständlich, indem bewegliche Teile gekapselt werden. FP macht Code verständlich, indem bewegliche Teile minimiert werden. " - Michael Feathers, 2010
jaco0646

Antworten:

1193

Wann wählen Sie funktionale Programmierung gegenüber objektorientiert?

Wenn Sie eine andere Art der Softwareentwicklung erwarten:

  • Objektorientierte Sprachen sind gut, wenn Sie einen festen Satz von Operationen für Dinge haben und wenn sich Ihr Code weiterentwickelt, fügen Sie hauptsächlich neue Dinge hinzu. Dies kann erreicht werden, indem neue Klassen hinzugefügt werden, die vorhandene Methoden implementieren, und die vorhandenen Klassen werden in Ruhe gelassen.

  • Funktionale Sprachen sind gut, wenn Sie einen festen Satz von Dingen haben und wenn sich Ihr Code weiterentwickelt, fügen Sie hauptsächlich neue Operationen für vorhandene Dinge hinzu. Dies kann erreicht werden, indem neue Funktionen hinzugefügt werden, die mit vorhandenen Datentypen rechnen, und die vorhandenen Funktionen bleiben in Ruhe.

Wenn die Evolution in die falsche Richtung geht, haben Sie Probleme:

  • Das Hinzufügen einer neuen Operation zu einem objektorientierten Programm erfordert möglicherweise das Bearbeiten vieler Klassendefinitionen, um eine neue Methode hinzuzufügen.

  • Das Hinzufügen einer neuen Art von Dingen zu einem Funktionsprogramm erfordert möglicherweise das Bearbeiten vieler Funktionsdefinitionen, um einen neuen Fall hinzuzufügen.

Dieses Problem ist seit vielen Jahren bekannt. 1998 nannte Phil Wadler es das "Ausdrucksproblem" . Obwohl einige Forscher der Meinung sind, dass das Ausdrucksproblem mit Sprachmerkmalen wie Mixins angegangen werden kann, muss eine allgemein akzeptierte Lösung erst noch den Mainstream erreichen.

Was sind die typischen Problemdefinitionen, bei denen funktionale Programmierung die bessere Wahl ist?

Funktionale Sprachen zeichnen sich durch die Manipulation symbolischer Daten in Baumform aus. Ein beliebtes Beispiel sind Compiler, bei denen sich Quell- und Zwischensprachen selten ändern (meistens die gleichen Dinge ), aber Compiler-Autoren immer neue Übersetzungen und Codeverbesserungen oder -optimierungen hinzufügen (neue Operationen an Dingen). Kompilierung und Übersetzung sind im Allgemeinen "Killer-Apps" für funktionale Sprachen.

Norman Ramsey
quelle
119
Hinter dieser Antwort steckt ein ernsthafter Zen. Ich denke, es beleuchtet die Tatsache, dass bestimmte OOP-Entwurfsmuster (Besucher) tatsächlich Hacks sind, die versuchen, das Problem des Hinzufügens neuer Operationen zu überwinden.
Jacobs Data Solutions
54
In JavaScript können Sie alle Dinge haben.
Erik Reppen
61
@ErikReppen An welchem ​​Punkt stellt sich die Frage, wann Sie die Funktionsmerkmale verwenden und wann Sie die objektorientierten Merkmale verwenden?
Norman Ramsey
7
@NormanRamsey Es ist keineswegs ungewöhnlich, es in JS zu verwechseln, und erstklassige Funktionen sind mit vielen JS OOP-bezogenen Funktionen verbunden. Die Array-Sortierung von JS übernimmt Funktionen als Argument, das einige leistungsstarke Datenstrukturen erzeugen kann. Closures + eine übergebene Funktion wird verwendet, um jquery-Objekte sehr leicht zu speichern, da die meisten Methoden nur Referenzen sind. Usw. ...
Erik Reppen
9
@NormanRamsey: Sehr gute Antwort nach dem Vorbild von SICP. Nach dieser Klassifizierung werden funktionale und prozedurale Programmierung auf der gegenüberliegenden Seite der objektorientierten Programmierung zusammengefasst. Dies könnte den Boom von OOP in den späten 1980ern und frühen 1990ern erklären: Als GUIs zum Mainstream wurden, erwies sich OOP als ein guter Ansatz, um sie zu modellieren, da Sie normalerweise einen festen Satz von Operationen haben (malen, öffnen, schließen, Größe ändern). und eine wachsende Anzahl von Widgets. Dies bedeutet natürlich nicht, dass OOP für jede Anwendung besser als prozedural ist, wie Sie dargestellt haben.
Giorgio
177

Sie müssen sich nicht unbedingt zwischen den beiden Paradigmen entscheiden. Sie können Software mit einer OO-Architektur unter Verwendung vieler Funktionskonzepte schreiben. FP und OOP sind orthogonaler Natur .

Nehmen Sie zum Beispiel C #. Man könnte sagen, es ist meistens OOP, aber es gibt viele FP-Konzepte und -Konstrukte. Wenn Sie Linq betrachten , sind die wichtigsten Konstrukte, die die Existenz von Linq ermöglichen, funktionaler Natur: Lambda-Ausdrücke .

Ein weiteres Beispiel, F #. Man könnte sagen, es ist hauptsächlich FP, aber es gibt viele OOP-Konzepte und -Konstrukte. Sie können Klassen, abstrakte Klassen und Schnittstellen definieren und sich mit Vererbung befassen. Sie können die Veränderbarkeit sogar verwenden, wenn dadurch Ihr Code klarer wird oder wenn die Leistung erheblich gesteigert wird.

Viele moderne Sprachen sind Multi-Paradigmen.

Empfohlene Lesungen

Da ich im selben Boot bin (OOP-Hintergrund, FP lernen), würde ich Ihnen einige Lesungen vorschlagen, die ich sehr geschätzt habe:

Bruno Reis
quelle
8
@duffymo: Dein Kommentar, wie du ihn ausdrückst, ist meistens sinnlos. Niemand möchte einen Vergleich von Sprachen, virtuellen Maschinen oder Plattformen, danke.
Bruno Reis
6
@Bruno - eine Antwort auf "Power of .NET". Entspannen.
Duffymo
6
Komisch, ich sehe dich nicht, wie du Dykam wegen seines sinnlosen Kommentars tadelst. Wurden Sie als Moderator nominiert, während ich nicht hinschaute? Niemand außer dir flammt hier. Ich werde es noch einmal sagen - entspann dich.
Duffymo
4
Tut mir leid, wenn ich anfing zu flammen. Ich wollte nicht sagen, dass andere Plattformen weniger leistungsfähig sind, nur dass .NET nicht nur OOP unterstützt. Zum Beispiel hat es Tail Call Optimierung.
Dykam
5
@nawfal, bis Sie auf einige wesentliche Merkmale in den beiden Paradigmen hinweisen und sagen können, dass sie nicht kompatibel sind, sind sie orthogonal: Das ist das Herzstück der Diskussion. FP ist per Definition nicht mit der imperativen Programmierung kompatibel, aber OOP ist nicht auf die imperative Programmierung beschränkt. Der Grund, warum wir unterschiedliche Wörter für diese Konzepte haben, ist, dass wir darüber sprechen können: Wenn Sie sie zusammenfassen, zwingen Sie uns einfach, unnötig neue Wörter zu finden.
DavidS
31

Objektorientierte Programmierung bietet:

  1. Verkapselung, zu
    • Kontrollmutation des inneren Zustands
    • Kopplung an interne Darstellung begrenzen
  2. Subtyping, erlaubt:
    • Substitution kompatibler Typen (Polymorphismus)
    • ein grobes Mittel zum Teilen der Implementierung zwischen Klassen (Implementierungsvererbung)

Die funktionale Programmierung in Haskell oder sogar in Scala kann die Substitution durch allgemeinere Mechanismen von Typklassen ermöglichen. Der veränderbare innere Zustand wird entweder entmutigt oder verboten. Die Kapselung der internen Repräsentation kann ebenfalls erreicht werden. Siehe Haskell vs OOP für einen guten Vergleich.

Normans Behauptung, dass "das Hinzufügen einer neuen Art von Dingen zu einem Funktionsprogramm möglicherweise das Bearbeiten vieler Funktionsdefinitionen erfordert, um einen neuen Fall hinzuzufügen." hängt davon ab, wie gut der Funktionscode Typklassen verwendet hat. Wenn die Musterübereinstimmung für einen bestimmten abstrakten Datentyp über eine Codebasis verteilt ist, leiden Sie zwar unter diesem Problem, aber es ist möglicherweise zunächst ein schlechtes Design.

BEARBEITET Verweis auf implizite Konvertierungen bei der Erörterung von Typklassen entfernt. In Scala werden Typklassen mit impliziten Parametern und nicht mit Konvertierungen codiert, obwohl implizite Konvertierungen ein weiteres Mittel sind, um die Substitution kompatibler Typen zu erreichen.

Retronym
quelle
3
Typklassen sind kein Mechanismus für die implizite Konvertierung in andere Typen. Sie beschreiben eine Reihe von Funktionen, die für einen Typ definiert wurden, um eine Form des Polymorphismus bereitzustellen. Das Nächste an OOP im Java-Stil wären Schnittstellen, obwohl Haskell-Typklassen einige wichtige Unterschiede aufweisen.
Zak
25
  1. Wenn Sie sich in einer stark gleichzeitigen Umgebung befinden, ist eine reine funktionale Programmierung hilfreich. Das Fehlen eines veränderlichen Zustands macht die Parallelität fast trivial. Siehe Erlang.

  2. In einer Multiparadigmensprache möchten Sie möglicherweise einige Dinge funktional modellieren, wenn das Vorhandensein eines veränderlichen Zustands ein Implementierungsdetail sein muss und FP daher ein gutes Modell für die Problemdomäne ist. Siehe beispielsweise Listenverständnisse in Python oder std.range in der Programmiersprache D. Diese sind von der funktionalen Programmierung inspiriert.

Dsimcha
quelle