编程的97件事——2、应用函数式编程原则

Apply Functional Programming Principles

Functional programming has recently enjoyed renewed interest from the mainstream programming community. Part of the reason is because emergent properties of the functional paradigm are well positioned to address the challenges posed by our industry‘s shift toward multi-core. However, while that is certainly an important application, it is not the reason this piece admonishes you to know thy functional programming.

Mastery of the functional programming paradigm can greatly improve the quality of the code you write in other contexts. If you deeply understand and apply the functional paradigm, your designs will exhibit a much higher degree of referential transparency.

Referential transparency is a very desirable property: It implies that functions consistently yield the same results given the same input, irrespective of where and when they are invoked. That is, function evaluation depends less — ideally, not at all — on the side effects of mutable state.

A leading cause of defects in imperative code is attributable to mutable variables. Everyone reading this will have investigated why some value is not as expected in a particular situation. Visibility semantics can help to mitigate these insidious defects, or at least to drastically narrow down their location, but their true culprit may in fact be the providence of designs that employ inordinate mutability.

And we certainly don‘t get much help from industry in this regard. Introductions to object orientation tacitly promote such design, because they often show examples composed of graphs of relatively long-lived objects that happily call mutator methods on each other, which can be dangerous. However, with astute test-driven design, particularly when being sure to "Mock Roles, not Objects", unnecessary mutability can be designed away.

The net result is a design that typically has better responsibility allocation with more numerous, smaller functions that act on arguments passed into them, rather than referencing mutable member variables. There will be fewer defects, and furthermore they will often be simpler to debug, because it is easier to locate where a rogue value is introduced in these designs than to otherwise deduce the particular context that results in an erroneous assignment. This adds up to a much higher degree of referential transparency, and positively nothing will get these ideas Fas deeply into your bones as learning a functional programming language, where this model of computation is the norm.

Of course, this approach is not optimal in all situations. For example, in object-oriented systems this style often yields better results with domain model development (i.e., where collaborations serve to break down the complexity of business rules) than with user-interface development.

Master the functional programming paradigm so you are able to judiciously apply the lessons learned to other domains. Your object systems (for one) will resonate with referential transparency goodness and be much closer to their functional counterparts than many would have you believe. In fact, some would even assert that the apex of functional programming and object orientation are merely a reflection of each other, a form of computational yin and yang.

By Edward Garson


应用函数式编程原则


函数式编程最近再次获得了主流编程社区的关注。部分原因是因为函数式编程的模式能很好的适应行业向多核发展带来的挑战。然而,尽管这很重要,却并不是你需要了解函数式编程的主要原因。

掌握函数式编程能显著提高你的代码在其他上下文中的质量。如果你能深刻的理解和应用函数式编程,你的程序设计就能呈现出非常高度的引用透明。引用透明性是我们非常想要的特性:它保证了无论代码在何时何地被调用,相同的输入都会得到相同的输出结果。就是说,对比共享状态,函数赋值依赖更少,理想情况是完全没有。

命令式编程的一大缺陷就是公共变量,每个阅读到公共变量的人都要深入挖掘为什么变量的值在当前情景下不是自己预期的那个。良好的命名和排版能降低这种缺陷,至少能大幅缩小要检索的范围。但造成代码缺陷的根本原因还是程序设计中对变量的滥用。

就这个问题我们无法从行业获得太多帮助,面向对象的编程方法有意无意的助长了这样的设计。他们经常会展示这样的范例:范例由图表和长期存在的对象组成,他们高兴地将这种对象称为赋值方法,这可能是一种危险的设计。但是,通过巧妙的测试驱动开发的设计,特别是确保做到“模拟职责,而不是对象”,就能通过设计消除不必要的可变性。

最终的结果就是按照职责划分了更多更小的方法,它们接受传入的参数,而不是共享变量。这样的设计缺陷更少,更重要的是易于调试,因为这样的设计容易定位何处引入了错误,而不是去推测发生错误的代码段。这使你的程序的引用透明程度大幅提高,要让这种意识深入骨髓,最好的办法莫过于学习一门将这种设计作为规范的函数式编程语言。

当然,这种做法也并不是适用于所有的情景。例如,在面向对象系统中,这种模式应用在领域模型开发(用来分解商业规则的复杂度)的效果一般要好于用户界面开发。

掌握了函数式编程的规范你就能明智地将本课的内容应用在其他领域。你的对象系统获得了引用透明带来的好处并且功能上比你预想要更加契合。事实上,甚至有人断言,函数式编程和面向对象设计的终点是殊途同归,是计算机行业的阴阳两极。

后记:因前段时间事情较多,没有顾上更新。这是系列文章的第2篇,篇幅和难度较第1篇都有增大,因本人能力所限,翻译质量不是很高,希望看到的朋友能够多提出意见。

时间: 2024-10-09 08:33:50

编程的97件事——2、应用函数式编程原则的相关文章

编程的97件事——6、在重构之前

