从面向对象编程到函数式编程,简述

7
我已经使用F#和Haskell学习函数式编程有一段时间了。但由于公司还没有批准使用F#,我仍然必须使用C#。不过我仍然试图保持函数式编程的风格,因为我注意到它有很多好处。
下面是一个典型的问题:
1. 数据库中有一个键集表,其中包含3个键(650万行)。 2. 还有4个支持性大小不同的表。 3. 基于多个输入的复杂公式。
我需要从上述所有数据中获取数据计算出一个值,并将其与每个键集行相关联并将其发送回数据库。需要查询其他4个表。为了提高性能,所有操作都在内存中完成。
对于对象导向开发(OO),我知道如何使用静态字典、对象模型、策略模式等来解决这个问题。但是在函数式编程中,我无法摆脱使用某些构造的不良影响。
我目前正在做以下假设以实现函数式解决方案:
1. 静态字典是不好的。这样可能会导致函数具有副作用。 2. 我需要一个“Calculate”函数,它接受不可变对象并返回一个带有三个键和计算值的不可变对象。这个函数内部可能还包含另一个相同风格的函数。 3. 传统的OO模式可能行不通。
您会如何高层次地设计这个问题?我的假设是否正确?是否有什么我忽略了的东西?
4个回答

6
不,你没有错。面向对象编程和函数式编程都有其优点和缺点。开发人员需要知道如何以及何时使用每种开发风格。幸运的是,C#在某种程度上支持这两种开发风格。
我个人认为,在日常工作中我同时使用函数式和面向对象的编程风格,面向对象编程在处理各种抽象实体(实体、名词等)之间的复杂交互和相互依赖关系时最好。而函数式编程最适用于算法、数据转换等情况,例如需要解决给定问题所需语句的复杂度很高的情况。
通常我将面向对象编程用于我的领域(实体、聚合、值对象、存储库和事件),并将函数式编程保留给我的服务对象。
大多数情况下,选择哪种风格更好取决于感觉或直觉,因为在软件开发中没有明确的选择,经验和实践通常是做出选择的最佳裁判。

2
如果你想要更快的速度,你可能需要考虑使用底层数据结构。在C#中,Dictionary<>是哈希表,而SortedDictionary<>是二叉搜索树。
F#和Haskell都很擅长表示树形数据结构。你可能需要考虑使用比C#提供的默认数据结构更具体的数据结构。
从高层次来看,我会找出你的公式显示的性能特征,并将它们与不同的数据结构进行比较(如果你需要复习,维基百科是一个很好的来源)。一旦确定了要使用哪些数据结构,那么就可以开始担心要使用哪些实现。

1
不知道C#,但是一个正确实现的哈希表不会有缓慢的查找。为了保持查找速度,插入时偶尔需要重新哈希整个表。但这并不是什么大问题;即使BerkeleyDB也会为其磁盘哈希执行此操作。相对于哈希表,树的优势在于引用局部性;如果您按顺序迭代一块表,则很容易预取“下一个”节点。 - jrockway
我删除了关于什么更快或更慢的评论。哈希表和二叉树有许多不同的优缺点,具体取决于您如何使用它们。C# Dictionary<>确实具有快速查找时间。 "使用探测添加、删除和搜索哈希表的平均渐近运行时间是常数时间,O(1)" http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx - gradbot

1
你会如何在高层次上设计这个问题?
基本上,你可以使用高阶函数将工作分解为可重用的组件,语法开销较低。然后,您可能希望从命令式数据结构迁移到纯函数数据结构(纯函数计算包装在具有IO(例如数据库写入)副作用的函数中)。最后,您甚至可以跟踪副作用(完全纯函数)。
粗略地说,这三个渐变到完全纯净的程度首先在Lisp(主要是不纯的),Standard ML(更多地使用纯函数数据结构)和Haskell(完全纯净)中看到。
如果不知道确切的问题,我无法提供更多具体信息,但您可以放心,现在许多人每天都在做这件事,并且效果非常好。

0

在面向对象的语言中使用函数式编程往往是错误的。它会产生过于冗长的代码,性能不佳,并且更容易出错(例如,在不支持尾调用的语言中编写深度递归函数)。

引用1. 静态字典是不好的。函数可能会有副作用。

它要么有副作用,要么没有。在面向对象的语言中,静态字典可以是实现记忆化的好方法。

引用3. 传统的面向对象模式可能行不通。

面向对象的模式在面向对象的语言中运作良好,试图将函数式编程技术强行加入面向对象的语言中会产生冗长而脆弱的代码。这有点像试图用锤子技术使用螺丝刀,虽然可以得到结果,但还有更好的方法。尽可能地发挥你的工具的最佳效果。某些函数式编程技术可能很有用,但完全忽略语言特性并不能产生高质量的代码。


取决于所讨论的面向对象编程语言。C# 在函数式技术方面做得非常好。在 Java 这样更加僵硬的面向对象语言中,某些事情可以以相当函数式的方式完成,但这种情况下肯定存在着相当多的认知摩擦。 - JasonTrue
1
如果你想尝试使用函数式编程,并且在Java环境中,最好使用Clojure。虽然它是一种Lisp语言而不是基于ML的语言,但它可以与Java应用程序一起使用(生成JVM字节码),并支持函数式风格的开发。 - Brian Knoblauch
C# 在许多函数式技术方面表现不佳。极其有限的类型推断只是一个致命缺陷。试着写出使用多个泛型参数的函数的类型,比如函数字典。哎呀。 - MichaelGG
1
@MichaelGG C# 函数式编程存在问题,但我从未将其视为其中之一。我发现 IntelliSense 使我在一半的时间里比类型推断更具生产力。另一半时间相对较少。 - Rei Miyasaka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接