简体   繁体   English

函数式编程会取代 GoF 设计模式吗?

[英]Does functional programming replace GoF design patterns?

Since I started learningF# and OCaml last year, I've read a huge number of articles which insist that design patterns (especially in Java) are workarounds for the missing features in imperative languages.自从我去年开始学习F#OCaml以来,我已经阅读了大量文章,这些文章坚持认为设计模式(尤其是在 Java 中)是命令式语言中缺少的功能的解决方法。 One article I found makes a fairly strong claim :我发现的一篇文章提出了相当强烈的主张

Most people I've met have read the Design Patterns book by the Gang of Four (GoF).我遇到的大多数人都读过四人帮 (GoF)的设计模式一书 Any self respecting programmer will tell you that the book is language agnostic and the patterns apply to software engineering in general, regardless of which language you use.任何有自尊的程序员都会告诉你,这本书与语言无关,而且这些模式通常适用于软件工程,无论你使用哪种语言。 This is a noble claim.这是一个崇高的主张。 Unfortunately it is far removed from the truth.不幸的是,它与事实相去甚远。

Functional languages are extremely expressive.函数式语言极具表现力。 In a functional language one does not need design patterns because the language is likely so high level, you end up programming in concepts that eliminate design patterns all together.在函数式语言中,不需要设计模式,因为该语言可能非常高级,您最终会以完全消除设计模式的概念进行编程。

The main features of functional programming (FP) include functions as first-class values, currying, immutable values, etc. It doesn't seem obvious to me that OO design patterns are approximating any of those features.函数式编程 (FP) 的主要特征包括作为一等值的函数、柯里化、不可变值等。对我来说,OO 设计模式似乎并不明显接近这些特征中的任何一个。

Additionally, in functional languages which support OOP (such as F# and OCaml), it seems obvious to me that programmers using these languages would use the same design patterns found available to every other OOP language.此外,在支持 OOP 的函数式语言中(例如 F# 和 OCaml),在我看来,使用这些语言的程序员显然会使用与所有其他 ZCE4195DA808656BEAE0C97FED9194192 语言相同的设计模式。 In fact, right now I use F# and OCaml every day, and there are no striking differences between the patterns I use in these languages vs. the patterns I use when I write in Java.事实上,现在我每天都在使用 F# 和 OCaml,我在这些语言中使用的模式与我在 Java 中使用的模式之间没有显着差异。

Is there any truth to the claim that functional programming eliminates the need for OOP design patterns?函数式编程消除了对 OOP 设计模式的需求的说法有道理吗? If so, could you post or link to an example of a typical OOP design pattern and its functional equivalent?如果是这样,您能否发布或链接到典型 OOP 设计模式及其等效功能的示例?

The blog post you quoted overstates its claim a bit.您引用的博客文章夸大了它的主张。 FP doesn't eliminate the need for design patterns. FP 并没有消除对设计模式的需求。 The term "design patterns" just isn't widely used to describe the same thing in FP languages.术语“设计模式”并未广泛用于描述 FP 语言中的相同事物。 But they exist.但它们存在。 Functional languages have plenty of best practice rules of the form "when you encounter problem X, use code that looks like Y", which is basically what a design pattern is.函数式语言有很多最佳实践规则,例如“当你遇到问题 X 时,使用看起来像 Y 的代码”,这基本上就是设计模式。

However, it's correct that most OOP-specific design patterns are pretty much irrelevant in functional languages.然而,大多数 OOP 特定的设计模式在函数式语言中几乎无关紧要,这是正确的。

I don't think it should be particularly controversial to say that design patterns in general only exist to patch up shortcomings in the language.我认为说设计模式通常只是为了弥补语言中的缺点而存在,这应该不是特别有争议的。 And if another language can solve the same problem trivially, that other language won't have need of a design pattern for it.如果另一种语言可以简单地解决同样的问题,那另一种语言就不需要设计模式了。 Users of that language may not even be aware that the problem exists , because, well, it's not a problem in that language.该语言的用户甚至可能不知道存在问题,因为,好吧,这不是该语言的问题。

Here is what the Gang of Four has to say about this issue:以下是四人帮对这个问题的看法:

The choice of programming language is important because it influences one's point of view.编程语言的选择很重要,因为它会影响一个人的观点。 Our patterns assume Smalltalk/C++-level language features, and that choice determines what can and cannot be implemented easily.我们的模式假设 Smalltalk/C++ 级别的语言特性,而这种选择决定了哪些可以轻松实现,哪些不能轻松实现。 If we assumed procedural languages, we might have included design patterns called "Inheritance", "Encapsulation," and "Polymorphism".如果我们假设是过程语言,我们可能已经包含了称为“继承”、“封装”和“多态”的设计模式。 Similarly, some of our patterns are supported directly by the less common object-oriented languages.类似地,我们的一些模式直接由不太常见的面向对象语言支持。 CLOS has multi-methods, for example, which lessen the need for a pattern such as Visitor.例如,CLOS 有多种方法,可以减少对诸如访问者之类的模式的需求。 In fact, there are enough differences between Smalltalk and C++ to mean that some patterns can be expressed more easily in one language than the other.事实上,Smalltalk 和 C++ 之间有足够的差异,这意味着某些模式可以用一种语言比另一种更容易表达。 (See Iterator for example.) (例如,参见迭代器。)

(The above is a quote from the Introduction to the Design Patterns book, page 4, paragraph 3) (以上引自《设计模式简介》一书,第 4 页,第 3 段)

The main features of functional programming include functions as first-class values, currying, immutable values, etc. It doesn't seem obvious to me that OO design patterns are approximating any of those features.函数式编程的主要特征包括函数作为一等值、currying、不可变值等。对我来说,OO 设计模式似乎并不明显接近这些特征中的任何一个。

What is the command pattern, if not an approximation of first-class functions?:) In an FP language, you'd simply pass a function as the argument to another function.如果不是一等函数的近似值,命令模式是什么?:) 在 FP 语言中,您只需将 function 作为参数传递给另一个 function。 In an OOP language, you have to wrap up the function in a class, which you can instantiate and then pass that object to the other function. In an OOP language, you have to wrap up the function in a class, which you can instantiate and then pass that object to the other function. The effect is the same, but in OOP it's called a design pattern, and it takes a whole lot more code.效果是一样的,但是在 OOP 中它被称为设计模式,它需要更多的代码。 And what is the abstract factory pattern, if not currying?如果不是柯里化,那么抽象工厂模式是什么? Pass parameters to a function a bit at a time, to configure what kind of value it spits out when you finally call it.一次一点地将参数传递给 function,以配置当您最终调用它时它会吐出什么样的值。

