Ignoriert die funktionale Programmierung die Vorteile, die sich aus den „Kriterien für die Zerlegung von Systemen in Module“ (Ausblenden von Daten) ergeben?

27

Es gibt einen klassischen Artikel mit dem Namen " Zu den Kriterien für die Zerlegung von Systemen in Module" , den ich gerade zum ersten Mal gelesen habe. Es macht für mich vollkommen Sinn und ist wahrscheinlich einer dieser Artikel, auf denen OOP basierte. Sein Fazit:

Wir haben versucht, anhand dieser Beispiele zu demonstrieren, dass es fast immer falsch ist, die Zerlegung eines Systems in Module anhand eines Flussdiagramms zu beginnen. ... Jedes Modul soll dann eine solche Entscheidung vor den anderen verbergen

Nach meiner ungebildeten und unerfahrenen Meinung entspricht die funktionale Programmierung genau dem gegenteiligen Rat dieses Artikels. Mein Verständnis ist, dass funktionale Programmierung den Datenfluss idiomatisch macht. Daten werden von Funktion zu Funktion weitergegeben, wobei jede Funktion die Daten genau kennt und sie auf dem Weg "ändert" . Und ich glaube, ich habe einen Rich Hickey-Vortrag gesehen, in dem er darüber spricht, wie das Verbergen von Daten überbewertet oder unnötig ist oder so, aber ich kann mich nicht sicher erinnern.

  1. Zuerst möchte ich wissen, ob meine Einschätzung korrekt ist. Stimmen das FP-Paradigma und dieser Artikel philosophisch nicht überein?
  2. Angenommen, sie stimmen nicht überein, wie "kompensiert" FP den Mangel an versteckten Daten? Vielleicht opfern sie das Ausblenden von Daten, gewinnen aber X, Y und Z. Ich möchte wissen, warum X, Y und Z als vorteilhafter gelten als das Ausblenden von Daten.
  3. Unter der Annahme, dass sie nicht übereinstimmen, ist FP der Ansicht, dass das Verstecken von Daten schlecht ist. Wenn ja, warum hält es das Ausblenden von Daten für schlecht?
  4. Vorausgesetzt, sie stimmen überein, würde ich gerne wissen, wie FPs das Verbergen von Daten implementieren. Es ist offensichtlich, dass dies in OOP zu sehen ist. Sie können ein privateFeld haben, auf das niemand außerhalb der Klasse zugreifen kann. Es gibt keine offensichtliche Analogie zu mir in FP.
  5. Ich habe das Gefühl, es gibt andere Fragen, die ich stellen sollte, aber ich weiß nicht, ob ich sie stellen sollte. Beantworten Sie auch diese Fragen.

Aktualisieren

Ich fand diesen Neal Ford-Vortrag , der eine sehr relevante Folie enthält. Ich binde den Screenshot hier ein:

Bildbeschreibung hier eingeben

Daniel Kaplan
quelle
1
Ich kann die vollständige Frage nicht beantworten, aber für (4) gibt es Modulsysteme in einigen FP-Sprachen, die eine Kapselung bereitstellen können.
Andres F.
@AndresF. ah ja das stimmt Ich habe vergessen, dass Haskell Module enthält und Sie darin Datentypen und Funktionen ausblenden können. Vielleicht sage ich, wenn ich FP sage, wirklich Clojure. Sie können in Clojure private Funktionen und "Felder" haben, aber ich halte es für idiomatisch, Ihre Daten für alles sichtbar zu machen und sie überallhin weiterzugeben.
Daniel Kaplan
6
Was Sie oft tun, ist, Ihre Typen sichtbar zu machen, aber Ihre Konstruktoren zu verbergen. Diese abstrakten Typen werden besonders gut vom OCaml-Modulsystem
Daniel Gratzer,
6
In einer ML-ähnlichen Sprache bedeutet der fehlende Zugriff auf die Konstruktoren, dass Sie keine Musterübereinstimmung über einen Wert dieses Typs durchführen können, um ihn zu dekonstruieren. Mit diesen Werten können Sie sie nur an die jeweils zur Verfügung gestellte Funktion übergeben. Es ist die gleiche Art von Datenabstraktion wie beispielsweise in C, bei der es keine erstklassigen Vorstellungen davon gibt, was öffentlich oder privat ist.
Luc Danton
1
@ SK-logic: Unter dem Gesichtspunkt des "Ausdrucksproblems" ist es gut, die Daten zu enthüllen, wenn Sie sie in Zukunft mit neuen Funktionen erweitern möchten (und die Daten in Ordnung halten möchten), und die Daten zu verbergen, wenn Sie möchten in Zukunft mit neuen Datentypen zu erweitern (auf Kosten der Beibehaltung der funktionalen Schnittstelle)
hugomg

