关于OOP:函数式编程与面向对象编程Functional programming vs Object Oriented programming

Functional programming vs Object Oriented programming

到目前为止,我主要学习面向对象编程,并期待着学习一种函数式语言。我的问题是:

  • 什么时候选择函数式编程而不是面向对象编程?
  • 在函数式编程是更好的选择的地方,典型的问题定义是什么?


When do you choose functional programming over object oriented?

当您预测到不同类型的软件发展时:

  • 当您对事物有一组固定的操作时,面向对象的语言是很好的,并且随着代码的发展,您主要添加新事物。这可以通过添加实现现有方法的新类来实现,并且只保留现有类。

  • 当您拥有一组固定的事物时,函数语言是很好的,并且随着代码的发展,您主要是在现有事物上添加新的操作。这可以通过添加用现有数据类型计算的新函数来实现,而现有函数则单独使用。

当进化走错路时,你会遇到问题:

  • 向面向对象程序添加新操作可能需要编辑许多类定义才能添加新方法。

  • 在函数程序中添加一种新的东西可能需要编辑许多函数定义来添加一个新的案例。

这个问题已经众所周知很多年了;1998年,菲尔·韦德勒称之为"表达问题"。尽管一些研究人员认为,表达问题可以通过诸如mixin之类的语言特性来解决,但一个广为接受的解决方案尚未进入主流。

What are the typical problem definitions where functional programming is a better choice?

函数语言擅长以树的形式操作符号数据。最喜欢的例子是编译器,源语言和中间语言很少改变(基本上是相同的事情),但编译器编写者总是添加新的翻译和代码改进或优化(对事物的新操作)。编译和翻译通常是功能语言的"杀手程序"。


你不必在这两种模式之间做出选择。您可以使用许多功能概念编写具有OO体系结构的软件。FP和OOP本质上是正交的。

以C为例。您可以说它主要是OOP,但是有许多FP概念和构造。如果考虑Linq,那么允许Linq存在的最重要的构造本质上是函数性的:lambda表达式。

另一个例子,F。您可以说它主要是FP,但是有许多OOP概念和构造可用。您可以定义类、抽象类、接口、处理继承。当代码更清晰或显著提高性能时,甚至可以使用可变性。

许多现代语言是多范式的。

推荐读数

由于我在同一条船上(OOP背景,学习FP),我建议你阅读一些我非常欣赏的读物:

  • 用于日常.NET开发的函数式编程,作者:Jeremy Miller。一篇很棒的文章(尽管格式不好),展示了许多关于c_的技巧和实际的FP示例。

  • 真实世界函数编程,作者:Tomas Petricek。一本主要讨论FP概念的好书,试图解释它们是什么,什么时候应该使用它们。在f和c中都有很多例子。此外,Petricek的博客也是一个很好的信息来源。


面向对象编程提供:

  • 封装,至
    • 内部状态控制突变
    • 限制耦合到内部表示
  • 子类型,允许:
    • 兼容类型替换(多态性)
    • 在类之间共享实现的一种粗糙方法(实现继承)
  • 函数编程,在haskell中,甚至在scala中,都可以允许通过更通用的类型类机制进行替换。不鼓励或禁止可变的内部状态。还可以实现内部表示的封装。请参阅haskell与oop进行比较。

    诺曼断言"向函数程序添加一种新的东西可能需要编辑许多函数定义来添加一个新的用例",这取决于函数代码使用类型类的程度。如果特定抽象数据类型上的模式匹配分布在整个代码库中,那么您确实会遇到这个问题,但从一开始,它可能是一个糟糕的设计。

    在讨论类型类时,编辑删除了对隐式转换的引用。在scala中,类型类使用隐式参数而不是转换进行编码,尽管隐式转换是实现兼容类型替换的另一种方法。


  • 如果您处在一个高度并发的环境中,那么纯函数编程是有用的。缺少可变状态使得并发性几乎微不足道。见Erlang。

  • 在多半径语言中,如果可变状态的存在必须是一个实现细节,那么您可能希望在功能上对某些事物建模,因此fp是一个很好的问题域模型。例如,请参见D编程语言中的python或std.range中的列表理解。这些都是受到函数式编程的启发。