在重构之前 每个程序员都会在某些时候需要重构已存在的代码.但在这样做之前请想想下面的问题,这会省去你和其他人很多时间(和痛苦): 开始重构的最佳时机是审查代码库和代码库的测试代码的时候.这时你明白当前代码的优点和不足,这可以确保你重构时保持代码的优秀特性并避免上个版本犯下的错误.我们都以为自己会比现存系统做得更好,结果并没有更好,还可能更糟-这是因为我们没有从前人的错误中吸取教训. 避开推到重来的诱惑.复用的代码越多越好.无论这些代码多么丑陋,这些代码毕竟是被测试和复查过的.丢弃旧代码,尤其是产

编程的97件事——3、多问“用户会怎么做”(你不是用户)

Ask "What Would the User Do?" (You Are not the User) We all tend to assume that other people think like us. But they don't. Psychologists call this the false consensus bias. When people think or act differently to us, we're quite likely to label

编程的97件事——8、童子军军规

童子军军规 童子军有一条规则:"总是保证营地在离开时比发现时整洁."如果你发现地上是乱的,不论是谁弄乱的,你都要收拾干净.你要有意的为一下批露营者改善营地环境.实际上这条规则,是童子军之父,Robert Stephenson Smyth Baden-Powell写的:"努力留下一个比你发现时更好的世界." 如果我们在编码时也新遵循一条类似的规则:"总是保证模块签入时比签出时整洁".无论模块的原作者是谁,如果我们总是作出一些努力,无论多么微小,去改

97. 在LotusScript中模拟函数式编程

本文将介绍96. 通用字段修改器用到的在LotusScript中模拟函数式编程的技巧. 函数式编程 函数式编程是一种优美而强大的编程范式.它源于Alonzo Church提出的λ演算(Lambda演算),而某个问题能表示成Lambda演算,按照Church–Turing论题,等价于该问题在数学上是可以有效计算的.粗略地说,用对应于Lambda演算的一门函数式程序语言可以写出任何理论上可计算问题的计算程序.因为与可计算理论的紧密关系和强大的表现力,函数式编程在学术界历来很受重视.但是在日常应用的软

翻译连载 | 附录 C:函数式编程函数库-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱:分享,是 CSS 里最闪耀的一瞥:总结,是 JavaScript 中最严谨的逻辑.经过捶打磨练,成就了本书的中文版.本书包含了函数式编程之精髓,希望可以帮助大家在学习函数式编程的道路上走的更顺畅.比心. 译者团队(排名不分先后):阿希.blueken.brucecham.cfanlife.d

软件架构师应该知道的97件事

1.客户需求重于个人简历客户需求至上.为了自己的简历更炫而采用新技术是沽名钓誉,往往事与愿违. 2.  简化根本复杂性 ,消除偶发复杂性根本复杂性指的是问题与生俱来的.无法避免的困难.偶发复杂性是人们解决根本复杂性的过程中衍生的.分析问题好比拨云见月.水落石出.架构师的责任在于解决问题的根本复杂性,同时避免引入偶发复杂性. 3.  关键问题可能不是出在技术上大多数项目是由人完成的,人才是项目成败与否的基础.学会尊重他人,给予团队成员充分的信任,是聪明的架构师获得成功必须掌握的核心技能.团队同心,

Python核心编程读笔 9:函数和函数式编程

第11章 函数和函数式编程 一 调用函数 1 关键字参数 def foo(x): foo_suite # presumably does some processing with 'x' 标准调用 foo(): foo(42)  foo('bar')  foo(y) 关键字调用 foo(): foo(x=42)  foo(x='bar')  foo(x=y) 即明确给出相应的参数名 2 参数组 Python允许程序员执行一个没有显式定义参数的函数,相应的方法是通过一个把元组(非关键字参数)或字典

从函数式编程异常处理到薛定谔类型 -- 函数式编程本质(I)

首先说明一下 这里并不打算展开讲函数式异常处理 因为这篇文章的主题是介绍薛定谔类型. 关于前者我推荐medium上的一篇文章"Functional Error Handling". 本文很大程度上是受到这篇文章的启发 一句话来说 很多语言都有自己函数式处理异常的方式 也许你已经用过了 只是没有认识到这一点而已: Typescript的Union类型 Swif的Option类型 Haskell的Maybe类型 如果要给这种类型下个定义 那就是薛定谔类型(非公式说法) 怎么用薛定谔类型处理

软件架构师应该知道的97件事(一)

1 客户需求重于简历和个人兴趣 ,选用合适的技术,保证服务的稳定性,易用性. 2 明白业务的关键点,简化根本复杂性,避免为了解决问题引入偶发可用性. 3 技术只是项目的一部分.沟通,合理有效的沟通很重要. 4 沟通的简明清晰,开明的方式,与团队里面的人合作 . 5 架构决定了应用的性能 6 了解需求的意义,事件的意义,为目标努力,而不仅仅是需求.把最优价值的摆在首位 7 架构师最重要的是沟通,起立发言,考虑完善推动事情. 8 故障终究会发生.合理设计故障防范模型. 9 需求讨论或者其他的讨论,也