【问题标题】:Functional programming equivalents for the following [closed]以下的函数式编程等价物[关闭]
【发布时间】:2014-04-22 03:15:28
【问题描述】:

我正在尝试从“hello world”等价物的功能程序飞跃到更真实的应用程序。

由于我来自 Java 世界并接触过它的所有设计模式,我的建模过程仍然非常面向 Java(例如,我认为是 *Managers、*Factory、*ClientFactory、*Handler 等)

一次性改变我的思维过程会很困难,所以我希望获得一些关于如何用函数式语言建模以下场景(以 OO 方式描述)的指示。

像 Clojure/Haskell(或者像 Scala 这样的混合语言)这样的函数式语言的示例会很有帮助。

无状态请求处理程序

例如是一个 Servlet。它本质上是一个带有 doGet、doPost 等方法的请求处理程序。如何用函数式语言为这样的类建模?

协调器类

这样的类自己不做任何事情,只是编排整个过程或工作流。它们提供多个入口点 API。

例如OrderOrchestrator 编排了一个多步骤的工作流程,从支付工具验证、购物车管理、支付、发货启动等开始。

他们可能会维护自己的一些内部状态,供付款、发货等不同步骤使用。

ClientFactory 模式

假设您为 LogService 编写了一个客户端,您的客户端使用它来记录有关其服务的流量数据。客户端将数据记录在您管理的存储桶和帐户下的 S3 中,并且您提供其他服务,例如对这些数据进行报告和分析。 您不希望您的客户担心提供 AWS 帐户信息等配置信息,因此您提供了一个 ClientFactory,它根据是用于测试还是生产目的来实例化适当的客户端对象,而无需客户提供任何配置。例如。 LogServiceClientFactory.getProdInstance() 或 LogServiceClientFactory.getTestInstance()。

这样的客户端是如何用函数式语言建模的?

Builder Pattern 和其他 Fluent API 设计

客户端库通常提供构建器来创建具有复杂配置的对象。有时 API 也很流畅,可以轻松创建。 Fluent API 的一个示例是 Mockito API:Mockito.when(A.get()).thenReturn(a) IIRC,这是通过返回渐进式限制性构建器在内部实现的,以允许开发人员编写此代码。

这是否与函数式编程世界中的 this 相似?

数据存储实例

假设您的代码库使用来自多个位置的 ActiveUserRegistry 中存储的数据。您只希望此注册表的 1 个实例存在并让整个代码库访问此注册表。因此,您提供了一个 ActiveUserRegistry.getInstance() 来保证所有代码库都访问该实例(假设该实例是线程安全的等)

如何在功能设置中进行管理?我们是否必须确保在整个代码库中传递相同的实例?

【问题讨论】:

标签: scala design-patterns clojure functional-programming


【解决方案1】:

下面是一些开始:

无状态请求处理程序

Clojure:协议

Haskell:类型类

协调器类

状态单子

ClientFactory 模式

LogServiceClientFactory 是一个模块,getProdInstance 和 getTestInstance 是模块中的函数。

Builder Pattern 和其他 Fluent API 设计

功能构成

数据存储实例

Clojure:使用原子的函数(存储和使用单个实例)

Haskell:TVar,MVar

【讨论】:

    【解决方案2】:

    我对这些 Java 风格的结构并不熟悉,但我会尝试回答:

    无状态请求处理程序

    这些也存在于功能世界中。函数可以很容易地扮演这个角色,即使是像从请求到响应这样简单的函数。 Play Framework 使用了更强大的功能,特别是从RequestIteratee(类型(RequestHeader) ⇒ Iteratee[Array[Byte], SimpleResult])的函数。 Iteratee 是一个实体,它可以在接收到输入 (Array[Byte]) 并最终产​​生响应 (SimpleResult) 以回馈给客户端时逐步使用它。请求处理函数是无状态的,可以重复使用。 Iteratee 也是无状态的——喂给它每个块的结果实际上是得到一个新的Iteratee,然后喂给下一个块。 (我真的过度简化了,它使用 Futures,完全无阻塞,并且具有有效的错误处理 - 值得一看,以了解函数式代码可以为这个问题带来的强大和简单性)。

    协调器类

    我不熟悉这种模式,如果这没有意义,请原谅我。拥有一个可以传递的巨大可变对象是一种反模式。在功能代码中,将有单独的数据类型来表示需要在流程的每个阶段之间传递的数据。这些数据类型将是不可变的。

    至于组织其他事物的事物,看看 Akka 以及一个 Actor 如何监控它下面的其他 Actor,处理错误或根据需要重新启动它们。

    Builder Pattern 和其他 Fluent API 设计

    函数式程序具有这些并将它们带到合乎逻辑的结论。函数式代码允许非常强大的 DSL。例如,查看一个解析器组合器库,可以是 Scala 标准库中的一个,也可以是 Haskell 的库之一。

    ClientFactory 模式和 Datastore 实例

    我认为这在功能代码中没有什么不同。要么你有一个单例,要么你做了正确的依赖注入。工厂模式也用于函数式代码,尽管一流的函数使许多设计模式太琐碎以至于不值得命名(来自 GoF:工厂、工厂方法、命令,以及至少一些 Strategy 和 Template 的实例通常可以是函数)。

    【讨论】:

      【解决方案3】:

      查看 Scala 和 Clojure 中的函数式编程模式:http://pragprog.com/book/mbfpp/functional-programming-patterns-in-scala-and-clojure

      它应该正好有你需要的东西。

      【讨论】:

        猜你喜欢
        • 2013-01-07
        • 2018-06-15
        • 2011-03-20
        • 2019-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-01
        相关资源
        最近更新 更多