So yes, several GoF design patterns are rendered redundant in FP languages, because more powerful and easier to use alternatives exist.所以是的,一些 GoF 设计模式在 FP 语言中显得多余,因为存在更强大和更易于使用的替代方案。

But of course there are still design patterns which are not solved by FP languages.但是当然还有一些设计模式是 FP 语言无法解决的。 What is the FP equivalent of a singleton? singleton 的 FP 等效项是多少? (Disregarding for a moment that singletons are generally a terrible pattern to use.) (暂时忽略单例通常是一种糟糕的使用模式。)

And it works both ways too.它也适用于两种方式。 As I said, FP has its design patterns too;正如我所说,FP 也有它的设计模式。 people just don't usually think of them as such.人们只是通常不这么认为。

But you may have run across monads.但是你可能遇到过单子。 What are they, if not a design pattern for "dealing with global state"?如果不是“处理全局状态”的设计模式,它们是什么? That's a problem that's so simple in OOP languages that no equivalent design pattern exists there.这是一个在 OOP 语言中非常简单的问题,以至于那里不存在等效的设计模式。

We don't need a design pattern for "increment a static variable", or "read from that socket", because it's just what you do .我们不需要“增加 static 变量”或“从该套接字读取”的设计模式,因为这正是您所做的。

Saying a monad is a design pattern is as absurd as saying the Integers with their usual operations and zero element is a design pattern.说 monad 是一种设计模式就像说具有通常操作的整数和零元素是一种设计模式一样荒谬。 No, a monad is a mathematical pattern , not a design pattern.不,monad 是一种数学模式,而不是设计模式。

In (pure) functional languages, side effects and mutable state are impossible, unless you work around it with the monad "design pattern", or any of the other methods for allowing the same thing.在(纯)函数式语言中,副作用和可变 state 是不可能的,除非您使用 monad“设计模式”或任何其他允许相同事物的方法来解决它。

Additionally, in functional languages which support OOP (such as F# and OCaml), it seems obvious to me that programmers using these languages would use the same design patterns found available to every other OOP language.此外,在支持 OOP 的函数式语言中(例如 F# 和 OCaml),在我看来,使用这些语言的程序员显然会使用与所有其他 ZCE4195DA808656BEAE0C97FED9194192 语言相同的设计模式。 In fact, right now I use F# and OCaml everyday, and there are no striking differences between the patterns I use in these languages vs the patterns I use when I write in Java.事实上,现在我每天都使用 F# 和 OCaml,我在这些语言中使用的模式与我在 Java 中使用的模式之间没有显着差异。

Perhaps because you're still thinking imperatively?也许是因为你仍然在思考? A lot of people, after dealing with imperative languages all their lives, have a hard time giving up on that habit when they try a functional language.很多人在一生都在处理命令式语言之后,在尝试使用函数式语言时很难放弃这种习惯。 (I've seen some pretty funny attempts at F#, where literally every function was just a string of 'let' statements, basically as if you'd taken a C program, and replaced all semicolons with 'let'.:)) (I've seen some pretty funny attempts at F#, where literally every function was just a string of 'let' statements, basically as if you'd taken a C program, and replaced all semicolons with 'let'.:))

But another possibility might be that you just haven't realized that you're solving problems trivially which would require design patterns in an OOP language.但另一种可能性可能是您还没有意识到您正在解决琐碎的问题,这需要 OOP 语言中的设计模式。

When you use currying, or pass a function as an argument to another, stop and think about how you'd do that in an OOP language.当您使用柯里化,或将 function 作为参数传递给另一个时,请停下来考虑如何在 OOP 语言中执行此操作。

Is there any truth to the claim that functional programming eliminates the need for OOP design patterns?函数式编程消除了对 OOP 设计模式的需求的说法有道理吗?

Yep.:) When you work in a FP language, you no longer need the OOP-specific design patterns.是的。:) 当您使用 FP 语言工作时,您不再需要特定于 OOP 的设计模式。 But you still need some general design patterns, like MVC or other non-OOP specific stuff, and you need a couple of new FP-specific "design patterns" instead.但是您仍然需要一些通用设计模式,例如 MVC 或其他非 OOP 特定的东西,并且您需要一些新的 FP 特定的“设计模式”。 All languages have their shortcomings, and design patterns are usually how we work around them.所有语言都有其缺点,设计模式通常是我们解决它们的方式。

Anyway, you may find it interesting to try your hand at "cleaner" FP languages, like ML (my personal favorite, at least for learning purposes), orHaskell , where you don't have the OOP crutch to fall back on when you're faced with something new.无论如何,您可能会发现尝试“更干净”的 FP 语言很有趣,例如ML (我个人最喜欢,至少用于学习目的)或Haskell ,当您没有 OOP 拐杖时'面临着新的事物。


As expected, a few people objected to my definition of design patterns as "patching up shortcomings in a language", so here's my justification:正如所料,一些人反对我将设计模式定义为“修补语言中的缺点”,所以这是我的理由:

