Sind FP und OO orthogonal?


75

Ich habe dies immer wieder gehört und versuche, die Idee zu verstehen und zu bestätigen, dass FP und OO orthogonal sind.

Was bedeutet es zunächst, dass zwei Konzepte orthogonal sind?

FP fördert Unveränderlichkeit und Reinheit so weit wie möglich, während OO für Zustand und Mutation gebaut zu sein scheint - eine leicht organisierte Version der imperativen Programmierung? Mir ist klar, dass Objekte unveränderlich sein können, aber OO scheint für mich einen Zustand / eine Veränderung zu bedeuten.

Sie scheinen Gegensätze zu sein. Wie wirkt sich das auf ihre Orthogonalität aus?

Eine Sprache wie Scala macht es einfach, sowohl OO als auch FP zu machen. Beeinträchtigt dies die Orthogonalität der beiden Methoden?

Antworten:


72

Orthogonalität impliziert, dass zwei Dinge nichts miteinander zu tun haben. Es kommt aus der Mathematik, wo es senkrecht bedeutet . Im allgemeinen Sprachgebrauch kann dies bedeuten, dass zwei Entscheidungen nicht miteinander zusammenhängen oder dass ein Thema für die Betrachtung eines anderen Themas irrelevant ist. Wie hier verwendet, bedeutet orthogonal, dass ein Konzept das andere weder impliziert noch ausschließt.

Die beiden Konzepte objektorientierte Programmierung und funktionale Programmierung sind nicht miteinander unvereinbar. Objektorientierung bedeutet keine Veränderlichkeit. Viele Leute, die auf herkömmliche Weise in objektorientierte Programme eingeführt werden, verwenden häufig zuerst C ++, Java, C # oder ähnliche Sprachen, in denen Mutabilität häufig vorkommt und sogar gefördert wird (Standardbibliotheken bieten eine Vielzahl von veränderlichen Klassen für Benutzer). Daher ist es verständlich, dass viele Menschen objektorientierte Programmierung mit zwingender Programmierung und Veränderlichkeit verbinden, da sie dies so gelernt haben.

Die objektorientierte Programmierung umfasst jedoch Themen wie:

  • Verkapselung
  • Polymorphismus
  • Abstraktion

Nichts davon impliziert Veränderlichkeit, und nichts davon schließt funktionale Programmierung aus. Ja, sie sind insofern orthogonal , als sie unterschiedliche Konzepte sind. Sie sind keine Gegensätze - Sie können den einen oder den anderen oder beide (oder sogar keinen) verwenden. Sprachen wie Scala und F # versuchen, beide Paradigmen in einer einzigen Sprache zu kombinieren:

Scala ist eine Multi-Paradigma-Programmiersprache, die Funktionen der objektorientierten Programmierung und der funktionalen Programmierung integriert .

Quelle

F # ist eine prägnante, ausdrucksstarke und effiziente funktionale und objektorientierte Sprache für .NET, mit der Sie einfachen Code schreiben können, um komplexe Probleme zu lösen.

Quelle


Ich wollte die Formulierung "OO geht um ..." in Frage stellen, weil ich nicht dachte, dass OO definiert ist (bei der funktionalen Programmierung geht es auch sehr viel um Polymorphismus und Abstraktion). Aber bevor ich Zeit dazu hatte, haben Sie es zu etwas bearbeitet, über das ich nicht streiten kann.
Pascal Cuoq

22
Scala-Erfinder Martin Odersky nennt Scala eine "postfunktionale" Sprache, die für einen pragmatischen Ansatz steht, der die nützlichsten vorhandenen Funktionen kombiniert, unabhängig davon, woher sie stammen. Nach diesem Schema könnte man Java eine dysfunktionale Sprache nennen, was wahr ist, aber etwas vom Thema
abweicht

15
Aber offensichtlich verwenden die Erfinder und Händler diese Begriffe aus Marketinggründen. Diese Zitate sollten diskutiert und nicht als unterstützendes Argument verwendet werden.
Debilski

4
Ich stimme nicht zu, dass objektorientiert und funktional "völlig unabhängige Konzepte" sind. Sprachdesigner, die beide gut verstehen, können diese beiden Konzepte ineinander integrieren. Diese Antwort könnte interessant sein, wenn Sie den Ansatz der verschiedenen Sprachen vergleichen möchten, die Designer gewählt haben: stackoverflow.com/questions/3644251/…
soc

