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.
- Zuerst möchte ich wissen, ob meine Einschätzung korrekt ist. Stimmen das FP-Paradigma und dieser Artikel philosophisch nicht überein?
- 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.
- 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?
- 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
private
Feld haben, auf das niemand außerhalb der Klasse zugreifen kann. Es gibt keine offensichtliche Analogie zu mir in FP. - 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:
quelle
Antworten:
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 .
quelle
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.
Nein. Außerdem unterscheidet sich Ihre Beschreibung, wie ein FP-Programm aussieht, aus meiner Sicht nicht von anderen, die Prozeduren oder Funktionen verwenden:
... 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.
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:
Wenn Sie die Datenabstraktion ignorieren, erhalten Sie den Zähler und Nenner höchstwahrscheinlich mit
car
undcdr
:Nach diesem Ansatz wissen alle Teile des Systems, die rationale Zahlen manipulieren, dass eine rationale Zahl a ist
cons
- siecons
nummerieren, 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
cons
Darstellung 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
,car
undcdr
ist nicht wesentlich für rationals, abermake-rat
,numer
unddenom
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:
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.
quelle
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
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.
quelle
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
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
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.
quelle
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.
quelle
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:
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.
IMHO kompensiert es nicht. Siehe unten.
Ich glaube nicht, dass die meisten FP-Benutzer oder Designer so denken oder fühlen, siehe unten.
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".
quelle
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.
Ausblenden von Daten
quelle