As already said, most design patterns are specific to one programming paradigm, or sometimes even one specific language.如前所述,大多数设计模式都特定于一种编程范式,有时甚至是一种特定的语言。 Often, they solve problems that only exist in that paradigm (see monads for FP, or abstract factories for OOP).通常,它们解决仅存在于该范式中的问题(参见 FP 的 monad,或 OOP 的抽象工厂)。

Why doesn't the abstract factory pattern exist in FP?为什么 FP 中不存在抽象工厂模式? Because the problem it tries to solve does not exist there.因为它试图解决的问题在那里不存在。

So, if a problem exists in OOP languages, which does not exist in FP languages, then clearly that is a shortcoming of OOP languages.所以,如果OOP语言存在问题,而FP语言不存在,那么显然这是OOP语言的缺点。 The problem can be solved, but your language does not do so, but requires a bunch of boilerplate code from you to work around it.问题可以解决,但您的语言并没有这样做,而是需要您提供一堆样板代码来解决它。 Ideally, we'd like our programming language to magically make all problems go away.理想情况下,我们希望我们的编程语言能够神奇地解决 go 的所有问题。 Any problem that is still there is in principle a shortcoming of the language.;)原则上仍然存在的任何问题都是语言的缺点。;)

Is there any truth to the claim that functional programming eliminates the need for OOP design patterns?函数式编程消除了对 OOP 设计模式的需求的说法有道理吗?

Functional programming is not the same as object-oriented programming.函数式编程与面向对象编程不同。 Object-oriented design patterns don't apply to functional programming.面向对象的设计模式不适用于函数式编程。 Instead, you have functional programming design patterns.相反,您拥有函数式编程设计模式。

For functional programming, you won't read the OO design pattern books;对于函数式编程,您不会阅读 OO 设计模式书籍; you'll read other books on FP design patterns.您将阅读其他有关 FP 设计模式的书籍。

language agnostic语言不可知论者

Not totally.不完全。 Only language-agnostic with respect to OO languages.只有 language-agnostic 与 OO 语言有关。 The design patterns don't apply to procedural languages at all.设计模式根本不适用于过程语言。 They barely make sense in a relational database design context.它们在关系数据库设计环境中几乎没有意义。 They don't apply when designing a spreadsheet.它们在设计电子表格时不适用。

a typical OOP design pattern and its functional equivalent?典型的 OOP 设计模式及其等效功能?

The above shouldn't exist.以上不应该存在。 That's like asking for a piece of procedural code rewritten as OO code.这就像要求将一段程序代码重写为 OO 代码一样。 Ummm... If I translate the original Fortran (or C) into Java, I haven't done anything more than translate it.嗯...如果我将原来的 Fortran(或 C)翻译成 Java,我除了翻译它什么也没做。 If I totally rewrite it into an OO paradigm, it will no longer look anything like the original Fortran or C -- it will be unrecognizable.如果我将它完全重写为 OO 范式,它将不再像原来的 Fortran 或 C 那样 - 它将无法识别。

There's no simple mapping from OO design to functional design.从 OO 设计到功能设计没有简单的映射。 They're very different ways of looking at the problem.他们看待问题的方式非常不同。

Functional programming (like all styles of programming) has design patterns.函数式编程(就像所有styles 的编程一样)具有设计模式。 Relational databases have design patterns, OO has design patterns, and procedural programming has design patterns.关系数据库有设计模式,OO 有设计模式,过程编程有设计模式。 Everything has design patterns, even the architecture of buildings.一切都有设计模式,甚至建筑物的架构。

Design patterns -- as a concept -- are a timeless way of building, irrespective of technology or problem domain.设计模式——作为一个概念——是一种永恒的构建方式,与技术或问题领域无关。 However, specific design patterns apply to specific problem domains and technologies.但是,特定的设计模式适用于特定的问题域和技术。

Everyone who thinks about what they're doing will uncover design patterns.每个思考自己在做什么的人都会发现设计模式。

Brian's comments on the tight linkage between language and pattern is to the point,布赖恩对语言和模式之间紧密联系的评论很中肯,

The missing part of this discussion is the concept of idiom.这个讨论中缺少的部分是成语的概念。 James O. Coplien's book, "Advanced C++" was a huge influence here. James O. Coplien 的书“Advanced C++”在这里产生了巨大的影响。 Long before he discovered Christopher Alexander and the Column Without a Name (and you can't talk sensibly about patterns without reading Alexander either), he talked about the importance of mastering idioms in truly learning a language.早在他发现 Christopher Alexander 和无名专栏之前(如果不阅读 Alexander,您也无法明智地谈论模式),他就谈到了掌握成语对于真正学习语言的重要性。 He used string copy in C as an example, while(*from++ = *to++);他以C中的string拷贝为例, while(*from++ = *to++); You can see this as a bandaid for a missing language feature (or library feature), but what really matters about it is that it's a larger unit of thought, or of expression, than any of its parts.您可以将其视为缺少语言功能(或库功能)的创可贴,但真正重要的是,它是一个比任何部分都更大的思想或表达单元。

That is what patterns, and languages, are trying to do, to allow us to express our intentions more succinctly.这就是模式和语言试图做的事情,让我们更简洁地表达我们的意图。 The richer the units of thought the more complex the thoughts you can express.思想单位越丰富,你能表达的思想就越复杂。 Having a rich, shared vocabulary at a range of scales - from system architecture down to bit twiddling - allows us to have more intelligent conversations, and thoughts about what we should be doing.拥有一个范围广泛的丰富的、共享的词汇表——从系统架构到小游戏——让我们能够进行更智能的对话,并思考我们应该做什么。

We can also, as individuals, learn.作为个人,我们也可以学习。 Which is the entire point of the exercise.这是整个练习的重点。 We each can understand and use things we would never be able to think of ourselves.我们每个人都可以理解和使用我们永远无法想到的东西。 Languages, frameworks, libraries, patterns, idioms and so on all have their place in sharing the intellectual wealth.语言、框架、库、模式、习语等都在分享知识财富方面占有一席之地。