Es kann sein, dass objektorientierte Programmierung trotz Veränderlichkeit mit Abstraktion, Kapselung usw. verbunden ist. Es scheint jedoch etwas schwierig zu sein, über die Semantik von "Objekten" zu sprechen, ohne eine Identität zu erwähnen, die Veränderungen standhalten kann, dh Veränderlichkeit. Siehe softwarefordays.com/post/… und Kapitel 3 in mitpress.mit.edu/sites/default/files/sicp/full-text/book/…
jbmilgrom

15

Was bedeutet es zunächst, wenn zwei Konzepte orthogonal sind?

Dies bedeutet, dass die beiden Konzepte keine gegensätzlichen Vorstellungen haben oder nicht miteinander unvereinbar sind.

FP fördert die Unveränderlichkeit und Reinheit so weit wie möglich. und OO scheint etwas zu sein, das für Zustand und Mutation gebaut ist (eine leicht organisierte Version der imperativen Programmierung?). Und mir ist klar, dass Objekte unveränderlich sein können. Aber OO scheint für mich einen Zustand / eine Veränderung zu bedeuten.

Sie scheinen Gegensätze zu sein. Wie wirkt es sich auf ihre Orthogonalität aus?

Eine Sprache wie Scala macht es einfach, sowohl OO als auch FP zu machen. Beeinflusst dies die Orthogonalität der beiden Methoden?

Bei OO geht es um Einkapselung, Objektzusammensetzung, Datenabstraktion, Polymorphismus durch Subtypisierung und kontrollierte Mutation , falls erforderlich (Unveränderlichkeit wird auch bei OO gefördert). Bei FP geht es um Funktionszusammensetzung, Kontrollabstraktion und eingeschränkten Polymorphismus (auch bekannt als parametrischer Polymorphismus). Somit sind die beiden Ideen nicht widersprüchlich. Beide bieten Ihnen verschiedene Arten von Befugnissen und Abstraktionsmechanismen, die sicherlich in einer Sprache verfügbar sind. In der Tat ist dies die These, auf der Scala aufgebaut wurde!

In seinem Scala-Experiment- Vortrag bei Google erklärt Martin Odersky sehr gut, wie er glaubt, dass die beiden Konzepte - OO und FP - orthogonal zueinander sind und wie Scala die beiden Paradigmen elegant und nahtlos zu einem neuen Paradigma vereint, das in der Scala-Community als bekannt ist Objekt-Funktions-Paradigma. Muss zuschauen, wie du redest. :-)


Weitere Beispiele für objektfunktionale Sprachen: OCaml , F # , Nemerle .


1
Hier ist der Youtube-Link zum einfachen Herunterladen ~> youtube.com/watch?v=01rXrI6xelE
letronje

2
Mein Punkt ist, obwohl oop und fp im Allgemeinen nicht gegensätzlich sind, gibt es einige Punkte, in denen Sie eine Funktion oder einen oop ungefähr wählen müssen. Eine der Eigenschaften von oop ist das Binden von Daten und Verhalten. In fp ist dies nicht der Standard, obwohl Sie dies tun können. Noch ein Char. ist die hierarchische Organisation von Daten und des Typensystems (in den meisten Fällen mit Vererbung), um die Abstraktionen und den Polymosphismus zu regieren. Vielleicht ist diese Szene mit fp möglich, aber nicht beliebt.
Jneira

Orthogonalität bedeutet nicht nur, nicht in Konflikt zu geraten. Es bedeutet auch, dass das eine nicht das andere impliziert.
Deduplikator

12

Was bedeutet es zunächst, dass zwei Konzepte orthogonal sind?

Es bedeutet, dass sie sich nicht gegenseitig beeinflussen. Das heißt, eine funktionale Sprache ist nicht weniger funktional, weil sie auch objektorientiert ist.

Sie scheinen Gegensätze zu sein. Wie wirkt es sich auf ihre Orthogonalität aus?

Wenn sie Gegensätze wären (dh eine rein funktionale Sprache könnte unmöglich objektorientiert sein), wären sie per Definition nicht orthogonal. Ich glaube jedoch nicht, dass dies der Fall ist.

