Web编程天生就是函数式编程

任何一位在两个领域里——本地应用程序和Web应用程序——都做过长期开发的人都会告诉你,Web应用开发和传统的应用开发有很大的不同,这指的并不是编程语言。

同样用Java,或者是Python,甚至C++,你既能开发本地应用,也能开发出Web应用。不同之处在于Web的载体介质。它体现出的是一种完全不同的部署和运行环境。它实现了一种不同的服务模式。它使用的是一种不同的应用架构。它需要程序员采用一种不同的思维方法,因为Web编程所体现出的哲学体系跟我们传统的编程派系都相去甚远。在此,对于Web编程范式,我们有一些有趣的事情需要去认识清楚。虽然很明显,很真实,但却被现代强势的编程范式的阴影遮蔽着,被眩目的新技术和工具的光芒淹没了。

“究竟是什么?” – 你会问。

我们就来看看。

我们从看看典型的本地应用程序的生命周期开始,拿它跟典型的Web应用程序的相比较。我将会一直使用“生命周期”这个词来表示应用程序的活动周期,运行时的,指的不是包括不同开发和维护阶段的项目周期。

一个典型的本地应用程序的生命周期是什么样子的?一个用户启动这个程序,程序被加载到内存里,开始运行。它能对用户的输入起反应,从磁盘上读取文 件,或通过网络传输数据。它能跟其它的软件或硬件进行交互,调用其它服务,或响应一个外部调用。它可以收集数据,累计数据,以某种方式处理这些数据。简言之,这些都是一个本地应用程序启动后,运行时能做的事情。

一个典型的Web应用程序的生命周期是什么样的呢?用户在浏览器里点击一个链接。浏览器向Web服务器发送一个请求,然后会接收到响应信息,把它展 示给用户。非常的简单。但应用程序并非是运行在用户机器上的浏览器中的。它运行在Web服务器中。在那里,应用并不是持续的运行。服务器只是短暂使应用苏醒来完成处理请求的任务,准备好要回复的东西。这些事情发生在眨眼之间。在两个请求之间应用并不处于运行状态。它只是被调用很短的一段时间,当完成请求服 务后会立即停止运行。而且应用也不会被整个的加载到内存里,只会加载对于目前的任务真正有必要的部分。你可以认为Web应用程序只有一个瞬时的生命期。只有它的运行所在的环境,也就是Web服务器在持续的运行。

事实上会有一些变通的策略,例如session和数据序列化,来帮助在应用程序的生命期之间保持数据,来模仿有状态的操作,例如某些框架,像ASP.NET的WebForms或JSP就是这样做的,但毕竟,这都是些技术上的技巧,跟本文所讨论的问题不相干。我们关注的是普通的Web应用,关注它们处理请求的过程。这些Web应用程序都只享有一个非常短暂的运行存在状态。

对于开发本地应用程序,有很多技术被证明非常有用。面向对象的方法可以用来构造问题环境,帮助降低问题的复杂性。一些设计模式能体现出一种高效的, 而且优雅的设计方案。分层的架构把代码责任分离,最小化各层的依赖性。这些全是典型的最佳方案,它们在开发本地应用程序的过程中被充分的证实过。

而在Web应用程序里对这些技术方案的使用却是另外一种不同的情形了。我们积极的使用面向对象的方法来定义我们的业务模型,我们采用各种设计模式,我们实现分层架构。这些帮助我们提高代码质量,增加复用性,把应用程序组织成概念上的各个模块。这些都很有效,是我们最常用的技术路线。但即使如此,我还 是忍不住要提醒你,这些东西看起来有些多余,有大炮打蚊子的感觉。时不时我会盯着这些精巧而且深思熟虑的代码,一种无由的想法会袭上我的心头:干嘛不把这些全都剥离掉,直接做要做的事情呢?

什么是直接做?想想一个应用处理一个请求的典型处理方式。在主要步骤里发生了什么?应用程序接收用户输入,校验它,把它转换成业务领域相关的格式, 把它传进一个SQL语句里,保持到数据库里。下面又发生了什么?程序从数据库里读出一些数据,格式化信息,使之能够被用户识别,以一段HTML的形式返回给用户使用。就是这样。这就是大多数Web应用程序在其幕后所做的事情。在它们的运行期里没有什么特别的对象,它们发送和接收消息,智能的在其内部交互运 作来实现高层的行为。不,只是一些数据在用户和数据库之间旅行,送出去,返回来。就是一个接一个的数据流。实现这些任务的程序代码本质上就像一个函数式程序,不管它们被构造出来的风格是什么样的。

在讨论这个问题时,有些开发者写道:函数式编程跟Web应用开发非常的匹配。Web应用接收一个HTTP请求,生成一个HTML返回结果。这应当被认做是一个从请求到页面的函数式功能。

而我要补充下面的东西。实现这些功能的代码本质上反映的就是函数式的风格。我们并没有用真正的对象把应用程序的状态保存在内存里、用它们来实现应用 逻辑操作,我们使用的是数据库来保存应用程序的状态,整个的代码基本上就是一个巨大的,复杂的函数式功能编码,它来管理特定数据流的走向:数据库或用户。

从这些讨论我们能得到什么?狂热的强制使用面向对象的风格、对Web应用使用复杂的架构未必总会有好处。你不一定就能从这种架构方式中获得有价值的 好处,但从性能和日后维护的角度看,它们却能使你的应用过于复杂和效能低下。我们必须针对每个项目的各自情况来掂量采用某种方式的好处和坏处。

当一个程序员编写一个Web应用程序,如果突然代码中显示出了函数式编程风格的印记时,不要马上批评和嘲笑他。也许他是特意这样做的。也许这是一种敏锐的感觉到Web编程本身就是天生的函数式编程的潜意识表现。

相关推荐