Antworten:

23

Der Artikel, den Sie erwähnen, befasst sich mit Modularität im Allgemeinen und gilt gleichermaßen für strukturierte, funktionale und objektorientierte Programme. Ich habe diesen Artikel schon einmal von jemandem gehört, der ein großer OOP-Typ war, aber ich habe ihn als Artikel über das Programmieren im Allgemeinen gelesen, nicht als etwas OOP-spezifisches. Es gibt einen berühmten Artikel über funktionale Programmierung, Why Functional Programming Matters , und im ersten Satz der Schlussfolgerung heißt es: "In diesem Artikel haben wir argumentiert, dass Modularität der Schlüssel für eine erfolgreiche Programmierung ist." Die Antwort auf (1) lautet also nein.

Bei gut gestalteten Funktionen wird nicht mehr von den Daten ausgegangen, als sie benötigen. Daher ist der Teil über die "genaue Kenntnis der Daten" falsch. (Oder zumindest so falsch wie bei OOP. Sie können nicht streng auf einer hohen Abstraktionsebene programmieren und alle Details in jedem Paradigma für immer ignorieren. Letztendlich muss ein Teil des Programms tatsächlich etwas über das wissen spezifische Details der Daten.)

Das Ausblenden von Daten ist ein OOP-spezifischer Begriff und entspricht nicht genau dem im Artikel beschriebenen Ausblenden von Informationen. Informationen, die im Artikel versteckt sind, beziehen sich auf Entwurfsentscheidungen, die schwer zu treffen waren oder sich wahrscheinlich ändern werden. Nicht jede Entwurfsentscheidung über ein Datenformat ist schwer oder wahrscheinlich zu ändern, und nicht jede Entscheidung, die schwer oder wahrscheinlich zu ändern ist, betrifft ein Datenformat. Persönlich kann ich nicht verstehen, warum OO-Programmierer wollen, dass alles ein Objekt ist. Manchmal genügt eine einfache Datenstruktur.

Bearbeiten: Ich fand ein relevantes Zitat aus einem Interview mit Rich Hickey .

Fogus: Dieser Idee folgend - einige Leute sind überrascht über die Tatsache, dass Clojure keine datenversteckenden Kapselungen für seine Typen vornimmt. Warum haben Sie auf das Verbergen von Daten verzichtet?

Hickey: Lassen Sie uns klarstellen, dass Clojure die Programmierung von Abstraktionen stark betont. Irgendwann muss jemand Zugriff auf die Daten haben. Und wenn Sie eine Vorstellung von „privat“ haben, brauchen Sie entsprechende Vorstellungen von Privilegien und Vertrauen. Und das erhöht die Komplexität und den Wert des Systems um eine ganze Tonne, schafft Starrheit in einem System und zwingt die Dinge oft dazu, an Orten zu leben, an denen sie nicht sein sollten. Dies ist zusätzlich zu dem anderen Verlust, der auftritt, wenn einfache Informationen in Klassen eingeteilt werden. In dem Maße, in dem die Daten unveränderlich sind, kann die Bereitstellung des Zugriffs nur wenig schaden, außer dass jemand von etwas abhängen könnte, das sich ändern könnte. Okay, die Leute machen das die ganze Zeit im wirklichen Leben und wenn sich die Dinge ändern, passen sie sich an. Und wenn sie rational sind, Sie wissen, wann sie eine Entscheidung treffen, die auf etwas basiert, das sich ändern kann und das sie möglicherweise in Zukunft anpassen müssen. Es ist also eine Risikomanagement-Entscheidung, die Programmierer meiner Meinung nach frei treffen sollten. Wenn die Leute nicht die Sensibilität haben, auf Abstraktionen programmieren zu wollen und sich davor hüten, Implementierungsdetails zu verwechseln, werden sie niemals gute Programmierer sein.

