繁体   English   中英

纯 function 应该如何读取配置文件或打开数据库?

[英]How should a pure function read a config file or open a database?

通常我的函数需要来自配置文件或数据库的数据。 我希望尽可能地使用纯函数和可以进行单元测试的东西。

我不知道如何正确地做到这一点,因为我没有 CS 学位。 我可以看到的选项是:

示例 1:

function myFunc(p1, p2, db, configFile) { ... }

但这意味着调用myFunc()的所有其他函数也需要具有db, configFile作为 arguments。

示例 2:

function myFunc(p1, p2) { 
  const config = readConfig();
  dbConn = openDb();    
  ...
}

我想这使单元测试变得不可能?

示例 3:

const struct = {
  config: readConfig(),
  dbConn: openDb(),
  ...
};

function myFunc(p1, p2, struct) { ... }

这有不利的一面,当其他函数数据也存储在这个全局struct中时,每个 function 可以访问超出他们需要的内容。

问题

还有其他可能性吗? 推荐的方法是什么?

像这样定义myFunc()以保持其纯净:

function myFunc(p1, p2, readConfig, openDb) { ... }

并在封闭的 scope 中调用它

// other code here

{
  const config = readConfig();
  const dbConn = openDb();
  myFunc(p1, p2, readConfig, openDb);
}

// other code here
// config and dbConn isn't available here

一个 PoC:

 function func(a, b) { console.log(a); console.log(b); } const a = undefined; const b = undefined; { const a = 'private1'; const b = 'private2'; func(a, b); } console.log(a); console.log(b);

我认为您可以在这里使用依赖注入。 像这样的东西:

function readConfig() { 
 // returns real config
}
function openDb() {
 // return real db connection
}
function readConfigMock() { 
 // returns mock config
}
function openDbMock() {
 // return mock db connection
}
function myFuncBuilder(readConfigFn, openDbFn) { 
  return function(p1, p2) {
      // can use readConfigFn everywhere because of closure
      const config = readConfigFn();
      dbConn = openDbFn();    
      ...
  }
}
const myFunc = myFuncBuilder(readConfig, openDb);

// no need to know about openDb and readConfig
function topFunc() {
  myFunc(p1, p2);
}

// code
const myFunc = myFuncBuilder(readConfig, openDb);

// test
const myFunc = myFuncBuilder(readConfigMock, openDbMock);

诀窍是将 function 作为参数传递。 此外,还有称为myFuncBuilder的高阶 function(返回函数的函数)。 此 function 基于 2 个 arguments 构建myFunc - 用于 db 连接的 function 和用于 Cconfig 的 ZC1C42145268E68A9F14D

因此,您可以轻松地创建readConfigopenDb的模拟以进行测试。

PS 此外,函数式编程范式教我们在这种情况下使用 IO 单子。 但是在 JS/TS 中使用 monad 的学习曲线非常陡峭。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM