函数式编程是否有软件工程方法?

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

新的炒作function编程,这是在许多书籍和教程中教授。 但是function软件工程呢? 在阅读Lisp和Clojure时,我发现了两个有趣的陈述:

  1. function程序通常是自下而上的,而不是自上而下(“On Lisp”,Paul Graham)

  2. function程序员使用OO程序员使用对象/类的地图(“Clojure for Java程序员”,由Rich Hickley讲话)。

那么,一个function性应用程序的系统化(基于模型)devise的方法是什么呢,例如在Lisp或Clojure中呢? 什么是常见步骤,我使用的是什么工件,我如何将它们从问题空间映射到解决scheme空间?

感谢上帝,软件工程人员还没有发现函数式编程。 这里有一些相似之处:

  • 许多OO“devise模式”被捕获为高阶函数。 例如,访问者模式在function世界中被称为“折叠”(或者如果你是一个尖头的理论家,一个“变形”)。 在函数式语言中,数据types主要是树或元组,每种树型都有一个与之相关的自然变形。

    这些高阶函数往往伴随着一定的编程规律,也就是“自由定理”。

  • function程序员使用图表比OO程序员less得多。 OO图中expression的大部分内容是用types表示,或者在“签名”中expression,您应该将其视为“模块types”。 Haskell也有“types类”,有点像接口types。

    那些使用types的函数式程序员通常认为,“一旦你得到正确的types,代码实际上就自己写了”。

    并不是所有的函数式语言都使用明确的types,但是如何devise程序书籍,是学习Scheme / Lisp / Clojure的优秀书籍,在很大程度上依赖于与types密切相关的“数据描述”。

那么,一个function性应用程序的系统化(基于模型)devise的方法是什么呢,例如在Lisp或Clojure中呢?

任何基于数据抽象的devise方法都能很好地工作。 我碰巧认为,当语言具有明确的types时,这会更容易,但是即使没有,也是有效的。 关于抽象数据types的devise方法的一本很好的书,很容易适应函数式编程,它是Barbara Liskov和第一版John Guttag 在程序开发中抽象和规范 。 Liskov在这项工作中赢得了图灵奖。

Lisp独特的另一种devise方法是确定哪些语言扩展在您工作的问题领域中有用,然后使用卫生macros将这些构造添加到您的语言中。 阅读这种devise的好地方是Matthew Flatt的文章“ 在球拍上制作语言” 。 文章可能在付费墙后面。 您也可以通过search“特定于领域的embedded式语言”这个术语来find更多关于这种devise的一般资料。 除了Matthew Flatt涵盖的特定build议和例子,我可能会从Graham的On LispANSI Common Lisp开始

什么是常见的步骤,我使用什么工件?

常见步骤:

  1. 识别程序中的数据及其中的操作,并定义表示这些数据的抽象数据types。

  2. 识别常见的计算行为或模式,并将其表示为高阶函数或macros。 预计将这一步作为重构的一部分。

  3. 如果您使用的是键入function语言,请尽早使用types检查器。 如果你使用的是Lisp或Clojure,最好的做法是首先编写函数合同,包括unit testing – 这是testing驱动开发到最大。 你会想要使用任何版本的QuickCheck已经移植到您的平台,在你的情况下,它看起来就是所谓的ClojureCheck 。 这是一个非常强大的库,用于构build使用高阶函数的代码的随机testing。

对于Clojure,我build议回到旧的关系build模。 在Tar​​pit之外是鼓舞人心的读书。

就我个人而言,我发现面向对象开发的所有常见良好实践也适用于函数式编程 – 只需稍作调整即可考虑实用的世界观。 从方法论的angular度来看,你并不需要做任何根本性的改变。

我的经验来自近年来从Java转移到Clojure。

一些例子:

  • 了解您的业务领域/数据模型 – 无论您要devise对象模型还是使用嵌套地图创buildfunction数据结构,同等重要。 在某些方面,FP可能更容易,因为它鼓励您将数据模型与函数/进程分开进行思考,但是您仍然必须同时执行这两个操作。

  • devise中的服务导向 – 从FP的angular度来看,实际上效果非常好,因为典型的服务实际上只是一个带有一些副作用的function。 我认为在Lisp世界中有时候支持的软件开发的“自下而上”的观点实际上只是另一个幌子的良好的面向服务的APIdevise原则。

  • testing驱动开发 – 在FP语言中运行良好,事实上有时甚至更好,因为纯函数非常适合编写清晰,可重复的testing,而无需设置有状态的环境。 您可能还想要构build单独的testing来检查数据完整性(例如,此映射是否包含我期望的所有关键字,以平衡在OO语言中,类定义将在编译时为您执行此操作的事实)。

  • Prototying /迭代 – 与FP一样好。 如果您非常擅长构build工具/ DSL并在REPL上使用它们,您甚至可以与用户进行原型开发。

