像Elixir这样的函数式语言处理大型进程链的惯用方法是什么? [关闭]

问题描述 投票:0回答:1

考虑一个例如处理客户结账的服务/功能的例子,涉及许多步骤:服务器应该(例如)检查库存,验证欺诈,收取信用卡,扣除库存,关闭购买,通过电子邮件发送给客户,通知后端/处理程序/仓库,然后返回http请求。

在面向对象的语言中,我将通过构建服务对象以及按顺序同步执行这些步骤来解决此问题,在出现问题时进行分支(甚至可能使用状态机)。

然而,当我想到如何用像Elixir这样的语言解决这个问题时,我能想出的唯一解决方案就是长链管道 - 感觉就像Elixir世界中的反模式,尤其是当你考虑分支。

我的第二个想法是每一步都是它自己的功能(感觉惯用),它需要额外的购买状态参数。在这种情况下,validate_fraud动作然后可以用charge_credit_card信息调用{purchase, fraud_passed}然后charge_credit_card然后在完成时调用行中的下一个。然而,这意味着每个函数都需要知道它在一个链中的位置,这又感觉就像一个气味(然后每个函数都需要有逻辑来处理不同的传入'状态')。

在Elixir中处理OO世界用服务对象解决的情况的惯用方法是什么?

functional-programming elixir
1个回答
2
投票

该语言的功能性质并不意味着任何业务规则。如果链接看起来像你所描述的那样,没有任何价值(实际上没有可能)使步骤异步,因为validate_fraudinventory_check之前没有任何意义,也没有在charge_credit之后。

在这种情况下,解决方案与OO服务非常相似:可能会产生一个流程(在这个特定情况下为Task),它将管理所有步骤:

task = Task.async(fn ->
   check inventory()
   |> validate fraud()
   |> charge()
   |> deduct_inventory()
   |> close_purchase()
   |> email_customer()
   |> notify_handler()
   |> return_http_request()
end)

现在任务有一个很好的功能,人们可能会检查它是否与Task.yield/2一起完成,拥有它自己的超时。调用者代码可能只是调用Task.await/2来阻止调用者,直到任务完成,或者更好的是,它可能会等待,比如3秒,使用Task.yield并回复结果,如果它已完成,或者响应“promise”执行需要更长的时间。

© www.soinside.com 2019 - 2024. All rights reserved.