Michael Shaw
quelle
2
OO-Programmierer möchten nicht, dass alles ein Objekt ist. Aber einige Dinge (viele Dinge) profitieren von Verkapselung. Ich habe Probleme zu verstehen, wie oder wo Ihre Antwort die Frage wirklich anspricht. Es scheint nur zu behaupten, dass das Konzept nicht spezifisch für OOP ist und dass OOP andere Probleme usw. hat. Können Sie vielleicht ein klares Beispiel liefern, auch wenn es sich nur um ein paar Zeilen Pseudocode handelt? Oder eine Whiteboard-Beschreibung eines Designs, das dies berücksichtigt? Oder irgendetwas, das die Behauptungen hier untermauern würde?
Aaronaught
2
@Aaronaught: Ich habe viele (wenn auch nicht alle) der in der Frage angesprochenen Punkte angesprochen und auf einen Artikel über funktionale Programmierung verwiesen, der die Modularität in ähnlicher Weise wie der in der Frage behandelte Artikel betrachtet. Zu einem großen Teil ist die Tatsache, dass das Konzept nicht spezifisch für OOP ist, die Antwort auf seine Frage (es sei denn, ich habe die Frage vollständig falsch verstanden). Ich habe wirklich nicht darüber gesprochen, dass OOP hier andere Probleme hat. Sie haben ein gutes Argument für die Bereitstellung eines Beispiels. Ich werde sehen, ob ich einen guten finden kann.
Michael Shaw
2
"Manchmal genügt eine einfache Datenstruktur". +1. Etwas OOP macht Sinn, manchmal ist es FP.
Laurent Bourgault-Roy
1
@Aaronaught In dieser Antwort wird darauf hingewiesen, dass Modularität (die sowohl Verkapselung als auch Wiederverwendung ist) eines der Ziele von FP ist (wie in "Warum funktionale Programmierung von Bedeutung ist" beschrieben), und daher die Antwort auf Punkt (1) der Frage a gegeben. Nein".
Andres F.
2
@ JimmyHoffa Verstecken von Informationen ist ein vernünftiges Prinzip, auch außerhalb von OO. In haskell möchte ich weiterhin, dass Benutzer mit minimalem Wissen über Datenstrukturen arbeiten können. Natürlich ist der Zugriff auf die Interna weniger gefährlich, da nichts veränderlich ist. Aber je weniger ein Benutzer über ein Modul / eine Datenstruktur / ein abstraktes Konzept sieht, desto mehr Refactoring-Möglichkeiten erhalten Sie. Es ist mir egal, ob es sich bei einer Karte um einen ausgeglichenen Binärbaum handelt oder um eine Maus in einer kleinen Box auf meinem Computer. Dies ist die Hauptmotivation für das Verbergen von Daten und gilt außerhalb von OO.
Simon Bergot
12

... und ist wahrscheinlich einer dieser Artikel, auf denen OOP basierte.

Nicht wirklich, aber es fügte sich in die Diskussion ein, insbesondere für Praktiker, die zu dieser Zeit darauf trainiert waren, Systeme anhand der ersten Kriterien zu zerlegen, die er in dem Artikel beschreibt.

Zuerst möchte ich wissen, ob meine Einschätzung korrekt ist. Stimmen das FP-Paradigma und dieser Artikel philosophisch nicht überein?

Nein. Außerdem unterscheidet sich Ihre Beschreibung, wie ein FP-Programm aussieht, aus meiner Sicht nicht von anderen, die Prozeduren oder Funktionen verwenden:

Daten werden von Funktion zu Funktion weitergegeben, wobei jede Funktion die Daten genau kennt und sie auf dem Weg "ändert".

... mit Ausnahme des Teils "Intimität", da Sie Funktionen haben können (und dies häufig tun), die mit abstrakten Daten arbeiten, um die Intimität zu vermeiden. Sie haben also eine gewisse Kontrolle über diese "Intimität" und können sie regulieren, wie Sie möchten, indem Sie Schnittstellen (dh Funktionen) für das einrichten, was Sie ausblenden möchten.

Daher sehe ich keinen Grund, warum wir Parnas Kriterien für das Verbergen von Informationen mithilfe der funktionalen Programmierung nicht folgen und eine Implementierung eines KWIC-Indexes mit ähnlichen Vorteilen wie seine zweite Implementierung erzielen könnten.

