今天所教授的软件工程完全专注于面向对象的编程和“自然的”面向对象的世界观。有一个详细的方法,描述了如何将一个领域模型转换成一个类模型,该方法有几个步骤和很多(UML)工件,比如用例图或类图。许多程序员已经内化了这种方法,并且对如何从头开始设计面向对象的应用程序有很好的想法。

新的宣传是函数式编程,在许多书籍和教程中都有介绍。但是功能性软件工程呢? 在阅读关于Lisp和Clojure的文章时,我发现了两个有趣的陈述:

函数式程序通常是自底向上而不是自顶向下开发的(《论Lisp》,Paul Graham) 函数式程序员使用映射,而oop程序员使用对象/类(《Clojure for Java Programmers》,Rich Hickley谈话)。

那么,在Lisp或Clojure中,系统地(基于模型的)设计功能应用程序的方法是什么呢?常见的步骤是什么,我使用什么构件,我如何将它们从问题空间映射到解决方案空间?


当前回答

我发现行为驱动开发非常适合在Clojure和SBCL中快速开发代码。与函数式语言一起使用BDD的真正好处是,我倾向于编写比使用过程式语言更精细的单元测试,因为我在将问题分解为更小的功能块方面做得更好。

其他回答

老实说,如果你想设计函数式程序,可以看看标准函数库,比如Haskell的Prelude。在FP中,模式通常由高阶过程(对函数进行操作的函数)本身捕获。因此,如果看到了一个模式,通常会创建一个更高阶的函数来捕捉该模式。

fmap就是一个很好的例子。该函数以一个函数作为参数,并将其应用于第二个参数的所有“元素”。因为它是Functor类型类的一部分,所以Functor的任何实例(如列表、图形等)都可以作为第二个参数传递给这个函数。它捕捉了将函数应用于第二个参数的每个元素的一般行为。

一种方法是在所选择的函数式编程语言中创建内部DSL。“模型”是用DSL表示的一组业务规则。

好吧,

一般来说,许多函数式编程语言在大学里被用来解决“小玩具问题”已经很长时间了。

由于“状态”的原因,OOP在“并行编程”方面有困难,因此它们现在变得越来越流行。有时函数式风格更适合解决手头的问题,比如谷歌MapReduce。

我敢肯定,当功能人员碰壁(尝试实现超过1.000.000行代码的系统)时,他们中的一些人会提出新的软件工程方法,并使用流行语:-)。他们应该回答这个老问题:如何将系统分成几部分,以便我们可以一次“咬”每一部分?使用功能风格[工作迭代,仪式和进化的方式]。

函数式风格肯定会影响我们的面向对象 风格。我们“保留”了功能系统中的许多概念并加以适应 我们的OOP语言。

但是函数式程序会被用于这样一个大系统吗?它们会成为主流吗?这就是问题所在。

没有人能提出现实的方法,而不实施这样一个大系统,弄脏自己的手。 首先你应该把自己的手弄脏,然后再提出解决方案。解决方案-没有“真正的痛苦和污垢”的建议将是“幻想”。

虽然这可能被认为是天真和简单的,但我认为“设计食谱”(一种应用于编程的系统解决问题的方法,如Felleisen等人在他们的书HtDP中所提倡的)将接近你所寻找的东西。

这里有一些链接:

http://www.northeastern.edu/magazine/0301/programming.html

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.86.8371

OO编程将数据与行为紧密地结合在一起。函数式编程将两者分开。你没有类图,但你有数据结构,特别是代数数据类型。可以将这些类型编写为与您的域非常匹配,包括通过构造消除不可能的值。

所以没有关于这个问题的书籍,但有一种行之有效的方法,正如俗话所说,让不可能的价值观变得不可代表。

在这样做的过程中,您可以做出一系列选择,将某些类型的数据表示为函数,反之,将某些函数表示为数据类型的联合,这样您就可以获得,例如序列化、更严格的规范、优化等。

然后,考虑到这一点,你在adts上写函数,这样你就建立了某种代数——也就是说,这些函数有固定的定律。有些可能是等幂的,多次应用后是一样的。有些是结合性的。有些是传递性的,等等。

现在你有了一个定义域,在这个定义域上,你有了函数,这些函数根据良好的规律组成。一个简单的嵌入式DSL!

哦,对了,给定属性,你当然可以编写自动随机测试。而这仅仅是个开始。