The GoF book explicitly ties itself to OOP - the title is Design Patterns - Elements of Reusable Object-Oriented Software (emphasis mine). GoF 书明确地将自己与 OOP 联系在一起——标题是 Design Patterns - Elements of Reusable Object-Oriented Software(重点是我的)。

Design Patterns in Dynamic Programming by Peter Norvig has thoughtful coverage of this general theme, though about 'dynamic' languages instead of 'functional' (there's overlap). Peter Norvig的动态编程中的设计模式对这个一般主题进行了深思熟虑的报道,尽管是关于“动态”语言而不是“功能”语言(有重叠)。

Here's another link, discussing this topic: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/这是另一个链接,讨论这个话题: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

In his blog post Edward describes all 23 original GoF patterns in terms of Haskell.在他的博文中,Edward 根据 Haskell 描述了所有 23 种原始 GoF 模式。

When you try to look at this at the level of "design patterns" (in general) and "FP versus OOP", the answers you'll find will be murky at best.当您尝试从“设计模式”(一般)和“FP 与 OOP”的层面来看待这个问题时,您会发现的答案充其量是模糊的。

Go a level deeper on both axes, though, and consider specific design patterns and specific language features and things become clearer.不过,Go 在两个轴上都更深一层,考虑到特定的设计模式特定的语言特性,事情就会变得更加清晰。

So, for example, some specific patterns, like Visitor , Strategy , Command , and Observer definitely change or disappear when using a language with algebraic data types and pattern matching , closures , first class functions , etc. Some other patterns from the GoF book still 'stick around', though.因此,例如,当使用具有代数数据类型和模式匹配闭包第一个 class 函数等的语言时,某些特定模式,如VisitorStrategyCommandObserver肯定会改变或消失。GoF 书中的一些其他模式仍然不过,“坚持”。

In general, I would say that, over time, specific patterns are being eliminated by new (or just rising-in-popularity) language features.一般来说,我会说,随着时间的推移,特定的模式正在被新的(或只是越来越流行的)语言特性所消除。 This is the natural course of language design;这是语言设计的自然过程; as languages become more high-level, abstractions that could previously only be called out in a book using examples now become applications of a particular language feature or library.随着语言变得更加高级,以前只能在书中使用示例调用的抽象现在成为特定语言功能或库的应用程序。

(Aside: here's a recent blog I wrote, which has other links to more discussion on FP and design patterns.) (除此之外:这是我最近写的一篇博客,其中包含更多关于 FP 和设计模式的讨论的其他链接。)

I would say that when you have a language like Lisp with its support for macros, then you can build you own domain-specific abstractions, abstractions which often are much better than the general idiom solutions.我想说的是,当您拥有像 Lisp 这样支持宏的语言时,您可以构建自己的特定领域抽象,这些抽象通常比一般的成语解决方案要好得多。

Norvig's presentation alludes to an analysis they did of all the GoF patterns, and they say that 16 of the 23 patterns had simpler implementations in functional languages, or were simply part of the language. Norvig 的演讲暗示了他们对所有 GoF 模式所做的分析,他们说 23 种模式中有 16 种在函数式语言中具有更简单的实现,或者只是语言的一部分。 So presumably at least seven of them either were a) equally complicated or b) not present in the language.所以大概至少有七个是a)同样复杂或b)不存在于语言中。 Unfortunately for us, they are not enumerated对我们来说不幸的是,它们没有被列举

I think it's clear that most of the "creational" or "structural" patterns in GoF are merely tricks to get the primitive type systems in Java or C++ to do what you want.我认为很明显,GoF 中的大多数“创建”或“结构”模式只是让 Java 或 C++ 中的原始类型系统做你想做的事情的技巧。 But the rest are worthy of consideration no matter what language you program in.但是无论您使用哪种语言编程,rest 都值得考虑。

One might be Prototype;一个可能是原型; while it is a fundamental notion of JavaScript, it has to be implemented from scratch in other languages.虽然它是 JavaScript 的基本概念,但它必须在其他语言中从头开始实现。

One of my favorite patterns is the Null Object pattern: represent the absence of something as an object that does an appropriate kind of nothing.我最喜欢的模式之一是 Null Object 模式:表示没有某种东西,就像 object 一样,它什么都不做。 This may be easier to model in a functional language.这在函数式语言中可能更容易 model。 However, the real achievement is the shift in perspective.然而,真正的成就是视角的转变。

And even the OO design pattern solutions are language specific.甚至 OO 设计模式解决方案也是特定于语言的。

Design patterns are solutions to common problems that your programming language doesn't solve for you.设计模式是您的编程语言无法为您解决的常见问题的解决方案。 In Java, the Singleton pattern solves the one-of-something (simplified) problem.在 Java 中,Singleton 模式解决了单一事物(简化)问题。

In Scala, you have a top level construct called Object in addition to Class.在 Scala 中,除了 Class 之外,还有一个名为 Object 的顶级构造。 It's lazily instantiated and there is only one.You don't have to use the Singleton pattern to get a Singleton.它是惰性实例化的,只有一个。您不必使用 Singleton 模式来获得 Singleton。 It's part of the language.这是语言的一部分。

Patterns are ways of solving similar problems that get seen again and again, and then get described and documented.模式是解决类似问题的方法,这些问题反复出现,然后被描述和记录。 So no, FP is not going to replace patterns;所以不,FP 不会取代模式。 however, FP might create new patterns, and make some current "best practices" patterns "obsolete".但是,FP 可能会创建新模式,并使某些当前的“最佳实践”模式“过时”。

The GoF Design Patterns is coding workaround recipes for OO languages that are descendants of Simula 67 , like Java and C++. GoF设计模式正在为作为Simula 67后代的 OO 语言编写变通方案,例如 Java 和 C++。

Most of the "ills" treated by the design patterns are caused by:设计模式处理的大多数“弊病”是由以下原因引起的:

  • statically typed classes, which specify objects, but are not themselves objects;静态类型的类,它指定对象,但它们本身不是对象;
  • restriction to single dispatch (only the leftmost argument is used to select a method, the remaining arguments are considered as static types only: if they have dynamic types, it's up to the method to sort that out with ad-hoc approaches);限制为单一调度(仅最左边的参数用于 select 一种方法,其余的 arguments 被视为 static 类型:如果它们具有动态类型,则仅使用 ad-hoc 方法进行排序;
  • distinction between regular function calls and object-oriented function calls, meaning that object-oriented functions cannot be passed as functional arguments where regular functions are expected and vice versa;常规 function 调用和面向对象的 function 调用之间的区别,这意味着面向对象的函数不能作为函数式 arguments 传递,而需要常规函数,反之亦然; and
  • distinction between "base types" and "class types". “基本类型”和“类类型”之间的区别。

There isn't a single one of these design patterns that doesn't disappear in the Common Lisp Object System, even though the solution is structured in essentially the same way as in the corresponding design pattern.这些设计模式中没有一个不会在 Common Lisp Object 系统中消失,即使解决方案的结构与相应的设计模式基本相同。 (Moreover, that object system precedes the GoF book by well over a decade. Common Lisp became an ANSI standard the same year that that book was first published.) (此外,object 系统比 GoF 书早了十多年。Common Lisp 在该书首次出版的同一年成为 ANSI 标准。)

As far as functional programming is concerned, whether or not the patterns apply to it depends on whether the given functional programming language has some kind of object system, and whether it is modeled after the object systems which benefit from the patterns.就函数式编程而言,模式是否适用于它取决于给定的函数式编程语言是否具有某种 object 系统,以及是否仿照受益于模式的 object 系统。 That type of object-orientation does not mix well with functional programming, because the mutation of state is at the front and centre.这种面向对象的类型不能很好地与函数式编程混合,因为 state 的突变位于前面和中间。

Construction and non-mutating access are compatible with functional programming, and so patterns which have to do with abstracting access or construction could be applicable: patterns like Factory, Facade, Proxy, Decorator, and Visitor.构造和非可变访问与函数式编程兼容,因此与抽象访问或构造有关的模式可能适用:工厂、外观、代理、装饰器和访问者等模式。

On the other hand, the behavioral patterns like State and Strategy probably do not directly apply in functional OOP because mutation of state is at their core.另一方面,像 State 和 Strategy 这样的行为模式可能并不直接适用于功能性 OOP,因为 state 的突变是其核心。 This doesn't mean they don't apply;这并不意味着它们不适用; perhaps they somehow apply in combination with whatever tricks are available for simulating mutable state.也许它们以某种方式与任何可用于模拟可变 state 的技巧结合使用。

As others have said, there are patterns specific to functional programming.正如其他人所说,有一些特定于函数式编程的模式。 I think the issue of getting rid of design patterns is not so much a matter of switching to functional, but a matter of language features .我认为摆脱设计模式的问题与其说是切换到函数式的问题,不如说是语言特性的问题。

Take a look at how Scala does away with the "singleton pattern": you simply declare an object instead of a class.看看 Scala 如何消除“单例模式”:您只需声明object而不是 class。 Another feature, pattern matching, helps avoiding the clunkiness of the visitor pattern.另一个特性,模式匹配,有助于避免访问者模式的笨拙。 See the comparison here: Scala's Pattern Matching = Visitor Pattern on Steroids在此处查看比较: Scala 的模式匹配 = 类固醇上的访问者模式

And Scala, like F#, is a fusion of OO-functional.而Scala和F#一样,是OO功能的融合。 I don't know about F#, but it probably has these kind of features.我不知道 F#,但它可能具有这些功能。

Closures are present in functional language, but they need not be restricted to them.闭包存在于函数式语言中,但它们不必局限于它们。 They help with the delegator pattern.它们有助于使用委托人模式。

One more observation.再来一个观察。 This piece of code implements a pattern: it's such a classic and it's so elemental that we don't usually think of it as a "pattern", but it sure is:这段代码实现了一个模式:它是如此经典且如此基本,以至于我们通常不会将其视为“模式”,但它确实是:

 for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }

Imperative languages like Java and C# have adopted what is essentially a functional construct to deal with this: "foreach".命令式语言,如 Java 和 C# 采用了本质上是一种函数式构造来处理这个问题:“foreach”。

I'd like to plug a couple of excellent but somewhat dense papers by Jeremy Gibbons: "Design patterns as higher-order datatype-generic programs" and "The essence of the Iterator pattern" (both available here: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/ ).我想插入几篇杰里米·吉本斯(Jeremy Gibbons)的优秀但有些密集的论文:“将模式设计为​​高阶数据类型通用程序”和“迭代器模式的本质”(均可在此处获得: http://www. comlab.ox.ac.uk/jeremy.gibbons/publications/ )。

These both describe how idiomatic functional constructs cover the terrain that is covered by specific design patterns in other (object-oriented) settings.这些都描述了惯用的功能构造如何覆盖其他(面向对象)设置中特定设计模式所覆盖的领域。

You can't have this discussion without bringing up type systems.如果不提出类型系统,就无法进行此讨论。

The main features of functional programming include functions as first-class values, currying, immutable values, etc. It doesn't seem obvious to me that OO design patterns are approximating any of those features.函数式编程的主要特征包括函数作为一等值、currying、不可变值等。对我来说,OO 设计模式似乎并不明显接近这些特征中的任何一个。

That's because these features don't address the same issues that OOP does... they are alternatives to imperative programming.那是因为这些功能没有解决 OOP 所做的相同问题......它们是命令式编程的替代方案。 The FP answer to OOP lies in the type systems of ML and Haskell... specifically sum types, abstract data types, ML modules, and Haskell typeclasses. OOP 的 FP 答案在于 ML 和 Haskell 的类型系统......特别是 sum 类型、抽象数据类型、ML 模块和 Haskell 类型类。

But of course there are still design patterns which are not solved by FP languages.但是当然还有一些设计模式是 FP 语言无法解决的。 What is the FP equivalent of a singleton? singleton 的 FP 等效项是多少? (Disregarding for a moment that singletons are generally a terrible pattern to use) (暂时忽略单例通常是一种糟糕的使用模式)

The first thing typeclasses do is eliminate the need for singletons.类型类做的第一件事是消除对单例的需求。

You could go through the list of 23 and eliminate more, but I don't have time to right now.您可以通过 23 的列表 go 并消除更多,但我现在没有时间。

I think only two GoF Design Patterns are designed to introduce the functional programming logic into natural OO language.我认为只有两个 GoF 设计模式旨在将函数式编程逻辑引入自然 OO 语言。 I think about Strategy and Command.我想到了战略和指挥。 Some of the other GoF design patterns can be modified by functional programming to simplify the design and keep the purpose.其他一些 GoF 设计模式可以通过函数式编程进行修改,以简化设计并保持目的。

Essentially, yes !本质上,的!

  • When a pattern circumvents the missing features (high order functions, stream handling...) that ultimalty facilitate composition .当一个模式绕过最终促进合成的缺失特征(高阶函数、 stream处理......)时。
  • The need to re-write patterns' implementation again and again can itself be seen as a language smell .一次又一次地重写模式实现的需要本身可以被视为一种语言气味

Besides, thispage (AreDesignPatternsMissingLanguageFeatures) provides a "pattern/feature" translation table and some nice discussions, if you are willing to dig.此外,这个页面(AreDesignPatternsMissingLanguageFeatures)提供了一个“模式/特征”翻译表和一些很好的讨论,如果你愿意挖掘的话。

In the new 2013 book named "Functional Programming Patterns- in Scala and Clojure" the author Michael.B.在 2013 年新书名为“Functional Programming Patterns- in Scala 和 Clojure”中,作者 Michael.B. Linn does a decent job comparing and providing replacements in many cases for the GoF patterns and also discusses the newer functional patterns like 'tail recursion', 'memoization', 'lazy sequence', etc. Linn 在许多情况下对 GoF 模式进行了比较和提供替换,并且还讨论了新的功能模式,如“尾递归”、“记忆”、“惰性序列”等。

This book is available on Amazon.这本书在亚马逊上有售。 I found it very informative and encouraging when coming from an OO background of a couple of decades.当我拥有几十年的面向对象背景时,我发现它非常有用和令人鼓舞。

Functional programming does not replace design patterns.函数式编程不会取代设计模式。 Design patterns can not be replaced.设计模式是不可替代的。

Patterns simply exist;模式只是存在; they emerged over time.它们随着时间的推移而出现。 The GoF book formalized some of them. GoF 书将其中一些正式化了。 If new patterns are coming to light as developers use functional programming languages that is exciting stuff, and perhaps there will be books written about them as well.如果随着开发人员使用函数式编程语言而出现新模式,那是令人兴奋的事情,也许还会有关于它们的书籍。

OOP and the GoF patterns deal with states. OOP 和 GoF 模式处理状态。 OOP models reality to keep the code base as near as possible to the given requirements of reality. OOP 对现实进行建模,以使代码库尽可能接近给定的现实要求。 GoF design patterns are patterns that were identified to solve atomic real world problems. GoF 设计模式是被确定用于解决原子现实世界问题的模式。 They handle the problem of state in a semantic way.他们以语义的方式处理 state 的问题。

As in real functional programming no state exists, it does not make sense to apply the GoF patterns.由于在真正的函数式编程中不存在 state,因此应用 GoF 模式没有意义。 There are not functional design patterns in the same way there are GoF design patterns.没有功能性设计模式,就像有 GoF 设计模式一样。 Every functional design pattern is artifical in contrast to reality as functions are constructs of math and not reality.与现实相比,每个功能设计模式都是人工的,因为功能是数学而不是现实的构造。

Functions lack the concept of time as they are always return the same value whatever the current time is unless time is part of the function parameters what makes it really hard to prrocess "future requests".函数缺乏时间的概念,因为无论当前时间是什么,它们总是返回相同的值,除非时间是 function 参数的一部分,这使得处理“未来请求”变得非常困难。 Hybrid languages mix those concepts make the languages not real functional programming languages.混合语言混合了这些概念,使这些语言不是真正的函数式编程语言。

Functional languages are rising only because of one thing: the current natural restrictions of physics.函数式语言的兴起只是因为一件事:当前物理学的自然限制。 Todays processors are limited in their speed of processing instructions due to physical laws.由于物理定律,当今的处理器在处理指令的速度方面受到限制。 You see a stagnation in clock frequency but an expansion in processing cores.您会看到时钟频率停滞不前,但处理核心有所扩展。 That's why parallelism of instructions becomes more and more important to increase speed of modern applications.这就是为什么指令的并行性对于提高现代应用程序的速度变得越来越重要的原因。 As functional programming by definition has no state and therefore has no side effects it is safe to process functions safely in parallel.根据定义,函数式编程没有 state,因此没有副作用,因此安全地并行处理函数是安全的。

GoF patterns are not obsolete. GoF 模式并没有过时。 They are at least necessary to model the real world requirements.它们至少是现实世界的要求所必需的。 But if you use a functional programming language you have to transform them into their hybrid equivalents.但是,如果您使用函数式编程语言,则必须将它们转换为它们的混合等价物。 Finally you have no chance to make only functional programs if you use persistence.最后,如果您使用持久性,您将没有机会只制作功能性程序。 For the hybrid elements of your program there remains the necessity to use GoF patterns.对于程序的混合元素,仍然有必要使用 GoF 模式。 For any other element that is purely functional there is no necessity to use GoF patterns because there is no state.对于任何其他纯功能元素,没有必要使用 GoF 模式,因为没有 state。

Because the GoF patterns are not necessary for real functional programming, it doesn't mean that the SOLID principles should not be applied.因为真正的函数式编程不需要 GoF 模式,这并不意味着不应该应用 SOLID 原则。 The SOLID principles are beyond any language paradigm. SOLID 原则超越了任何语言范式。

As the accepted answer said, OOP and FP all have their specific patterns.正如公认的答案所说,OOP 和 FP 都有其特定的模式。

However, there are some patterns which are so common that all programming platforms I can think of should have.但是,有些模式非常普遍,我能想到的所有编程平台都应该有。 Here is an (incomplete) list:这是一个(不完整的)列表:

  • Adapter.适配器。 I can hardly think of a useful programming platform which is so comprehensive (and self-fulfilled) that it does not need to talk to the world.我几乎想不出一个有用的编程平台,它是如此全面(和自我实现)以至于它不需要与世界交谈。 If it is going to do so, an adapter is definitely needed.如果要这样做,肯定需要一个适配器。

  • Façade.正面。 Any programming platforms that can handle big source code should be able to modularise.任何可以处理大型源代码的编程平台都应该能够模块化。 If you were to create a module for other parts of the program, you will want to hide the "dirty" parts of the code and give it a nice interface.如果您要为程序的其他部分创建一个模块,您将希望隐藏代码的“脏”部分并为其提供一个漂亮的界面。

  • Interpreter.翻译。 In general, any program is just doing two things: parse input and print output.一般来说,任何程序都只做两件事:解析输入并打印 output。 Mouse inputs need to be parsed, and window widgets need to be printed out.需要解析鼠标输入,并且需要打印出 window 小部件。 Therefore, having an embedded interpreter gives the program additional power to customise things.因此,拥有一个嵌入式解释器为程序提供了额外的自定义事物的能力。

Also, I noticed in a typical FP language, Haskell, there is something similar to GoF patterns, but with different names.另外,我注意到在典型的 FP 语言 Haskell 中,有一些类似于 GoF 模式的东西,但名称不同。 In my opinion this suggest they were there because there are some common problems to solve in both FP and OOP languages.在我看来,这表明他们在那里,因为在 FP 和 OOP 语言中都有一些常见问题需要解决。

  • Monad transformer and decorator. Monad 变压器和装饰器。 The former used to add additional ability into an existing monad, the latter add additional ability to an existing object.前者用于为现有的 monad 添加额外的能力,后者为现有的 object 添加额外的能力。

I think that each paradigm serves a different purpose and as such cannot be compared in this way.我认为每种范式都有不同的目的,因此不能以这种方式进行比较。

I have not heard that the GoF design patterns are applicable to every language.我还没有听说 GoF 设计模式适用于所有语言。 I have heard that they are applicable to all OOP languages .我听说它们适用于所有OOP 语言 If you use functional programming then the domain of problems that you solve is different from OO languages.如果您使用函数式编程,那么您解决的问题领域与 OO 语言不同。

I wouldn't use functional language to write a user interface, but one of the OO languages like C# or Java would make this job easier.我不会使用函数式语言来编写用户界面,但是像 C# 或 Java 这样的 OO 语言之一会使这项工作更容易。 If I were writing a functional language then I wouldn't consider using OO design patterns.如果我正在编写一种函数式语言,那么我不会考虑使用 OO 设计模式。

OOP and FP have different goals. OOP和FP有不同的目标。 OOP aims to encapsulate the complexities/moving parts of software components and FP aims to minimize the complexity and dependencies of software components. OOP 旨在封装软件组件的复杂性/移动部分,FP 旨在最小化软件组件的复杂性和依赖性。

However these two paradigms are not necessarily 100% contradicting and could be applied together to get the benefit from both worlds.然而,这两种范式不一定是 100% 矛盾的,可以一起应用以从两个世界中受益。

Even with a language that does not natively support functional programming like C#, you could write functional code if you understand the FP principles.即使使用像 C# 这样本身不支持函数式编程的语言,如果您了解 FP 原理,您也可以编写函数式代码。 Likewise you could apply OOP principles using F# if you understand OOP principles, patterns, and best practices.同样,如果您了解 OOP 原则、模式和最佳实践,您可以使用 F# 应用 OOP 原则。 You would make the right choice based on the situation and problem that you try to solve, regardless of the programming language you use.无论您使用哪种编程语言,您都将根据您尝试解决的情况和问题做出正确的选择。

Some patterns are easier to implement in a language supporting FP.一些模式在支持 FP 的语言中更容易实现。 For example, Strategy can be implemented using nicely using closures.例如,策略可以很好地使用闭包来实现。 However depending on context, you may prefer to implement Strategy using a class-based approach, say where the strategies themselves are quite complicated and/or share structure that you want to model using Template Method.但是,根据上下文,您可能更喜欢使用基于类的方法来实现策略,比如策略本身非常复杂和/或共享您希望使用模板方法 model 的结构。

In my experience developing in a multi-paradigm language (Ruby), the FP implementation works well in simple cases, but where the context is more complicated the GoF OOP based approach is a better fit.根据我使用多范式语言 (Ruby) 开发的经验,FP 实现在简单的情况下运行良好,但在上下文更复杂的情况下,基于 GoF OOP 的方法更适合。

The FP approach does not replace the OOP approach, it complements it. FP 方法不会取代 OOP 方法,而是对其进行补充。

It does, in that a high-level functional PL (like OCaml, with classes, modules, etc.) certainly supersedes OOP imperative languages in type versatility and power of expression.确实如此,因为高级功能 PL(如 OCaml,具有类、模块等)在类型多功能性和表达能力方面肯定会取代 OOP 命令式语言。 The abstractions do not leak, you can express most of your ideas directly in the program.抽象不会泄漏,您可以直接在程序中表达您的大部分想法。 Therefore, yes, it does replace design patterns, most of which are ridiculously simplistic compared to functional patterns anyhow.因此,是的,它确实取代了设计模式,无论如何,与功能模式相比,大多数设计模式都过于简单化了。

In functional programming, design patterns have a different meaning.在函数式编程中,设计模式具有不同的含义。 In fact, most of OOP design patterns are unnecessary in functional programming because of the higher level of abstraction and HOFs used as building blocks.事实上,大多数OOP设计模式在函数式编程中是不必要的,因为更高级别的抽象和用作构建块的HOF

The principle of an HOF means that functions can be passed as arguments to other functions. HOF 的原理是指函数可以作为 arguments 传递给其他函数。 and functions can return values.并且函数可以返回值。

The paramount characteristic of functional programming, IMHO, is that you are programming with nothing but expressions -- expressions within expressions within expressions that all evaluate to the last, final expression that "warms the machine when evaluated".恕我直言,函数式编程的最重要特征是您只使用表达式进行编程 - 表达式中的表达式中的表达式都评估为最后一个“在评估时温暖机器”的最终表达式。

The paramount characteristic of object-oriented programming, IMHO is that you are programming with objects that have internal state.面向对象编程的最重要特征,恕我直言,您正在使用具有内部 state 的对象进行编程。 You cannot have internal state in pure functions -- object-oriented programming languages need statements to make things happen.您不能在纯函数中拥有内部 state —— 面向对象的编程语言需要语句才能使事情发生。 (There are no statements in functional programming.) (函数式编程中没有语句。)

You are comparing apples to oranges.您正在将苹果与橙子进行比较。 The patterns of object-oriented programming do not apply to function programming, because functional programming is programming with expressions, and object-oriented programming is programming with internal state.面向对象编程的模式不适用于 function 编程,因为函数式编程是用表达式编程,而面向对象编程是用内部 state 编程。

Brace yourselves.振作起来。

It will aggravate many to hear me claim to have replaced design patterns and debunked SOLID and DRY.听到我声称已经替换了设计模式并揭穿了 SOLID 和 DRY 的真相,会让很多人感到更加愤怒。 I'm nobody.我谁都不是。 Nevertheless, I correctly modeled collaborative (manufacturing) architecture and published the rules for building processes online along with the code and science behind it at my website http://www.powersemantics.com/ .尽管如此,我还是正确地建模了协作(制造)架构,并在我的网站http://www.powersemantics.com/上发布了在线构建流程的规则以及其背后的代码和科学。

My argument is that design patterns attempt to achieve what manufacturing calls "mass customization", a process form in which every step can be reshaped, recomposed and extended.我的论点是,设计模式试图实现制造业所称的“大规模定制”,这是一种每一步都可以重塑、重组和扩展的过程形式。 You might think of such processes as uncompiled scripts.您可能会将此类进程视为未编译的脚本。 I'm not going to repeat my (online) argument here.我不会在这里重复我的(在线)论点。 In short, my mass customization architecture replaces design patterns by achieving that flexibility without any of the messy semantics.简而言之,我的大规模定制架构通过在没有任何混乱语义的情况下实现灵活性来取代设计模式。 I was surprised my model worked so well, but the way programmers write code simply doesn't hold a candle to how manufacturing organizes collaborative work.我很惊讶我的 model 运行得如此之好,但程序员编写代码的方式根本无法与制造业组织协作工作的方式相提并论。

  • Manufacturing = each step interacts with one product制造 = 每一步都与一个产品相互作用
  • OOP = each step interacts with itself and other modules, passing the product around from point to point like useless office workers OOP = 每一步都与自身和其他模块交互,像无用的上班族一样将产品从一个点传递到另一个点

This architecture never needs refactoring.这种架构永远不需要重构。 There are also rules concerning centralization and distribution which affect complexity.还有一些关于集中和分配的规则会影响复杂性。 But to answer your question, functional programming is another set of processing semantics, not an architecture for mass custom processes where 1) the source routing exists as a (script) document which the wielder can rewrite before firing and 2) modules can be easily and dynamically added or removed.但是要回答您的问题,函数式编程是另一组处理语义,而不是大规模自定义流程的体系结构,其中 1)源路由作为(脚本)文档存在,使用者可以在触发之前重写,2)模块可以很容易和动态添加或删除。