Vorausgesetzt, sie stimmen überein, würde ich gerne wissen, wie FPs das Verbergen von Daten implementieren. Es ist offensichtlich, dass dies in OOP zu sehen ist. Sie können ein privates Feld haben, auf das niemand außerhalb der Klasse zugreifen kann. Es gibt keine offensichtliche Analogie zu mir in FP.

In Bezug auf Daten können Sie mit FP Datenabstraktionen und Datentypabstraktionen erstellen. Alle diese verbergen konkrete Strukturen und Manipulationen dieser konkreten Strukturen unter Verwendung von Funktionen als Abstraktionen.

BEARBEITEN

Es gibt eine wachsende Anzahl von Behauptungen, wonach das "Verbergen von Daten" im Kontext von FP nicht so nützlich ist (oder OOP-ish (?)). Lassen Sie mich hier ein sehr einfaches und klares Beispiel von SICP stempeln:

Angenommen, Ihr System muss mit rationalen Zahlen arbeiten. Eine Möglichkeit, sie darzustellen, besteht darin, sie als Paar oder als Liste mit zwei Ganzzahlen darzustellen: dem Zähler und dem Nenner. Somit:

(define my-rat (cons 1 2)) ; here is my 1/2 

Wenn Sie die Datenabstraktion ignorieren, erhalten Sie den Zähler und Nenner höchstwahrscheinlich mit carund cdr:

(... (car my-rat)) ; do something with the numerator

Nach diesem Ansatz wissen alle Teile des Systems, die rationale Zahlen manipulieren, dass eine rationale Zahl a ist cons- sie consnummerieren, um rationale Zahlen zu erstellen und sie mit Hilfe von Listenoperatoren zu extrahieren.

Ein Problem, mit dem Sie möglicherweise konfrontiert sind, besteht darin, dass Sie eine reduzierte Form der rationalen Zahlen benötigen - Änderungen sind im gesamten System erforderlich. Wenn Sie sich zum Zeitpunkt der Erstellung für eine Reduzierung entscheiden, ist es möglicherweise später besser, auf einen der rationalen Begriffe zuzugreifen, was zu einer weiteren vollständigen Änderung führt.

Ein anderes Problem ist, wenn hypothetisch eine alternative Darstellung für sie bevorzugt wird und Sie beschließen, die consDarstellung aufzugeben - Änderung des vollen Maßstabs erneut.

Jeder vernünftige Versuch, mit diesen Situationen umzugehen, wird wahrscheinlich die Darstellung von Begriffen hinter Schnittstellen verbergen. Am Ende könnte es so aussehen:

  • (make-rat <n> <d>)gibt die rationale Zahl zurück, deren Zähler die ganze Zahl <n>und deren Nenner die ganze Zahl ist <d>.

  • (numer <x>)Gibt den Zähler der rationalen Zahl zurück <x>.

  • (denom <x>)gibt den Nenner der rationalen Zahl zurück <x>.

und das System wird nicht länger wissen (und sollte nicht länger wissen), woraus Rationals bestehen. Dies liegt daran cons, carund cdrist nicht wesentlich für rationals, aber make-rat, numerund denom ist . Natürlich könnte dies leicht ein FP-System sein. "Verstecken von Daten" (in diesem Fall besser bekannt als Datenabstraktion oder der Versuch, Repräsentationen und konkrete Strukturen zu kapseln) ist ein relevantes Konzept und eine Technik, die weit verbreitet und erforscht ist, sei es im Kontext von OO, funktionaler Programmierung oder wie auch immer.

Und der Punkt ist ... obwohl man versuchen kann zu unterscheiden, welche Art von "Verstecken" oder Kapselung sie tun (ob sie eine Entwurfsentscheidung oder Datenstrukturen oder Algorithmen verstecken - im Fall von prozeduralen Abstraktionen), Alle haben das gleiche Thema: Sie sind motiviert durch einen oder mehrere Punkte, die ausdrücklich erwähnt wurden. Das ist:

  • Änderbarkeit: Gibt an, ob erforderliche Änderungen vor Ort vorgenommen oder über das System verteilt werden können.
  • Unabhängige Entwicklung: Inwieweit können zwei Teile des Systems parallel entwickelt werden?
  • Verständlichkeit: Wie viel des Systems muss bekannt sein, um einen seiner Teile zu verstehen.