und OO scheint etwas zu sein, das für Zustand und Mutation gebaut ist (eine leicht organisierte Version der imperativen Programmierung?). Und mir ist klar, dass Objekte unveränderlich sein können. Aber OO scheint für mich einen Zustand / eine Veränderung zu bedeuten.

Während dies für die meisten gängigen OO-Sprachen gilt, gibt es keinen Grund, warum eine OO-Sprache einen veränderlichen Zustand haben muss.

Wenn eine Sprache Objekte, Methoden, virtuelle Vererbung und Ad-hoc-Polymorphismus aufweist, ist sie eine objektorientierte Sprache - unabhängig davon, ob sie auch einen veränderlichen Status hat oder nicht.


4
Objektorientierte Sprachen müssen nicht zwischen Klassen und Objekten aufgeteilt werden: Self, JavaScript, Io, Cecil und einige (Dutzend) andere Sprachen veranschaulichen diesen Punkt sehr gut.
NUR MEINE RICHTIGE MEINUNG

@JUST: Ok, ich habe den Verweis auf Klassen entfernt. Um fair zu sein, habe ich nicht gesagt, dass sie es tun. Ich habe nur gesagt, wenn sie diese Funktionen haben, sind sie OO. Ich sage "genau dann, wenn", wenn ich es ernst meine.
sepp2k

7

Wenn zwei Konzepte orthogonal sind, bedeutet dies, dass sie in jeder Manifestation in jedem Grad unabhängig voneinander verwirklicht werden können. Wenn Sie beispielsweise Musik betrachten, können Sie ein Musikstück danach klassifizieren, wie harmonisch es ist und wie rhythmisch es ist. Die beiden Begriffe "harmonisch" und "rhythmisch" sind orthogonal in dem Sinne, dass es harmonische und rhythmische Stücke gibt, disharmonische und arrythmische Stücke, aber auch disharmonische und rhythmische Stücke sowie harmonische und arrhythmische Stücke.

Auf die ursprüngliche Frage angewendet bedeutet dies, dass es rein funktionale, nicht objektorientierte Programmiersprachen wie Haskell, rein objektorientierte, "nicht funktionale" Sprachen wie Eiffel gibt, aber auch Sprachen, die weder C sind, noch Sprachen, die es sind beide wie Scala.

Einfach ausgedrückt bedeutet Scala objektorientiert, dass Sie Datenstrukturen ("Klassen" und "Merkmale") definieren können, die Daten mit den Methoden kapseln, mit denen diese Daten bearbeitet werden, um sicherzustellen, dass sich Instanzen dieser Strukturen ("Objekte") immer in a befinden definierter Zustand (der Vertrag des Objekts in seiner Klasse).

Andererseits bedeutet Scala als funktionale Sprache, dass sie unveränderliche gegenüber veränderlichen Zuständen bevorzugt und dass Funktionen erstklassige Objekte sind, die wie jedes andere Objekt als lokale Variablen, Felder oder Parameter für andere Funktionen verwendet werden können. Darüber hinaus hat fast jede Anweisung in Scala einen Wert, der Sie dazu ermutigt, einen funktionalen Programmierstil zu verwenden.

Die Orthogonalität der objektorientierten Programmierung und der funktionalen Programmierung in Scala bedeutet außerdem, dass Sie als Programmierer frei sind, eine beliebige Mischung dieser beiden Konzepte zu wählen, die Sie für Ihren Zweck für geeignet halten. Sie können Ihre Programme in einem rein imperativen Stil schreiben, indem Sie nur veränderbare Objekte verwenden und Funktionen überhaupt nicht als Objekte verwenden. Andererseits können Sie in Scala auch rein funktionale Programme schreiben, die keine der objektorientierten Funktionen verwenden.

Scala verlangt wirklich nicht, dass Sie den einen oder anderen Stil verwenden. Damit können Sie das Beste aus beiden Welten auswählen, um Ihr Problem zu lösen.


7