OO编程将数据与行为紧密结合 函数式编程分离了两者。 所以你没有类图,但你有数据结构,而且你特别有代数数据types。 这些types可以写得非常紧密地匹配你的域名,包括通过构build消除不可能的值。

所以没有书和书,但是有一个很好的方法,就像俗话说的那样,使不可能的价值观变得无法代表。

这样做,您可以做出一系列的select,而不是将某些types的数据表示为函数,反之,将某些函数表示为数据types的联合,以便您可以获得例如序列化,更严格的规范,优化等。

那么,因为你写了一些函数来build立某种代数 – 也就是说这些函数有固定的规律。 有些也许是幂等的 – 多次申请后相同。 有些是联想的。 有些是传递性的,等等

现在你有一个领域,你有function,按照良好的法律组成的function。 一个简单的embedded式DSL!

哦,给定的属性,你当然可以写自动化的随机testing(ala QuickCheck)..这只是一个开始。

面向对象的devise与软件工程不是一回事。 软件工程必须处理从要求到工作系统的整个过程,按时,低缺陷率。 函数式编程可能与面向对象不同,但是它并没有消除需求,高层次和详细的devise,validation和testing,软件度量,估计以及所有其他“软件工程材料”。

而且,function程序确实performance出模块化和其他结构。 您的详细devise必须用该结构中的概念来expression。

看到我对另一篇文章的回答:

Clojure如何处理关注的分离?

我同意在如何构build使用FP方法的大型应用程序的主题上需要写更多的内容(还需要做更多的事情来loggingFP驱动的UI)

一种方法是在select的函数式编程语言中创build一个内部DSL。 那么这个“模型”就是在DSL中expression的一组业务规则。

虽然这可能被认为是幼稚和简单化的,但我认为“devise食谱”(Felleisen等人在他们的书HtDP中提出的一种系统化的解决问题的方法)将接近你所期待的。

这里有几个链接:

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

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

老实说,如果你想要function程序的devise食谱,看看标准函数库,如Haskell的前奏。 在FP中,模式通常由高阶程序(对函数进行操作的函数)自己捕获。 所以如果看到一个模式,通常会创build一个更高阶的函数来捕捉这个模式。

一个很好的例子就是fmap。 这个函数将一个函数作为参数,并将其应用于第二个参数的所有“元素”。 由于它是Functortypes类的一部分,所以Functor的任何实例(例如列表,graphics等)都可以作为第二个parameter passing给这个函数。 它捕获了将函数应用于第二个参数的每个元素的一般行为。

还有英国牛津大学的理查德·伯德教授和程序devise代数小组的“程序计算”/“devise计算”风格,我不认为这是一个太过牵强的方法。

我个人喜欢AoP团队所做的工作,我自己也没有这样的练习devise的纪律。 但是这是我的缺点,而不是程序计算。

我发现行为驱动开发是在Clojure和SBCL中快速开发代码的自然结合。 用函数式语言来利用BDD的真正好处是,我倾向于编写比我通常在使用过程语言时所做的更细粒度的unit testing,因为我把分解问题分解成更小的function块的工作做得更好。

我最近发现了这本书: function和反应域build模

我认为完全符合你的问题。

从书的描述:

function性和react native领域build模教你如何从纯粹的functionangular度思考领域模型,以及如何构build它们来构build更大的抽象。 您将从function性编程的基础知识入手,并逐步深入到实现复杂领域模型所需了解的高级概念和模式。 本书演示了代数数据types,基于typestypes的devise以及隔离副作用等高级FP模式如何使您的模型成为可读性和可validation性的组成部分。

好,

通常很多function编程语言在大学里被用于“小玩具问题”。

由于OOP由于“状态”而与“平行编程”有困难,现在它们越来越受欢迎。有时function方式更适合像Google MapReduce那样的问题。

我敢肯定,当functioanl的人碰壁时(尝试实现比1.000.000行代码更大的系统),其中一些将会带来新的软件工程方法论和stream行语:-)。 他们应该回答一个古老的问题:如何将系统分成几块,以便我们一次一个地“咬”一块。 使用function性风格[迭代,增量和演化的方式]。

可以肯定的是,function风格会影响我们面向对象的风格。我们仍然有许多来自function系统的概念,并且适应了我们的OOP语言。

但是function程序会被用于这么大的系统吗?它们会成为主stream吗? 这是个问题

没有实施这样一个大系统,没有人可以用现实的方法来实现,使自己的手变脏。 首先,你应该让你的手脏,然后build议解决scheme。 解决scheme – 没有“真正的痛苦和污垢”的build议将是“幻想”。