13

我最近一直在玩函数式编程,关于副作用的主题有很好的处理方法,为什么应该包含它们等等。在使用 OOP 的项目中,我正在寻找一些资源来制定一些策略最小化副作用和/或状态。

RESTful Web Services一书就是一个很好的例子,它为您提供了在 Web 应用程序中最小化状态的策略。还有什么其他存在?

请记住,我不是在寻找另一本 OOP 分析师/设计模式书籍(尽管良好的封装和松散耦合有助于避免副作用),而是寻找主题本身就是状态/副作用的资源。

一些编译的答案

  • 主要关心状态的 OOP 程序员这样做是因为并发性,因此请阅读Java 并发实践。[正是我想要的]
  • 使用 TDD 使副作用更明显[我喜欢它,例如:你的设置越大,运行测试所需的状态就越多 = 好警告]
  • 命令查询分离 [好东西,防止更改通常令人困惑的函数参数的副作用]
  • 方法只做一件事,如果它们改变了对象的状态,可能会使用描述性的名称,这样简单明了。
  • 使对象不可变 [我真的很喜欢这个]
  • 将值作为参数传递,而不是将它们存储在成员变量中。[我没有链接这个;它使函数原型变得混乱,并且被 Clean Code 和其他书籍积极劝阻,尽管我承认它有助于解决状态问题]
  • 重新计算值而不是存储和更新它们[我也很喜欢这个;在我工作的应用程序中,性能是一个小问题]
  • 同样,如果可以避免,请不要复制状态。让一个对象负责保存它,并让其他人在那里访问它。【OOP基本原理,好建议】
4

4 回答 4

7

我认为您不会在 OO 世界中找到很多关于这个主题的最新材料,仅仅是因为 OOP(以及大多数命令式编程,就此而言)依赖于状态和副作用。例如,考虑记录。这是纯粹的副作用,但在任何自尊的 J2EE 应用程序中,它无处不在。Hoare 的原始快速排序依赖于可变状态,因为您必须围绕枢轴交换值,但它也无处不在。

这就是为什么许多 OO 程序员难以理解函数式编程范式的原因。他们试图重新分配“x”的值,但发现无法完成(至少不能以他们使用过的所有其他语言的方式),然后他们举起双手大喊“这是不可能的!” 最终,如果他们有耐心,他们会学习递归和柯里化以及 map 函数如何取代循环的需要,然后他们就会冷静下来。但对于某些人来说,学习曲线可能非常陡峭。

如今,最关心避免状态的 OO 程序员是那些从事并发性工作的程序员。原因很明显——当您尝试管理线程之间的并发性时,可变状态和副作用会引起极大的麻烦。因此,我在 OO 世界中看到的关于避免状态的最佳讨论是Java Concurrency in Practice。

于 2009-07-27T14:12:24.377 回答
5

我认为规则很简单:方法应该只做一件事,并且应该在方法名称中清楚地传达意图。

方法应该查询或更改数据,但绝不能两者兼而有之。

于 2009-07-27T13:48:52.053 回答
4

我做的一些小事:

  • 首选不可变状态,它是相对良性的。例如,在Java 中,我将成员变量设为final,并尽可能在构造函数中设置它们。

  • 将值作为参数传递,而不是将它们存储在成员变量中。

  • 重新计算值而不是存储和更新它们,如果这样做可以足够便宜的话。这有助于通过忘记更新数据来避免不一致的数据。

  • 同样,如果可以避免,请不要复制状态。让一个对象负责保存它,并让其他人在那里访问它。

于 2009-07-27T14:53:09.583 回答
3

在 OO 中隔离副作用的一种方法是让操作只返回要引起的副作用的描述对象。

命令-查询分离是一种接近这种思想的模式。

通过练习 TDD(或至少编写单元测试),人们通常会更加了解副作用并更加谨慎地使用它们,并将它们与其他易于编写数据驱动的无副作用表达式(预期的,实际的)区分开来) 单元测试。

于 2009-07-27T14:15:32.313 回答