Wie bei allen Klassifikationen ist die Unterteilung der Programmiersprachen in funktionale, objektorientierte, prozedurale usw. fiktiv. Wir brauchen jedoch Klassifikationen, und in Programmiersprachen klassifizieren wir nach einer Reihe von Sprachmerkmalen und dem philosophischen Ansatz derjenigen, die die Sprache verwenden (wobei die letztere von der ersteren beeinflusst wird).

So können "objektorientierte" Sprachen manchmal erfolgreich sein, wenn sie die Merkmale und Philosophien "funktionaler" Programmiersprachen übernehmen und umgekehrt. Aber sicherlich sind nicht alle Programmiersprachenfunktionen und -philosophien kompatibel.

Beispielsweise erreicht eine funktionale Sprache wie OCaml die Kapselung durch lexikalisches Scoping und Schließen, während objektorientierte Sprachen Modifikatoren für den öffentlichen / privaten Zugriff verwenden. Dies sind per se keine inkompatiblen Mechanismen, aber sie sind redundant, und eine Sprache wie F # (eine meist funktionale Sprache, die im Einklang mit der ausgesprochen objektorientierten .NET-Bibliothek und dem Sprachstapel leben möchte) muss sich bemühen, eine Brücke zu schlagen die Lücke.

Als weiteres Beispiel verwendet OCaml ein strukturelles Typsystem zur Objektorientierung, während die meisten objektorientierten Sprachen ein nominales Typsystem verwenden. Diese sind so gut wie inkompatibel und repräsentieren interessanterweise Inkompatibilität im Bereich objektorientierter Sprachen.


1
Interessante Punkte. Obwohl OCaml mein Brot und Butter ist (und die "erste" Sprache, die Objektorientierung mit Inferenz vom Typ Hindley-Milner mischt), scheute ich jeden direkten Vergleich. Wenn ich das nicht getan hätte, hätte ich auch das Modulsystem von Caml Special Light erwähnt, das einige Jahre vor OCaml liegt und Abstraktions- / Kapselungsmechanismen bietet, die im Wettbewerb mit der Objektorientierung stehen (sie versuchen, ähnliche Probleme auf unterschiedliche Weise zu lösen).
Pascal Cuoq

@Pascal Cuoq - Ich bin froh, dass Sie dies interessant fanden. Ich war lange fasziniert von dem Konzept der Klassifizierung als künstliche Konstrukte und wurde mehr als einmal dafür bestraft, Pflanzen als Tiere in Scattergories aufzulisten.
Stephen Swensen

Es ist zu beachten, dass F # direkt auf OCaml basiert.
Jacobs Data Solutions

6

Die Idee von Objekten kann unveränderlich umgesetzt werden. Ein Beispiel ist das Buch " A Theory of Objects " von Abadi und Cardelli, das darauf abzielt, diese Ideen zu formalisieren, und in dem Objekten zunächst unveränderliche Semantik gegeben wird, weil dies das Denken über objektorientierte Programme vereinfacht.

In diesem Fall gibt eine Methode, die das Objekt traditionell an Ort und Stelle geändert hätte, stattdessen ein neues Objekt zurück, während das vorherige Objekt bestehen bleibt.


5

Sie können Funktionen als Objekte und Objekte als Sammlungen von Funktionen implementieren, sodass eindeutig eine Beziehung zwischen den beiden Konzepten besteht.

FP fördert die Unveränderlichkeit und Reinheit so weit wie möglich

Sie sprechen von einer rein funktionalen Programmierung.

während OO für Zustand und Mutation gebaut zu sein scheint

Objekte müssen nicht veränderbar sein. Ich würde sagen, dass Objekte und Mutationen orthogonale Konzepte waren. Beispielsweise bietet die Programmiersprache OCaml eine Syntax für die rein funktionale Objektaktualisierung.

Eine Sprache wie Scala macht es einfach, sowohl OO als auch FP zu machen

Nicht wirklich. Das Fehlen einer Tail-Call-Optimierung bedeutet, dass der Großteil des idiomatischen rein funktionalen Codes in Scala einen Stapelüberlauf aufweist, da dadurch Stapelrahmen verloren gehen. Zum Beispiel der Continuation Passing Style (CPS) und alle Techniken, die in dem Artikel That about von Bruce McAdam beschrieben werden. Es gibt keine einfache Möglichkeit, dies zu beheben, da die JVM selbst keine Tail-Call-Optimierung durchführen kann.