Das obige Beispiel wurde aus dem SICP-Buch entnommen, daher empfehle ich dringend, Kapitel 2 zu lesen, um dieses Konzept vollständig zu diskutieren und darzustellen . Ich empfehle auch, sich im Kontext von FP mit abstrakten Datentypen vertraut zu machen, wodurch andere Probleme auf den Tisch kommen.

Thiago Silva
quelle
Ich stimme zu, dass das Verbergen von Daten in FP relevant ist. Und wie Sie sagen, gibt es Möglichkeiten, dies zu erreichen.
Andres F.
2
Sie haben mich nur schön hervorgehoben: Sie haben diese Funktionen, die keine Daten verbergen. Es sind Ausdrücke, die beschreiben, wie Daten abgerufen werden. Dadurch, dass die Abstraktion in einem Ausdruck und nicht in einem Datenfeld enthalten ist, brauchen Sie sich keine Gedanken über das Verbergen zu machen Die Daten werden durch Erstellen eines komplexen Objekts mit privaten Mitgliedern oder durch Unzugänglichmachen Ihrer Nachteile ausgedrückt. Die Aktivitäten zum Generieren, Abrufen und Interagieren mit rationalen Daten müssen daher nicht ausgeblendet werden, da die Daten nicht geändert werden ändere deine Ausdrücke.
Jimmy Hoffa
8

Ihre Überzeugung, dass in der funktionalen Programmierung keine Daten versteckt sind, ist falsch. Es ist nur ein anderer Ansatz zum Ausblenden von Daten. Eine der häufigsten Methoden zum Ausblenden von Daten in der funktionalen Programmierung ist die Verwendung polymorpher Funktionen, die eine Funktion als Argument verwenden. Zum Beispiel diese Funktion

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

kann nur die äußerste Struktur der Daten sehen (dh, dass es sich um eine Liste handelt), kann nichts über die in der Liste enthaltenen Daten sehen und kann die Daten nur über die einzelne Funktion verarbeiten, die an sie übergeben wird.

Die als Argument übergebene Funktion entspricht einer öffentlichen Methode für den in der Liste enthaltenen Datentyp. Es bietet eine eingeschränkte Möglichkeit zur Verarbeitung der Daten, legt jedoch nicht die internen Funktionen des Datentyps offen.

Dirk Holsopple
quelle
5

Ich werde hier einen Strich durch die Rechnung machen und sagen, dass das Konzept in FP einfach nicht so relevant ist wie in OO.

tl; dr; Der Zweck des Versteckens von Daten besteht darin, sicherzustellen, dass Verantwortlichkeiten dort beibehalten werden, wo sie sein sollten, und dass keine externen Akteure mit Daten herumspielen, für die sie nicht das Wissen haben. In FP werden Daten durch Ausdrücke generiert, und auf diese Weise können Sie nicht mit den Daten herumspielen, da es sich nicht um veränderbare Eigenschaften handelt, sondern vielmehr um zusammensetzbare Berechnungen, die die Spielregeln vollständig ändern.


In meinen Erfahrungen mit FP; die zugegebenermaßen unbedeutend sind, neige ich dazu, einen starken Kontrast zu OO in dem zu finden, was eine gute / gemeinsame Datenmodellierung bezeichnet.

Dieser Gegensatz besteht darin, dass Sie in OO im Allgemeinen Dinge modellieren, um Ihre Daten darzustellen. Verbindliche Auto-Analogie:

OO

  • Sie haben ein Auto-Objekt, das Details über das Auto korrekt verbirgt, z. B. die AC-Implementierung (wird es durch einen Riemen oder Luftdruck angetrieben? Verbraucher sollten es nicht wissen müssen, also verstecken Sie es).
  • Dieses Autoobjekt verfügt über viele Eigenschaften und Methoden, die alle Fakten über das Auto sowie die Art und Weise beschreiben, wie Sie mit einem Auto arbeiten können.
  • Dieses Autoobjekt weist Eigenschaften auf, die Komponenten eines Autos sind, die ihre speziellen Implementierungen und ihre Datenfakten, die es ermöglichen, dass die Komponenten des Autos austauschbar sind, weiter vor dem Gesamtauto verbergen.

