Seit ich letztes Jahr angefangen habe, F # und OCaml zu lernen , habe ich eine Vielzahl von Artikeln gelesen, die darauf bestehen, dass Entwurfsmuster (insbesondere in Java) Problemumgehungen für die fehlenden Funktionen in imperativen Sprachen sind. Ein Artikel, den ich gefunden habe, behauptet ziemlich stark :
Die meisten Leute, die ich getroffen habe, haben das Design Patterns-Buch der Gang of Four (GoF) gelesen . Jeder Programmierer mit Selbstachtung wird Ihnen sagen, dass das Buch sprachunabhängig ist und die Muster für das Software-Engineering im Allgemeinen gelten, unabhängig davon, welche Sprache Sie verwenden. Dies ist eine edle Behauptung. Leider ist es weit von der Wahrheit entfernt.
Funktionssprachen sind äußerst ausdrucksstark. In einer funktionalen Sprache benötigt man keine Entwurfsmuster, da die Sprache wahrscheinlich so hoch ist, dass man am Ende Konzepte programmiert, die Entwurfsmuster insgesamt eliminieren.
Zu den Hauptmerkmalen der funktionalen Programmierung (FP) gehören Funktionen wie erstklassige Werte, Currying, unveränderliche Werte usw. Es scheint mir nicht offensichtlich, dass OO-Entwurfsmuster sich einem dieser Merkmale annähern.
Darüber hinaus scheint es mir in funktionalen Sprachen, die OOP unterstützen (wie F # und OCaml), offensichtlich, dass Programmierer, die diese Sprachen verwenden, dieselben Entwurfsmuster verwenden würden, die für jede andere OOP-Sprache verfügbar sind. Tatsächlich verwende ich momentan jeden Tag F # und OCaml, und es gibt keine auffälligen Unterschiede zwischen den Mustern, die ich in diesen Sprachen verwende, und den Mustern, die ich beim Schreiben in Java verwende.
Stimmt die Behauptung, dass durch funktionale Programmierung keine OOP-Entwurfsmuster mehr erforderlich sind? Wenn ja, können Sie ein Beispiel für ein typisches OOP-Entwurfsmuster und dessen funktionales Äquivalent veröffentlichen oder verlinken?
Antworten:
Der Blog-Beitrag, den Sie zitiert haben, übertreibt seine Behauptung ein wenig. FP nicht beseitigt die Notwendigkeit für Design - Muster. Der Begriff "Entwurfsmuster" wird in FP-Sprachen nicht häufig verwendet, um dasselbe zu beschreiben. Aber sie existieren. Funktionale Sprachen haben viele Best-Practice-Regeln der Form "Wenn Sie auf Problem X stoßen, verwenden Sie Code, der wie Y aussieht", was im Grunde ein Entwurfsmuster ist.
Es ist jedoch richtig, dass die meisten OOP-spezifischen Entwurfsmuster in funktionalen Sprachen so gut wie irrelevant sind.
Ich denke nicht, dass es besonders kontrovers sein sollte zu sagen, dass Designmuster im Allgemeinen nur existieren, um Mängel in der Sprache zu beheben. Und wenn eine andere Sprache das gleiche Problem trivial lösen kann, benötigt diese andere Sprache kein Entwurfsmuster dafür. Benutzer dieser Sprache sind sich möglicherweise nicht einmal bewusst, dass das Problem besteht , da es in dieser Sprache kein Problem darstellt.
Folgendes sagt die Viererbande zu diesem Thema:
(Das Obige ist ein Zitat aus dem Buch Einführung in das Entwurfsmuster, Seite 4, Absatz 3)
Was ist das Befehlsmuster, wenn nicht eine Annäherung an erstklassige Funktionen? :) In einer FP-Sprache würden Sie einfach eine Funktion als Argument an eine andere Funktion übergeben. In einer OOP-Sprache müssen Sie die Funktion in eine Klasse einschließen, die Sie instanziieren und dann an die andere Funktion übergeben können. Der Effekt ist der gleiche, aber in OOP wird er als Entwurfsmuster bezeichnet, und es wird viel mehr Code benötigt. Und was ist das abstrakte Fabrikmuster, wenn nicht Curry? Übergeben Sie die Parameter nach und nach an eine Funktion, um zu konfigurieren, welche Art von Wert ausgegeben wird, wenn Sie sie schließlich aufrufen.
Ja, mehrere GoF-Entwurfsmuster werden in FP-Sprachen überflüssig, da leistungsfähigere und benutzerfreundlichere Alternativen existieren.
Aber natürlich gibt es immer noch Entwurfsmuster, die von FP-Sprachen nicht gelöst werden. Was ist das FP-Äquivalent eines Singletons? (Ignorieren Sie für einen Moment, dass Singletons im Allgemeinen ein schreckliches Muster sind.)
Und es funktioniert auch in beide Richtungen. Wie gesagt, FP hat auch seine Designmuster; Leute denken normalerweise einfach nicht an sie als solche.
Aber Sie sind vielleicht auf Monaden gestoßen. Was sind sie, wenn nicht ein Entwurfsmuster für den "Umgang mit dem globalen Staat"? Das ist ein Problem, das in OOP-Sprachen so einfach ist, dass dort kein gleichwertiges Entwurfsmuster existiert.
Wir benötigen kein Entwurfsmuster für "Inkrementieren einer statischen Variablen" oder "Lesen aus diesem Socket", da dies genau das ist, was Sie tun .
Zu sagen, eine Monade sei ein Entwurfsmuster, ist genauso absurd wie zu sagen, dass die Ganzzahlen mit ihren üblichen Operationen und das Nullelement ein Entwurfsmuster sind. Nein, eine Monade ist ein mathematisches Muster , kein Entwurfsmuster.
In (reinen) funktionalen Sprachen sind Nebenwirkungen und veränderlicher Zustand unmöglich, es sei denn, Sie umgehen dies mit dem Monaden- "Entwurfsmuster" oder einer der anderen Methoden, um dasselbe zuzulassen.
Vielleicht, weil Sie immer noch zwingend denken? Viele Menschen haben es schwer, diese Gewohnheit aufzugeben, wenn sie eine funktionierende Sprache ausprobieren, nachdem sie sich ihr ganzes Leben lang mit imperativen Sprachen beschäftigt haben. (Ich habe einige ziemlich lustige Versuche mit F # gesehen, bei denen buchstäblich jede Funktion nur eine Folge von 'let'-Anweisungen war, im Grunde genommen, als hätten Sie ein C-Programm genommen und alle Semikolons durch' let 'ersetzt. :))
Eine andere Möglichkeit könnte sein, dass Sie einfach nicht bemerkt haben, dass Sie Probleme trivial lösen, die Entwurfsmuster in einer OOP-Sprache erfordern würden.
Wenn Sie Curry verwenden oder eine Funktion als Argument an eine andere übergeben, halten Sie inne und überlegen Sie, wie Sie dies in einer OOP-Sprache tun würden.
Ja. :) Wenn Sie in einer FP-Sprache arbeiten, benötigen Sie die OOP-spezifischen Entwurfsmuster nicht mehr. Sie benötigen jedoch noch einige allgemeine Entwurfsmuster wie MVC oder andere nicht OOP-spezifische Dinge, und Sie benötigen stattdessen einige neue FP-spezifische "Entwurfsmuster". Alle Sprachen haben ihre Mängel, und Designmuster sind normalerweise die Art und Weise, wie wir sie umgehen.
Wie auch immer, Sie finden es vielleicht interessant, sich in "saubereren" FP-Sprachen wie ML (mein persönlicher Favorit, zumindest zu Lernzwecken) oder Haskell zu versuchen , wo Sie nicht über die OOP-Krücke verfügen, auf die Sie zurückgreifen können, wenn Sie darauf zurückgreifen Ich bin mit etwas Neuem konfrontiert.
Wie erwartet haben einige Leute Einwände gegen meine Definition von Designmustern als "Ausbessern von Mängeln in einer Sprache" erhoben. Hier ist meine Rechtfertigung:
Wie bereits gesagt, sind die meisten Entwurfsmuster spezifisch für ein Programmierparadigma oder manchmal sogar für eine bestimmte Sprache. Oft sie Probleme lösen , die nur existieren in diesem Paradigma (Monaden für FP, oder abstrakte Fabriken für OOP sehen).
Warum existiert das abstrakte Fabrikmuster in FP nicht? Weil das Problem, das es zu lösen versucht, dort nicht existiert.
Wenn also ein Problem in OOP-Sprachen besteht, das in FP-Sprachen nicht vorhanden ist, ist dies eindeutig ein Mangel an OOP-Sprachen. Das Problem kann gelöst werden, aber Ihre Sprache tut dies nicht, sondern erfordert eine Menge Boilerplate-Code von Ihnen, um es zu umgehen. Idealerweise möchten wir, dass unsere Programmiersprache alle Probleme auf magische Weise beseitigt. Jedes Problem, das noch besteht, ist im Prinzip ein Mangel der Sprache. ;)
quelle
Funktionale Programmierung ist nicht dasselbe wie objektorientierte Programmierung. Objektorientierte Entwurfsmuster gelten nicht für die funktionale Programmierung. Stattdessen haben Sie funktionale Programmierentwurfsmuster.
Für die funktionale Programmierung werden Sie die OO-Entwurfsmusterbücher nicht lesen. Sie werden andere Bücher über FP-Designmuster lesen.
Nicht völlig. Nur sprachunabhängig in Bezug auf OO-Sprachen. Die Entwurfsmuster gelten überhaupt nicht für prozedurale Sprachen. Sie sind in einem relationalen Datenbankdesignkontext kaum sinnvoll. Sie gelten nicht beim Entwerfen einer Tabelle.
Das obige sollte nicht existieren. Das ist so, als würde man nach einem prozeduralen Code fragen, der als OO-Code umgeschrieben wurde. Ummm ... Wenn ich das ursprüngliche Fortran (oder C) in Java übersetze, habe ich nichts weiter getan, als es zu übersetzen. Wenn ich es komplett in ein OO-Paradigma umschreibe, sieht es nicht mehr wie das ursprüngliche Fortran oder C aus - es ist nicht wiederzuerkennen.
Es gibt keine einfache Zuordnung vom OO-Design zum funktionalen Design. Sie sehen das Problem sehr unterschiedlich.
Funktionale Programmierung (wie alle Programmierstile) weist Entwurfsmuster auf. Relationale Datenbanken haben Entwurfsmuster, OO hat Entwurfsmuster und prozedurale Programmierung hat Entwurfsmuster. Alles hat Designmuster, sogar die Architektur von Gebäuden.
Entwurfsmuster - als Konzept - sind eine zeitlose Art zu bauen, unabhängig von Technologie oder Problembereich. Bestimmte Entwurfsmuster gelten jedoch für bestimmte Problembereiche und Technologien.
Jeder, der darüber nachdenkt, was er tut, wird Designmuster aufdecken.
quelle
Brians Kommentare zur engen Verbindung zwischen Sprache und Muster sind auf den Punkt gebracht,
Der fehlende Teil dieser Diskussion ist das Konzept der Redewendung. James O. Copliens Buch "Advanced C ++" war hier ein großer Einfluss. Lange bevor er Christopher Alexander und die Spalte ohne Namen entdeckte (und man kann auch nicht vernünftig über Muster sprechen, ohne Alexander zu lesen), sprach er darüber, wie wichtig es ist, Redewendungen zu beherrschen, um wirklich eine Sprache zu lernen. Er hat die Zeichenfolgenkopie in C als Beispiel verwendet.
while(*from++ = *to++);
Sie können dies als Bandaid für ein fehlendes Sprachmerkmal (oder Bibliotheksmerkmal) ansehen, aber was wirklich wichtig ist, ist, dass es eine größere Einheit des Denkens oder Ausdrucks ist als irgendeines von seine Teile.Das ist es, was Muster und Sprachen versuchen, damit wir unsere Absichten prägnanter ausdrücken können. Je reicher die Gedankeneinheiten sind, desto komplexer sind die Gedanken, die Sie ausdrücken können. Ein reichhaltiges, gemeinsames Vokabular in verschiedenen Maßstäben - von der Systemarchitektur bis hin zum Twiddling - ermöglicht uns intelligentere Gespräche und Gedanken darüber, was wir tun sollten.
Wir können auch als Individuen lernen. Welches ist der ganze Punkt der Übung. Wir alle können Dinge verstehen und anwenden, an die wir niemals denken könnten. Sprachen, Frameworks, Bibliotheken, Muster, Redewendungen usw. haben ihren Platz darin, den geistigen Reichtum zu teilen.
quelle
Das GoF-Buch knüpft ausdrücklich an OOP an - der Titel lautet Design Patterns - Elements of Reusable Object-Oriented Software (Schwerpunkt Mine).
quelle
Entwurfsmuster in der dynamischen Programmierung von Peter Norvig haben dieses allgemeine Thema sorgfältig behandelt, allerdings über "dynamische" Sprachen statt über "funktionale" (es gibt Überschneidungen).
quelle
Hier ist ein weiterer Link, der dieses Thema behandelt: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/
In seinem Blog-Beitrag beschreibt Edward alle 23 ursprünglichen GoF-Muster in Bezug auf Haskell.
quelle
Wenn Sie versuchen, dies auf der Ebene der "Entwurfsmuster" (im Allgemeinen) und "FP versus OOP" zu betrachten, werden die Antworten, die Sie finden, bestenfalls trübe sein.
Gehen Sie jedoch auf beiden Achsen eine Ebene tiefer und berücksichtigen Sie bestimmte Entwurfsmuster und bestimmte Sprachmerkmale, und die Dinge werden klarer.
So ändern oder verschwinden beispielsweise bestimmte Muster wie Besucher , Strategie , Befehl und Beobachter definitiv, wenn eine Sprache mit algebraischen Datentypen und Mustervergleich , Abschlüssen , erstklassigen Funktionen usw. verwendet wird. Einige andere Muster aus dem GoF-Buch sind noch vorhanden "Bleib dabei".
Im Allgemeinen würde ich sagen, dass im Laufe der Zeit bestimmte Muster durch neue (oder nur immer beliebter werdende) Sprachfunktionen beseitigt werden. Dies ist der natürliche Verlauf des Sprachdesigns. Wenn Sprachen immer höher werden, werden Abstraktionen, die bisher nur in einem Buch anhand von Beispielen aufgerufen werden konnten, jetzt zu Anwendungen eines bestimmten Sprachmerkmals oder einer bestimmten Bibliothek.
(Nebenbei: Hier ist ein kürzlich von mir geschriebener Blog , der weitere Links zu weiteren Diskussionen über FP und Entwurfsmuster enthält.)
quelle
for
Schleifen hatten und alle nurwhile
Schleifen hatten, könnte "For" ein Iterationsmuster sein. Aber wennfor
nur ein Konstrukt von der Sprache unterstützt wird und wie Menschen normal codieren, dann ist es kein Muster - Sie tun es nicht. Ich brauche kein Muster, es ist nur Code, Mann.)foreach
und Haskell haben,mapM
heißt das nicht, dass sie nicht das Iteratormuster haben. Ich sehe kein Problem darin zu sagen, dass das Iterator-Muster als generische SchnittstelleIEnumerable<T>
in C # und als TypklasseTraversable
in Haskell implementiert ist .Norvigs Präsentation spielt auf eine Analyse aller GoF-Muster an und sagt, dass 16 der 23 Muster einfachere Implementierungen in funktionalen Sprachen hatten oder einfach Teil der Sprache waren. Vermutlich waren mindestens sieben von ihnen entweder a) gleich kompliziert oder b) nicht in der Sprache vorhanden. Leider sind sie für uns nicht aufgezählt!
Ich denke, es ist klar, dass die meisten "kreativen" oder "strukturellen" Muster in GoF nur Tricks sind, um die primitiven Typsysteme in Java oder C ++ dazu zu bringen, das zu tun, was Sie wollen. Aber der Rest ist eine Überlegung wert, egal in welcher Sprache Sie programmieren.
Einer könnte Prototyp sein; Während es ein grundlegender Begriff von JavaScript ist, muss es von Grund auf in anderen Sprachen implementiert werden.
Eines meiner Lieblingsmuster ist das Nullobjektmuster: Stellen Sie das Fehlen von etwas als Objekt dar, das eine angemessene Art von Nichts tut. Dies ist möglicherweise einfacher in einer funktionalen Sprache zu modellieren. Die eigentliche Errungenschaft ist jedoch der Perspektivwechsel.
quelle
Ich würde sagen, wenn Sie eine Sprache wie Lisp mit Unterstützung für Makros haben, können Sie Ihre eigenen domänenspezifischen Abstraktionen erstellen, Abstraktionen, die oft viel besser sind als die allgemeinen Redewendungen.
quelle
Und selbst die OO-Entwurfsmusterlösungen sind sprachspezifisch.
Entwurfsmuster sind Lösungen für häufig auftretende Probleme, die Ihre Programmiersprache für Sie nicht löst. In Java löst das Singleton-Muster das (vereinfachte) Problem.
In Scala haben Sie zusätzlich zu Class ein Konstrukt der obersten Ebene namens Object. Es ist träge instanziiert und es gibt nur eine. Sie müssen das Singleton-Muster nicht verwenden, um einen Singleton zu erhalten. Es ist Teil der Sprache.
quelle
Muster sind Möglichkeiten, ähnliche Probleme zu lösen, die immer wieder auftreten und dann beschrieben und dokumentiert werden. Also nein, FP wird Muster nicht ersetzen. FP kann jedoch neue Muster erstellen und einige aktuelle "Best Practices" -Muster "obsolet" machen.
quelle
Wie andere gesagt haben, gibt es Muster, die für die funktionale Programmierung spezifisch sind. Ich denke, das Problem, Designmuster loszuwerden, ist nicht so sehr eine Frage der Umstellung auf funktionale, sondern eine Frage der Sprachmerkmale .
Schauen Sie sich an, wie Scala das "Singleton-Muster" beseitigt: Sie deklarieren einfach ein Objekt anstelle einer Klasse. Ein weiteres Merkmal, der Mustervergleich, hilft dabei, die Unbeholfenheit des Besuchermusters zu vermeiden. Sehen Sie den Vergleich hier: Scalas Pattern Matching = Besuchermuster auf Steroiden
Und Scala ist wie F # eine Fusion von OO-Funktionen. Ich weiß nichts über F #, aber es hat wahrscheinlich diese Art von Funktionen.
Verschlüsse sind in funktionaler Sprache vorhanden, müssen aber nicht auf sie beschränkt sein. Sie helfen beim Delegatormuster.
Noch eine Beobachtung. Dieser Code implementiert ein Muster: Es ist so ein Klassiker und so elementar, dass wir es normalerweise nicht als "Muster" betrachten, aber es ist sicher:
Imperative Sprachen wie Java und C # haben ein im Wesentlichen funktionales Konstrukt übernommen, um damit umzugehen: "foreach".
quelle
Das GoF- Entwurfsmuster codiert Umgehungsrezepte für OO-Sprachen, die Nachkommen von Simula 67 sind , wie Java und C ++.
Die meisten der durch die Entwurfsmuster behandelten "Übel" werden verursacht durch:
Es gibt kein einziges dieser Entwurfsmuster, das im Common Lisp Object System nicht verschwindet, obwohl die Lösung im Wesentlichen so strukturiert ist wie im entsprechenden Entwurfsmuster. (Darüber hinaus geht dieses Objektsystem dem GoF-Buch weit über ein Jahrzehnt voraus. Common Lisp wurde im selben Jahr, in dem dieses Buch erstmals veröffentlicht wurde, zum ANSI-Standard.)
Was die funktionale Programmierung betrifft, hängt es davon ab, ob die gegebene funktionale Programmiersprache eine Art Objektsystem hat und ob sie den Objektsystemen nachempfunden ist, die von den Mustern profitieren. Diese Art der Objektorientierung passt nicht gut zur funktionalen Programmierung, da die Mutation des Zustands vorne und in der Mitte liegt.
Konstruktion und nicht mutierender Zugriff sind mit funktionaler Programmierung kompatibel. Daher können Muster angewendet werden, die mit abstrahiertem Zugriff oder Konstruktion zu tun haben: Muster wie Factory, Facade, Proxy, Decorator und Visitor.
Andererseits gelten Verhaltensmuster wie Zustand und Strategie wahrscheinlich nicht direkt für die funktionale OOP, da die Mutation des Zustands in ihrem Kern liegt. Dies bedeutet nicht, dass sie nicht zutreffen. Vielleicht lassen sie sich irgendwie in Kombination mit den verfügbaren Tricks anwenden, um einen veränderlichen Zustand zu simulieren.
quelle
Ich möchte ein paar ausgezeichnete, aber etwas dichte Artikel von Jeremy Gibbons einfügen: "Entwurfsmuster als generische Datentypprogramme höherer Ordnung" und "Die Essenz des Iteratormusters" (beide hier verfügbar: http: // www. comlab.ox.ac.uk/jeremy.gibbons/publications/ ).
Beide beschreiben, wie idiomatische Funktionskonstrukte das Gelände abdecken, das von bestimmten Entwurfsmustern in anderen (objektorientierten) Einstellungen abgedeckt wird.
quelle
Sie können diese Diskussion nicht führen, ohne Typsysteme aufzurufen.
Das liegt daran, dass diese Funktionen nicht die gleichen Probleme wie OOP lösen. Sie sind Alternativen zur imperativen Programmierung. Die FP-Antwort auf OOP liegt in den Typsystemen von ML und Haskell ... insbesondere in Summentypen, abstrakten Datentypen, ML-Modulen und Haskell-Typklassen.
Das erste, was Typklassen tun, ist die Notwendigkeit von Singletons zu beseitigen.
Sie könnten die Liste der 23 durchgehen und mehr eliminieren, aber ich habe momentan keine Zeit dafür.
quelle
Ich denke, nur zwei GoF-Entwurfsmuster wurden entwickelt, um die funktionale Programmierlogik in die natürliche OO-Sprache einzuführen. Ich denke an Strategie und Befehl. Einige der anderen GoF-Entwurfsmuster können durch funktionale Programmierung geändert werden, um den Entwurf zu vereinfachen und den Zweck beizubehalten.
quelle
Im Wesentlichen ja !
Außerdem bietet diese Seite (AreDesignPatternsMissingLanguageFeatures) eine "Muster / Feature" -Übersetzungstabelle und einige nette Diskussionen, wenn Sie bereit sind zu graben.
quelle
Die funktionale Programmierung ersetzt keine Entwurfsmuster. Entwurfsmuster können nicht ersetzt werden.
Muster existieren einfach; Sie entstanden im Laufe der Zeit. Das GoF-Buch hat einige von ihnen formalisiert. Wenn neue Muster zutage treten, wenn Entwickler funktionale Programmiersprachen verwenden, ist das aufregend, und vielleicht werden auch Bücher darüber geschrieben.
quelle
In dem neuen Buch von 2013 mit dem Titel "Functional Programming Patterns- in Scala and Clojure" hat der Autor Michael.B. Linn leistet gute Arbeit beim Vergleichen und Ersetzen der GoF-Muster in vielen Fällen und diskutiert auch die neueren Funktionsmuster wie "Schwanzrekursion", "Memoisierung", "Lazy Sequence" usw.
Dieses Buch ist bei Amazon erhältlich. Ich fand es sehr informativ und ermutigend, wenn ich aus einem OO-Hintergrund von ein paar Jahrzehnten stamme.
quelle
OOP und die GoF-Muster befassen sich mit Zuständen. OOP modelliert die Realität, um die Codebasis so nah wie möglich an den gegebenen Anforderungen der Realität zu halten. GoF-Entwurfsmuster sind Muster, die identifiziert wurden, um atomare Probleme der realen Welt zu lösen. Sie behandeln das Problem des Staates semantisch.
Da in der realen Funktionsprogrammierung kein Zustand existiert, ist es nicht sinnvoll, die GoF-Muster anzuwenden. Es gibt keine funktionalen Entwurfsmuster wie GoF-Entwurfsmuster. Jedes funktionale Entwurfsmuster ist im Gegensatz zur Realität künstlich, da Funktionen Konstrukte der Mathematik und nicht der Realität sind.
Funktionen fehlt das Konzept der Zeit, da sie unabhängig von der aktuellen Zeit immer den gleichen Wert zurückgeben, es sei denn, die Zeit ist Teil der Funktionsparameter, was es wirklich schwierig macht, "zukünftige Anforderungen" zu verarbeiten. Hybride Sprachen mischen diese Konzepte und machen die Sprachen nicht zu echten funktionalen Programmiersprachen.
Funktionale Sprachen nehmen nur aufgrund einer Sache zu: der gegenwärtigen natürlichen Einschränkungen der Physik. Heutzutage sind Prozessoren aufgrund physikalischer Gesetze in ihrer Verarbeitungsgeschwindigkeit begrenzt. Sie sehen eine Stagnation der Taktfrequenz, aber eine Erweiterung der Prozessorkerne. Aus diesem Grund wird die Parallelität von Anweisungen immer wichtiger, um die Geschwindigkeit moderner Anwendungen zu erhöhen. Da die funktionale Programmierung per Definition keinen Zustand hat und daher keine Nebenwirkungen hat, ist es sicher, Funktionen sicher parallel zu verarbeiten.
GoF-Muster sind nicht veraltet. Sie sind zumindest erforderlich, um die Anforderungen der realen Welt zu modellieren. Wenn Sie jedoch eine funktionale Programmiersprache verwenden, müssen Sie diese in ihre Hybridäquivalente umwandeln. Schließlich haben Sie keine Chance, nur funktionale Programme zu erstellen, wenn Sie Persistenz verwenden. Für die hybriden Elemente Ihres Programms besteht weiterhin die Notwendigkeit, GoF-Muster zu verwenden. Für jedes andere Element, das rein funktional ist, besteht keine Notwendigkeit, GoF-Muster zu verwenden, da es keinen Status gibt.
Da die GoF-Muster für eine echte funktionale Programmierung nicht erforderlich sind, bedeutet dies nicht, dass die SOLID-Prinzipien nicht angewendet werden sollten. Die SOLID-Prinzipien gehen über jedes Sprachparadigma hinaus.
quelle
In der funktionalen Programmierung haben Entwurfsmuster eine andere Bedeutung. Tatsächlich sind die meisten OOP- Entwurfsmuster in der funktionalen Programmierung aufgrund der höheren Abstraktionsebene und der als Bausteine verwendeten HOFs nicht erforderlich .
quelle
Wie in der akzeptierten Antwort angegeben, haben OOP und FP alle ihre spezifischen Muster.
Es gibt jedoch einige Muster, die so häufig sind, dass alle Programmierplattformen, die ich mir vorstellen kann, vorhanden sein sollten. Hier ist eine (unvollständige) Liste:
Adapter. Ich kann mir kaum eine nützliche Programmierplattform vorstellen, die so umfassend (und selbsterfüllt) ist, dass sie nicht mit der Welt sprechen muss. In diesem Fall wird auf jeden Fall ein Adapter benötigt.
Fassade. Alle Programmierplattformen, die großen Quellcode verarbeiten können, sollten modularisiert werden können. Wenn Sie ein Modul für andere Teile des Programms erstellen, möchten Sie die "schmutzigen" Teile des Codes ausblenden und ihm eine schöne Oberfläche geben.
Dolmetscher. Im Allgemeinen führt jedes Programm nur zwei Dinge aus: Analyseeingabe und Druckausgabe. Mauseingaben müssen analysiert und Fenster-Widgets ausgedruckt werden. Ein eingebetteter Interpreter bietet dem Programm daher zusätzliche Möglichkeiten zum Anpassen von Dingen.
Außerdem ist mir in einer typischen FP-Sprache, Haskell, aufgefallen, dass es etwas Ähnliches wie GoF-Muster gibt, aber mit unterschiedlichen Namen. Meiner Meinung nach deutet dies darauf hin, dass sie dort waren, da einige häufig auftretende Probleme sowohl in FP- als auch in OOP-Sprachen zu lösen sind.
quelle
Ich denke, dass jedes Paradigma einem anderen Zweck dient und als solches nicht auf diese Weise verglichen werden kann.
Ich habe nicht gehört, dass die GoF-Entwurfsmuster für jede Sprache gelten. Ich habe gehört, dass sie für alle OOP-Sprachen gelten . Wenn Sie funktionale Programmierung verwenden, unterscheidet sich der Bereich der Probleme, die Sie lösen, von den OO-Sprachen.
Ich würde keine funktionale Sprache verwenden, um eine Benutzeroberfläche zu schreiben, aber eine der OO-Sprachen wie C # oder Java würde diese Arbeit erleichtern. Wenn ich eine funktionale Sprache schreiben würde, würde ich nicht in Betracht ziehen, OO-Entwurfsmuster zu verwenden.
quelle
OOP und FP haben unterschiedliche Ziele. OOP zielt darauf ab, die Komplexität / beweglichen Teile von Softwarekomponenten zu kapseln, und FP zielt darauf ab, die Komplexität und Abhängigkeiten von Softwarekomponenten zu minimieren.
Diese beiden Paradigmen widersprechen sich jedoch nicht unbedingt zu 100% und könnten zusammen angewendet werden, um den Nutzen beider Welten zu erzielen.
Selbst mit einer Sprache, die funktionale Programmierung wie C # nicht nativ unterstützt, können Sie Funktionscode schreiben, wenn Sie die FP-Prinzipien verstehen. Ebenso können Sie OOP-Prinzipien mit F # anwenden, wenn Sie die OOP-Prinzipien, Muster und Best Practices verstehen. Sie würden die richtige Wahl treffen, basierend auf der Situation und dem Problem, das Sie zu lösen versuchen, unabhängig von der verwendeten Programmiersprache.
quelle
Einige Muster sind einfacher in einer Sprache zu implementieren, die FP unterstützt. Zum Beispiel kann Strategie mithilfe von Verschlüssen implementiert werden. Je nach Kontext bevorzugen Sie jedoch möglicherweise die Implementierung der Strategie mithilfe eines klassenbasierten Ansatzes, z. B. wenn die Strategien selbst recht kompliziert sind und / oder die Struktur gemeinsam nutzen, die Sie mithilfe der Vorlagenmethode modellieren möchten.
Nach meiner Erfahrung in einer Multi-Paradigmen-Sprache (Ruby) funktioniert die FP-Implementierung in einfachen Fällen gut, aber wenn der Kontext komplizierter ist, passt der GoF OOP-basierte Ansatz besser.
Der FP-Ansatz ersetzt den OOP-Ansatz nicht, sondern ergänzt ihn.
quelle
Das wichtigste Merkmal der funktionalen Programmierung, IMHO, ist, dass Sie nur mit Ausdrücken programmieren - Ausdrücken innerhalb von Ausdrücken innerhalb von Ausdrücken, die alle bis zum letzten, endgültigen Ausdruck ausgewertet werden, der "die Maschine bei der Auswertung erwärmt".
Das wichtigste Merkmal der objektorientierten Programmierung, IMHO, ist, dass Sie mit Objekten programmieren, die einen internen Status haben. Sie können keinen internen Zustand in reinen Funktionen haben - objektorientierte Programmiersprachen benötigen Anweisungen , um Dinge geschehen zu lassen. (Es gibt keine Anweisungen in der funktionalen Programmierung.)
Sie vergleichen Äpfel mit Orangen. Die Muster der objektorientierten Programmierung gelten nicht für die Funktionsprogrammierung, da die funktionale Programmierung mit Ausdrücken programmiert und die objektorientierte Programmierung mit internem Zustand programmiert.
quelle
Machen Sie sich bereit.
Es wird viele erschweren, wenn ich behaupte, Designmuster ersetzt und SOLID und DRY entlarvt zu haben. Ich bin niemand. Trotzdem habe ich die kollaborative (Fertigungs-) Architektur korrekt modelliert und die Regeln für Bauprozesse online zusammen mit dem Code und der Wissenschaft dahinter auf meiner Website http://www.powersemantics.com/ veröffentlicht .
Mein Argument ist, dass Entwurfsmuster versuchen, das zu erreichen, was die Fertigung "Massenanpassung" nennt, eine Prozessform, in der jeder Schritt umgestaltet, neu zusammengesetzt und erweitert werden kann. Sie können sich solche Prozesse als nicht kompilierte Skripte vorstellen. Ich werde mein (Online-) Argument hier nicht wiederholen. Kurz gesagt, meine Massenanpassungsarchitektur ersetzt Entwurfsmuster, indem sie diese Flexibilität ohne die chaotische Semantik erreicht. Ich war überrascht, dass mein Modell so gut funktioniert hat, aber die Art und Weise, wie Programmierer Code schreiben, lässt einfach keinen Einfluss darauf, wie die Fertigung die Zusammenarbeit organisiert.
Diese Architektur muss nie umgestaltet werden. Es gibt auch Regeln für die Zentralisierung und Verteilung, die sich auf die Komplexität auswirken. Um Ihre Frage zu beantworten, ist die funktionale Programmierung ein weiterer Satz von Verarbeitungssemantiken, keine Architektur für benutzerdefinierte Massenprozesse, bei denen 1) das Quellrouting als (Skript-) Dokument vorliegt, das der Benutzer vor dem Auslösen neu schreiben kann, und 2) Module einfach und einfach sein können dynamisch hinzugefügt oder entfernt.
Wir könnten sagen, dass OOP das Paradigma des "hartcodierten Prozesses" ist und dass Entwurfsmuster Wege sind, dieses Paradigma zu vermeiden. Aber genau darum geht es bei der Massenanpassung. Entwurfsmuster verkörpern dynamische Prozesse als chaotischen Hardcode. Es hat einfach keinen Sinn. Die Tatsache, dass F # das Übergeben von Funktionen als Parameter ermöglicht, bedeutet, dass funktionale und OOP- Sprachen gleichermaßen versuchen, eine Massenanpassung selbst durchzuführen.
Wie verwirrend ist das für den Leser, Hardcode, der das Skript darstellt? Überhaupt nicht, wenn Sie glauben, dass die Konsumenten Ihres Compilers für solche Funktionen bezahlen, aber für mich sind solche Funktionen semantische Verschwendung. Sie sind sinnlos, da der Punkt der Massenanpassung darin besteht, Prozesse selbst dynamisch zu gestalten und nicht nur für den Programmierer, der Visual Studio verwendet, dynamisch zu sein.
quelle
Dies bedeutet, dass ein funktionaler PL auf hoher Ebene (wie OCaml mit Klassen, Modulen usw.) die zwingenden OOP-Sprachen in Bezug auf Typvielfalt und Ausdruckskraft zweifellos ersetzt. Die Abstraktionen lecken nicht, Sie können die meisten Ihrer Ideen direkt im Programm ausdrücken. Daher ersetzt es ja Entwurfsmuster, von denen die meisten im Vergleich zu Funktionsmustern sowieso lächerlich simpel sind.
quelle