In Bezug auf die Orthogonalität der rein funktionalen Programmierung und der objektorientierten Programmierung würde ich sagen, dass sie zumindest nahezu orthogonal sind, nur weil sich die rein funktionale Programmierung nur mit Programmen in kleinen (z. B. Funktionen höherer Ordnung) befasst, während sich die objektorientierte Programmierung mit großen befasst -skalierte Strukturierung von Programmen. Aus diesem Grund bieten funktionale Programmiersprachen normalerweise einen anderen Mechanismus für die Strukturierung in großem Maßstab, z. B. die Modulsysteme höherer Ordnung von Standard ML und OCaml oder CLOS für Common Lisp oder Typklassen für Haskell.


3
-1. Sie mussten dieses Scala-TCO-Problem hier wirklich nicht ansprechen. Sie lassen keine einzige Gelegenheit, Scala zu verprügeln, oder?
fehlender Faktor

7
@missingfaktor: Die TCO ist ein offensichtliches Gegenbeispiel zu seiner Aussage, dass Scala FP einfach macht. Sie lassen keine einzige Gelegenheit offen, Scala angesichts überwältigender gegenteiliger Beweise blind zu vertreten, oder?
JD

5
Downvoting für das offensichtlich führende Wort "Mehrheit". Selbst in rein funktionalen Sprachen erfolgt der Großteil der Schleifen nicht über eine explizite Rekursion, sondern über Aufrufe von Funktionen höherer Ordnung, die Scala perfekt bereitstellt.
Dave Griffith

5
Lesen und Schreiben einer sehr großen Menge an Funktionscode über viel zu viele Jahre. Die Schwanzrekursion ist der Hammer, der herausgezogen wird, wenn Karte / Reißverschluss / Scannen / Falten / Reduzieren / usw. nicht für den Job geeignet sind. Das sollte nicht allzu überraschend sein. Der Grund, warum diese Aufrufe existieren, besteht darin, möglichst viele der gängigen Rekursionsmuster zu abstrahieren. Die einzige Ausnahme, an die ich denken kann (wobei Tail-Call die bevorzugte Lösung ist), ist Erlangs Trick "Fälsche den veränderlichen Komponentenzustand als Tail-Call-Argumente".
Dave Griffith

3
Wenn ich nicht falsch verstehe, würde sich der Aufruf der Listenfalte auf keinen Fall in der Schwanzposition innerhalb der Baumfalte befinden. Auf jeden Fall stoße ich in Scala auf ein Tail-Call-Problem, vielleicht einmal im Monat, wahrscheinlich weniger. Ich finde es einfach nicht besonders wichtig, geschweige denn einen lähmenden Mangel. Vielleicht müssen Sie daran arbeiten, Ihre Abhängigkeitsgraphen etwas strenger zu entwirren.
Dave Griffith


1

Ich habe gerade eine wunderbare Erklärung gefunden für die Orthogonalität von OOP und FP gefunden.

Die Grundidee ist wie folgt. Stellen Sie sich vor, wir arbeiten mit ASTs von mathematischen Ausdrücken. Wir haben also verschiedene Arten von Substantiven (Konstante, Addition, Multiplikation) und verschiedene Verben (eval, toString).

Sagen wir, der Ausdruck ist (1 + 2) * 3 . Dann wäre der AST:

       Multiplikation
         / \.
     Zusatz 3
      / \.
     1 2

Um ein Verb zu implementieren, müssen wir seine Implementierung für jede Art von Substantiv bereitstellen. Wir können es als Tabelle darstellen:

                +---------------------+-------------------------------------+
                | eval                | toString                            |
+---------------+---------------------+-------------------------------------+
| constant      | value               | value.toString                      |
+---------------+---------------------+-------------------------------------+
| addition      | lhs.eval + rhs.eval | lhs.toString + " + " + rhs.toString |
+---------------+---------------------+-------------------------------------+
| mutiplication | lhs.eval * rhs.eval | lhs.toString + " * " + rhs.toString |
+---------------+---------------------+-------------------------------------+

Die „Orthogonalität“ ergibt sich aus der Tatsache, dass wir diese Tabelle in OOP zeilenweise implementieren werden : Wir werden jedes Substantiv als Klasse darstellen, die jede Methode implementieren muss.