Beachten Sie, dass es beim Modellieren von Objekten im OO-Format nur darum geht, Objekte als Daten darzustellen. Sie haben Objekte mit Eigenschaften. Viele dieser Eigenschaften sind Objekte mit mehr Eigenschaften. Sie haben hier und da ein paar Methoden, die mit diesen Objekten verknüpft sind, aber alles, was sie wirklich tun, ist, die Eigenschaften der Objekte auf diese und jene Weise zu verändern. Auch dies ist eine sehr datenorientierte Modellierung. Das heißt, Sie modellieren Ihre Daten für die Interaktion und konzentrieren sich auf deren Strukturierung, um alle Punkte Ihrer Daten verfügbar zu machen, damit die Verbraucher die Daten auf diese und jene Weise ändern können.

FP

  • Sie haben eine Menge Berechnungen, mit denen Sie Verhaltensweisen beschreiben können
  • Diese Verhaltensausdrücke stehen in einer Weise in Beziehung, die sich auf die Art und Weise übertragen lässt, in der das Verhalten eines Autos zueinander in Beziehung steht, wie beispielsweise ein Auto, das beschleunigt / verlangsamt. Es gibt zwei Verhaltensweisen, die sich auf ähnliche Weise gegenüberstehen.

Der große Unterschied zwischen OO und FP, der mir ständig auffällt, ist, wie ich bereits sagte, die Art und Weise, wie Sie Daten modellieren. In OO modellieren Sie, wie oben erwähnt, Daten als Daten, in FP modellieren Sie Daten als Berechnungen, Ausdrücke, Algorithmen. Es geht mehr um die Modellierung der Aktivitäten Ihrer Daten als um die Fakten. Denken Sie an die grundlegende Datenmodellierung in der Mathematik. Es geht immer darum, eine Gleichung zu erhalten, mit der Ihre Daten generiert werden können. Dabei werden Ihre Daten als die Aktivität modelliert, die sie verursacht. Das ist ein großer Unterschied zwischen FP und OO.

Denken Sie daran, dass LISP, eine der grundlegenden FP-Sprachen, lange Zeit mit einer sehr geringen Anzahl primitiver Datentypen lebte. Dies funktioniert, da es bei diesem Ansatz nicht darum geht, komplexe Darstellungen Ihrer Daten zu modellieren, sondern vielmehr um Berechnungen, die das Verhalten Ihres Systems generieren und ausdrücken.

Wenn ich mit dem Schreiben von Code in FP beginne, beginne ich mit dem Schreiben von Code, der etwas bewirkt. Wenn ich mit dem Schreiben von Code in OO beginne, beginne ich mit dem Schreiben von Modellen, die etwas beschreiben. Das Tun von Dingen wird in FP durch Ausdrücke verborgen, das Tun von Dingen wird in OO durch Beschreiben mit Daten entlarvt, wobei das Ausblenden dieser Daten die Exposition einschränkt.


Zurück zu der Frage, was sagt FP über das Verbergen von Daten, schätzt es sie oder ist es nicht einverstanden oder was nicht?

Ich sage, es spielt keine Rolle, in OO sind Ihre Daten die Eingeweide und wichtigen Teile in Ihrem Programm, mit denen Sie sich nicht einmischen sollten. In FP ist der Mut und das Wissen Ihres Systems in den Algorithmen und Berechnungen verborgen, die das System ausdrücken. Diese sind per Definition mehr oder weniger unveränderlich. Die einzige Möglichkeit, Berechnungsausdrücke zu mutieren, sind Dinge wie Makros, aber selbst dann sind Ihre Mutationsdefinitionen Ausdrücke selbst, mit denen man sich nicht weiter befassen kann.

Jimmy Hoffa
quelle
das ist genial, ich habe es wirklich genossen zu lesen. Vielen Dank für Ihren Beitrag
Chris McCall
5

Hier gibt es ein kleines Paradoxon. Obwohl sich die funktionale Programmierung auf Funktionen konzentriert und häufig Funktionen hat, die direkt mit primitiven Datentypen arbeiten, sind in der Regel mehr Daten verborgen als bei der objektorientierten Programmierung.

