【问题标题】:How to call an API dynamically in functional programming paradigm如何在函数式编程范式中动态调用 API
【发布时间】:2021-10-23 02:04:58
【问题描述】:

我的应用程序接收来自人类客户端的 http 请求。

我的应用程序只需要调用 12 个 API 中的一个 API,具体取决于它接收到的输入中的一个特定数据。

我的第一个想法当然是

// requestPrice.js

const service = req.body.service

const APIs = {
    ser1: callAPI1,
    ser2: callAPI2,
    ser3: callAPI3,
    // ...
    ser12: callAPI12,
}

return APIs[service](req.body)

这很好用,但我想需要进行一些重构以使其符合 SOLID。 通常在 OOP 中,我可能会使用其中一种设计模式,例如策略或责任链。

但是我使用的函数式编程有点不同。

我想过做以下事情:

// ser1.js
export default callAPI(data) {
    // code 1
}

// ser2.js
export default callAPI(data) {
    // code 2
}

// ser3.js
export default callAPI(data) {
    // code 3
}

//...

// ser12.js
export default callAPI(data) {
    // code 12
}

// requestPrice.js
const service = req.body.service
const api = require(`./${service}`)

return api(req.body)

这看起来比第一个版本好得多,因为它更好地遵循单一责任原则。另外,我猜它也遵循 Open/Closed 原则,因为如果要添加第 13 个 api,requestPrice.js 不会改变。 另一方面,我应该能够轻松地对文件requestPrice.js 进行单元测试,因为req 可以注入。

这样做是否符合 SOLID 原则,还是有更好更清洁的方法?

【问题讨论】:

  • 不错的努力,但我认为它不符合依赖倒置原则,因为请求主体必须知道要调用哪个服务的详细信息。但是,它应该只知道输入。同意吗?
  • 其实恰恰相反。 req.body.service 是要调用的 API 的名称。这只是一把钥匙。

标签: javascript node.js functional-programming clean-architecture


【解决方案1】:

我建议使用工厂方法(在 FP 中实现为柯里化函数),以便分别决定调用哪个服务以及在每个服务中做什么。 request.body 应该传递给返回的 impl 函数。

function createService(body) {
  if(checkInput(body) == [something]) return service1;
  else if(checkInput(body) == [something2]) return service2;
  ..
}

function service1(body) {..}
function service2(body) {..}
..

let service = createService(req.body);
service(request.body);

我没有把它放在不同的文件中,但你可以这样做。现在 createService 可以在不同的模块中。并且每个 impl(service1、service2 等)都可以在自己的单独文件中,并且 service 的调用者不需要知道要调用哪个 impl,从而保持依赖倒置。高级模块不知道低级模块。 :)

【讨论】:

  • 我喜欢这样!这在工厂中封装了在服务中选择的代码。是的,我之前应该考虑过。谢谢! PS:我可能会等待另一个答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 2020-11-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
相关资源
最近更新 更多