【问题标题】:Functional Programming Architecture函数式编程架构
【发布时间】:2010-09-10 11:49:49
【问题描述】:

我熟悉面向对象的体系结构,包括使用设计模式和类图进行可视化,并且我知道面向服务的体系结构及其契约和协议绑定,但是 软件有什么特点吗用函数式编程语言编写的系统架构?

我知道 FP 已用于大中型项目。保罗格雷厄姆写了雅虎的第一个化身!存储在 Common Lisp 中。一些 lisp 开发系统很复杂。用函数式语言编写的人工智能和金融系统可以变得相当大。它们至少都有某种固有的架构,不过,我想知道它们是否有任何共同点?

基于表达式评估的架构是什么样的? FP 架构是否更易于组合?

更新:Kyle 提醒我 SICP 是这个主题的好资源。

更新 2: 我发现了一篇关于这个主题的好帖子:How does functional programming affect the structure of your code?

【问题讨论】:

    标签: architecture functional-programming


    【解决方案1】:

    我目前正在编写“函数式编程中的设计和架构”一书。它描述了纯 FP 世界中存在的许多设计模式和方法(主要语言是 Haskell),但不仅限于此。本书教你如何从零开始构建具有纯状态和非纯状态、多线程、网络、数据库、GUI 的大型应用程序,如何将其分层并获得简单性。它还展示了如何对领域和语言进行建模、如何组织和描述应用程序的架构、如何对其进行测试等等。

    主题列表包括:

    • 使用图表进行架构建模的方法;
    • 需求分析;
    • 嵌入式 DSL 域建模;
    • 外部 DSL 设计和实现;
    • Monad 作为具有效果的子系统;
    • 作为功能接口的免费 monad;
    • 箭头 eDSL;
    • 使用 Free monadic eDSL 实现控制反转;
    • 软件事务内存;
    • 镜头;
    • 状态、读取器、写入器、RWS、ST monad;
    • 不纯状态:IORef、MVar、STM;
    • 多线程和并发域建模;
    • 图形界面;
    • UML、SOLID、GRASP等主流技术和方法的适用性;
    • 与不纯子系统的交互。

    这本书基于我正在研究的 Haskell 项目,尤其是一个 SCADA 应用程序Andromeda。这本书的代码是可用的here。这本书正在开发中(将在 2017 年完成),我建议您熟悉我的文章“FP 中的设计和架构”here(Rus)。

    更新

    我在网上分享了我的书(前 5 章)。 See post on Reddit

    【讨论】:

      【解决方案2】:

      希望不要太切题,但对于浏览此问题答案的任何人来说可能很有趣的是 Peter Norvig 的此演示文稿Design Patterns in Dynamic Programming

      【讨论】:

        【解决方案3】:

        使用函数式语言的项目“架构”的共同点是,它们往往被分成代数层,而不是传统系统架构意义上的子系统。

        有关此类项目的优秀示例,请查看 XMonadYiHappS。如果你检查它们的结构,你会发现它们由单子结构层组成,中间有一些组合胶。

        另请参阅The Scala Experiment 论文,该论文概述了一种体系结构,其中系统由抽象其依赖关系的组件组成。

        【讨论】:

        • 感谢您的回答。我正在学习指称语义((在 Haskell 中)[en.wikibooks.org/wiki/Haskell/Denotational_semantics] 和(通常)[scss.tcd.ie/Andrew.Butterfield/Teaching/CS4003/…),您的回答与我所学的内容产生了共鸣。将问题分解为数学结构(例如您所说的代数),以便将它们组合成一个更大的系统。
        • 在 FP 中说“抽象依赖关系的组件”不是像在命令式/OOP 中说“创建更高级别的过程和数据结构”吗?我的具体问题是——你如何描述这些高阶抽象? OOP 有 UML,其中类图起主要作用。 FP有什么?
        • FP 具有用于描述这些组件的集成文档(例如 Rust)。不需要 UML 或其他东西。你可以创建一个封闭代码的文档,如果你认真地去做,我认为它会比任何 UML 图更具可读性。
        【解决方案4】:

        我认为这可能会有所帮助;

        一些模式消失了——那 是,它们直接由 语言特征,一些模式是 更简单或有不同的重点,并且 有些基本没有变化。

        [AIM-2002-005] Gregory T. Sullivan,Advanced Programming Language Features for Executable Design Patterns "Better Patterns Through Reflection

        2002 年 3 月 22 日

        设计模式书 [GOF95] 呈现 24 种经过时间考验的模式 始终如一地出现在精心设计的 软件系统。每个图案都是 介绍了 模式解决的设计问题, 以及示例实现代码 和设计考虑。这张纸 探索模式如何从 “四人帮”或“GOF”书,因为它 常被称为,相似时出现 使用一个解决问题 动态的、高阶的、面向对象的 编程语言。某些 模式消失了——也就是说,它们 由语言直接支持 功能,一些模式更简单或 有不同的重点,有些是 基本不变。

        【讨论】:

        • 我对函数式架构的期望是一样多的,尤其是基于具有某种宏或元编程工具的语言的架构,它完全没有任何所谓的设计模式(即,样板结构)。
        【解决方案5】:

        我打印出来并查看了Design Patterns in Ocaml,他们使用模块和函子(和对象)来重新创建我们习惯的正常设计模式。这很有趣,但我认为他们使用对象太多来真正看到函数式语言的好处。 FP 是非常可组合的,这是它的本质的一部分。我想我的简短回答是使用 modulesfunctors

        我当前的项目非常大,我们通过文件分隔每个模块——ocaml 中的隐式。我也一直在寻找一个综合资源,它可能对项目产生的真正成功的设计有一些不同的观点或想法。

        【讨论】:

          【解决方案6】:

          我曾参与过一些相当大的功能性项目。他们通常分为两个阵营(至少,我用过的):

          • 极高的可扩展性/可靠性/并发性。事务模型可以非常紧密地构建到语言中。并发 ML 就是一个很好的例子,使用它的项目在并发正确性方面很难出错。
          • 解析/修改框架。这些框架所基于的许多设计模式都非常容易用函数式语言来制定/构建/修改。访问者模式就是一个很好的例子。

          【讨论】:

          • 是的,我想功能设计对于并发执行会更加健壮。解析器组合器框架,如 Haskell 中的,是一个很好的例子,可以让您从函数范式中获得更容易的可组合性。
          【解决方案7】:

          函数式语言的最大共同点是使用函数来存储数据。这有点像在没有对象的对象上使用访问器函数。相反,该函数是在可以访问所需数据的环境中创建的。现在这个函数可以在任何地方传递和使用,并且仍然保留使用数据的能力。

          这是一个非常简单的例子。这不是纯粹的功能,因为它确实改变了状态,但它很常见:

          (define (make-counter)
            (let ((count 0))
              (lambda ()
                (set! count (+ count 1))
                count)))
          
          (define x (make-counter))
          
          (x) returns 1
          
          (x) returns 2
          
          ...etc...
          

          所以我们有一个函数,make-counter,它返回另一个函数,里面有计数器的状态。我们可以调用那个新创建的计数器,观察里面的变化。

          这就是函数式程序的结构。你有将函数作为参数的函数,你有返回隐藏状态函数的函数,等等。这一切都比你自己管理内存要干净得多。

          【讨论】:

          • 我熟悉使用闭包来维护状态,但我对函数式语言的共同点并不那么感兴趣,我对架构良好的大型函数式程序的共同点并不感兴趣。
          • 抱歉,我想低估了您对该领域的熟悉程度。许多函数式编程的新手尝试做的一件事是继续使用变量来封装状态,所以我试图提供一种更面向函数的方式来做到这一点。
          • 我更喜欢 Haskell 的 replace-the-immutable-World 方法来改变状态:)
          猜你喜欢
          • 1970-01-01
          • 2011-01-01
          • 2010-09-06
          • 2013-09-05
          • 1970-01-01
          • 1970-01-01
          • 2015-12-26
          • 1970-01-01
          相关资源
          最近更新 更多