Wie ist das so Denken Sie an eine nette OO-Oberfläche, die zugrunde liegende Daten verbirgt - vielleicht Sammlungen (ich versuche, etwas auszuwählen, das fast allgegenwärtig ist). Möglicherweise müssen Sie den zugrunde liegenden Typ der Objekte in der Auflistung oder den Typ des Objekts, das die Auflistung implementiert, nicht kennen, solange Sie wissen, dass die Auflistung beispielsweise IEnumerable implementiert. Sie haben also Daten versteckt.

Bei der funktionalen Programmierung können Sie eine Funktion schreiben, die effektiv mit einer IEnumerable-Schnittstelle funktioniert, jedoch mit einem primitiven Datentyp (oder einem beliebigen Datentyp) arbeitet. Was aber, wenn der Typ die IEnumerable-Methoden nie implementiert hat? Hier ist der Schlüssel, Sie können immer die "Methoden", die die benötigten Teile der "Schnittstelle" bilden, an Ihre Funktion übergeben. Oder Sie können Funktionen mit Daten zusammenfügen und Dinge auf eine OO-ähnliche Weise tun.

Beachten Sie, dass in beiden Fällen nicht weniger Daten versteckt sind als in OO. Meine allgemeine Funktion, die für jeden Typ funktioniert, greift eindeutig nicht auf die Daten in diesem Typ zu - das geschieht in den Funktionen, die als Parameter an die allgemeine Funktion übergeben werden, aber die allgemeine Funktion schaut nie in diese Funktionen, um die Daten anzuzeigen.

Was Punkt 1 betrifft, denke ich nicht, dass FP und der Artikel wirklich nicht übereinstimmen. Ich glaube nicht, dass Ihre Charakterisierung von FP, bei der Daten nicht ausgeblendet werden, korrekt ist. Man könnte das vom Autor bevorzugte Design sicherlich in FP implementieren.

Soweit Punkt 4 (2 und 3 bei dem, was ich für Punkt 1 gesagt habe, keinen Sinn ergibt), variiert er. Sie variiert auch in OO-Sprachen und ist in vielen privaten Bereichen eher privat als durch die Sprache erzwungen.

bA
quelle
Mit anderen Worten: In der funktionalen Programmierung ist viel mehr standardmäßig "verborgen", einfach weil es nicht einmal existiert! Nur Sachen, die Sie explizit in den Geltungsbereich bringen, sind "versteckt".
links
3

Erstens, danke für den Link zu diesem großartigen Artikel, den ich bisher nicht kannte und der mir großartige Anregungen zu einigen Dingen gab, die ich in den letzten Jahren mit einigen anderen Software-Designern aus der Community besprochen habe. Hier ist meine Meinung dazu:

Zuerst möchte ich wissen, ob meine Einschätzung korrekt ist. Stimmen das FP-Paradigma und dieser Artikel philosophisch nicht überein?

FP-Design konzentriert sich sehr auf den Datenfluss (was meiner Meinung nach nicht so schlimm ist, wie der Artikel andeutet). Ob dies eine völlige "Meinungsverschiedenheit" ist, ist fraglich.

Angenommen, sie stimmen nicht überein, wie "kompensiert" FP den Mangel an versteckten Daten? Vielleicht opfern sie das Ausblenden von Daten, gewinnen aber X, Y und Z. Ich möchte wissen, warum X, Y und Z als vorteilhafter gelten als das Ausblenden von Daten.

IMHO kompensiert es nicht. Siehe unten.

Unter der Annahme, dass sie nicht übereinstimmen, ist FP der Ansicht, dass das Verstecken von Daten schlecht ist. Wenn ja, warum hält es das Ausblenden von Daten für schlecht?

Ich glaube nicht, dass die meisten FP-Benutzer oder Designer so denken oder fühlen, siehe unten.

Vorausgesetzt, sie stimmen überein, würde ich gerne wissen, wie FPs das Verbergen von Daten implementieren. Es ist offensichtlich, dass dies in OOP zu sehen ist. Sie können ein privates Feld haben, auf das niemand außerhalb der Klasse zugreifen kann. Es gibt keine offensichtliche Analogie zu mir in FP.

Hier ist der Punkt - Sie haben wahrscheinlich so viele OOP-Systeme gesehen, die nicht funktionsfähig implementiert wurden, dass Sie glauben, dass OOP nicht funktionsfähig ist. Und das ist ein Trugschluss, IMHO OOP und FP sind meist orthogonale Konzepte, und Sie können perfekt funktionierende OO-Systeme erstellen, die Ihnen eine offensichtliche Antwort auf Ihre Frage geben. Die klassische "Objekt" -Implementierung in FP erfolgt unter Verwendung von Verschlüssen . Wenn Sie Objekte in einem funktionalen System verwenden möchten, müssen Sie sie unveränderlich gestalten.

Um größere Systeme zu erstellen, können Sie IMHO Module, Klassen und Objekte mit OO-Konzepten erstellen, genau wie unter "Modularisierung 2" im Artikel beschrieben, ohne den "FP-Pfad" zu verlassen. Sie verwenden das Modulkonzept Ihrer bevorzugten FP-Sprache, machen einfach alle Ihre Objekte unveränderlich und verwenden das "Beste aus beiden Welten".

Doc Brown
quelle
3

TL; DR : Nein

Stimmen das FP-Paradigma und dieser Artikel philosophisch nicht überein?

Nein, tut es nicht. Funktionale Programmierung ist deklarativ, was "ein Stil zum Aufbau der Struktur und der Elemente von Computerprogrammen ist, der die Logik einer Berechnung ausdrückt, ohne ihren Steuerungsfluss zu beschreiben." Es geht weniger darum, dem Flussdiagramm zu folgen, sondern vielmehr darum, Regeln zu erstellen, nach denen der Fluss von selbst entsteht.

Die prozedurale Programmierung kommt der Codierung eines Flussdiagramms viel näher als die funktionale Programmierung. Daraus folgt, dass auftretende Transformationen und Kodierungen dieser Transformationen in Prozeduren umgewandelt werden, die genau so ausgeführt werden, wie es der Ablauf in einem Ablaufdiagramm beschreibt.

Während prozedurale Sprachen die Ausführung des Programms als Folge von Imperativbefehlen modellieren, die implizit den gemeinsam genutzten Zustand ändern können, modellieren funktionale Programmiersprachen die Ausführung als Auswertung komplexer Ausdrücke, die nur in Bezug auf Argumente und Rückgabewerte voneinander abhängig sind. Aus diesem Grund können Funktionsprogramme eine freiere Reihenfolge der Codeausführung aufweisen, und die Sprachen bieten möglicherweise wenig Kontrolle über die Reihenfolge, in der verschiedene Teile des Programms ausgeführt werden. (Beispielsweise werden die Argumente für einen Prozeduraufruf in Schema in einer beliebigen Reihenfolge ausgeführt.)

Ausblenden von Daten

  • Die funktionale Programmierung hat eigene Methoden zum Verbergen von Daten, zum Beispiel Think Closures . Das sind Daten, die sich durch die Kapselung in einem Verschluss verstecken. Es ist schwierig für Felder, mehr private Daten zu sein, die geschlossen wurden, da nur die Schließung einen Verweis auf die Daten enthält und Sie nicht außerhalb der Schließung darauf verweisen können.
  • Einer der Gründe für das Ausblenden von Daten besteht darin, die Programmierschnittstelle durch Ausblenden mutierender Daten zu stabilisieren. Funktionale Programmierung hat keine mutierenden Daten, daher muss nicht so viel Daten versteckt werden.
dietbuddha
quelle
3
"Funktionale Programmierung hat keine mutierenden Daten, daher müssen nicht so viele Daten versteckt werden." - Dies ist eine sehr irreführende Behauptung. Sie sagten selbst (und ich stimme zu), dass einer der Gründe für die Verkapselung von Verhalten darin besteht, die Kontrolle über die Mutation von Daten zu haben. Aber zu dem Schluss, dass die fehlende Mutation die Verkapselung fast unbrauchbar macht, ist eine riesige Strecke. ADTs und Datenabstraktionen im Allgemeinen sind in der FP-Literatur und -Systemen allgegenwärtig.
Thiago Silva
Ich habe es nie gesagt "macht Kapselung fast nutzlos". Das sind deine Gedanken und nur deine. Ich sagte, Sie müssen nicht so viele Daten verstecken, weil es keine mutierenden Variablen gibt. Dies macht die Kapselung oder das Verbergen von Daten nicht unbrauchbar, sondern reduziert lediglich die Verwendung, da diese Fälle nicht existieren. Alle anderen Fälle, in denen das Ausblenden und Einkapseln von Daten nützlich ist, sind weiterhin gültig.
Dietbuddha