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:
Die Wahl der Programmiersprache ist wichtig, da sie den eigenen Standpunkt beeinflusst. Unsere Muster setzen Sprachfunktionen auf Smalltalk / C ++ - Ebene voraus, und diese Auswahl bestimmt, was einfach implementiert werden kann und was nicht. Wenn wir prozedurale Sprachen angenommen hätten, hätten wir möglicherweise Entwurfsmuster mit den Namen "Vererbung", "Kapselung" und "Polymorphismus" aufgenommen. In ähnlicher Weise werden einige unserer Muster direkt von den weniger verbreiteten objektorientierten Sprachen unterstützt. CLOS verfügt beispielsweise über mehrere Methoden, die die Notwendigkeit eines Musters wie "Besucher" verringern. Tatsächlich gibt es genug Unterschiede zwischen Smalltalk und C ++, um zu bedeuten, dass einige Muster in einer Sprache leichter ausgedrückt werden können als in der anderen. (Siehe zum Beispiel Iterator.)
(Das Obige ist ein Zitat aus dem Buch Einführung in das Entwurfsmuster, Seite 4, Absatz 3)
Zu den Hauptmerkmalen der funktionalen Programmierung 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.
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.
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.
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.
Stimmt die Behauptung, dass durch funktionale Programmierung keine OOP-Entwurfsmuster mehr erforderlich sind?
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. ;)