In FP hingegen implementieren wir diese Tabelle nach Spalten - wir schreiben für jedes Verb eine Funktion, und diese Funktion reagiert unterschiedlich auf Argumente unterschiedlichen Typs (wahrscheinlich unter Verwendung des Mustervergleichs).


Die Erklärung scheint zu argumentieren, dass FP und OOP nicht orthogonal sind, sondern tatsächlich gegensätzliche, sich gegenseitig ausschließende, allumfassende Ansätze sind.
Nathan Tuggy

1
Ich mag hier irgendwie "orthogonal". Natürlich nicht im mathematischen Sinne, dass sie unabhängig sind. In dem Sinne, dass sie die entgegengesetzten, grafisch orthogonalen Ansätze verfolgen, um ein Problem zu zerlegen.
Danila Piatov

Es ist mathematisch angemessen (da die Achsen der Tabelle sind senkrecht), aber leider nicht in dem Sinne , in dem jeder benutzt es, sagt sie zu vergleichen, Programmiertechniken. Dies ist also ein Fall des etymologischen Irrtums.
Nathan Tuggy

-1

Senkrecht. Es klingt gut. Wenn Sie eine Ausbildung haben, können Sie sie ein wenig binden und so tun, als ob. Es ist ein bisschen wie ein Paradigma.

Es hängt alles davon ab, in welchen Kreisen Sie reisen und welche Art von Programmiertechnik Sie erhalten. Ich habe ein paar Beiträge über SS gelesen und die meisten, die aus einer funktionalen Programmiersprache stammen, bestehen weiterhin darauf, dass man nur funktional werden kann und alles andere gegen das Denken und die Denkweise verstößt.

Bei der objektorientierten Programmierung geht es hauptsächlich darum, den Status zu erfassen und diesen Status so lokal wie möglich zu halten, damit er nicht von etwas beeinflusst wird, das nicht Teil des Objekts ist, mit dem Sie den Status verwalten. Andererseits betrachtet die funktionale Programmierung das Problem des Zustands aus einer anderen Perspektive und versucht, den Zustand vom System zu trennen und auf Funktionen zu reduzieren. Ja, Sie können beide Techniken in Ihrem Code verwenden, aber beide betrachten das Design von Software aus verschiedenen Blickwinkeln.

Es gab großes Interesse an den Techniken der funktionalen Programmierung, hauptsächlich wegen des vom Staat geforderten Managements beim Umgang mit Mehrkernchips und paralleler Programmierung. Zu diesem Zeitpunkt scheint die funktionale Programmierung die Oberhand zu haben, aber Sie können den gleichen Effekt mit Objekten erzielen. Sie denken nur anders über das Problem. Anstatt sich am Kopf zu kratzen und zu versuchen, den Zustand so weit wie möglich loszuwerden, sehen Sie sich Objekte im Design an und sehen, wie Sie sie mithilfe von Designmustern, CRC und dem Kern dessen koppeln können, was von ihnen erwartet wird Objektanalyse. Wo Objekte jedoch zu ihren eigenen gehören und wo funktionale Programmierung viel schwieriger ist, besteht darin, die reale Welt zu analysieren und sie einem verständlichen Computersystem zuzuordnen. In OO zum Beispiel Ein Personenobjekt wäre eine Verkapselung des Zustands mit Methoden, die auf den Personenzustand einwirken. Bei der funktionalen Programmierung würde eine Person in Datenteile und Funktionen zerlegt, die auf die Personendaten einwirken, mit der zusätzlichen Maßgabe, dass Daten einmal und nur einmal erstellt und unveränderlich sein sollten.

Ich muss zugeben, obwohl ich aus einem OO-Hintergrund stamme, dass ich in den meisten OO-Sprachen beim Umgang mit Multi-Core-Chips den funktionalen Weg gegangen bin, hauptsächlich durch Designstrukturen für die Kernprogrammierung (wie Threads und Delegaten) und Pseudodatenobjekte herumgereicht habe. Dies hat mich dazu gebracht, die Techniken der OO-Programmierung in Frage zu stellen, da sie diesem Thread-Design nicht gut zu entsprechen scheint.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.