We could say OOP is the "hardcoded process" paradigm and that design patterns are ways to avoid that paradigm.我们可以说 OOP 是“硬编码过程”范式,而设计模式是避免该范式的方法。 But that's what mass customization is all about.但这就是大规模定制的全部内容。 Design patterns embody dynamic processes as messy hardcode.设计模式将动态过程体现为凌乱的硬代码。 There's just no point.没有意义。 The fact that F# allows passing functions as a parameter means functional and OOP languages alike attempt to accomplish mass customization itself. F# 允许将函数作为参数传递这一事实意味着函数式和 OOP语言类似的尝试自己完成大规模定制。

How confusing is that to the reader, hardcode which represents script?代表脚本的硬编码对读者来说是多么令人困惑? Not at all if you think your compiler's consumers pay for such features, but to me such features are semantic waste.如果您认为编译器的消费者为此类功能付费,则根本不会,但对我而言,此类功能是语义浪费。 They are pointless, because the point of mass customization is to make processes themselves dynamic , not just dynamic to the programmer wielding Visual Studio.它们毫无意义,因为大规模定制的目的是使流程本身动态化,而不仅仅是对使用 Visual Studio 的程序员来说是动态的。

Let give an example of the wrong premise you state.让我们举一个错误前提的例子,你 state。

The adapter pattern we have in OOP as usecase adapter such as in cleanarch and ddd can be implemented in Functional via the monad variation of Option.我们在 OOP 中作为用例适配器(例如在 cleanarch 和 ddd 中)的适配器模式可以通过 Option 的 monad 变体在 Functional 中实现。

You are not replacing them but transforming them.你不是在替换它们,而是在改变它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM