【问题标题】:Improve design of an npm module改进 npm 模块的设计
【发布时间】:2018-05-30 23:38:05
【问题描述】:

我正在努力改进math.js的设计。

从概念上讲,我正在尝试将一个巨大的模块拆分成更小的模块:

当我在 lib/index.js 中只有一个导入时,它似乎正在工作:

module.exports = require('./trigonometric')

但是当我有两班(或更多)时,

module.exports = require('./trigonometric')
module.exports = require('./unit')

它会引发一堆错误,如下面的故障所示。

每个函数都在一个文件中,但我看到它的增长速度非常快,因此我决定在数学函数的不同区域(即单位、三角函数等)之间进行良好拆分会更清晰。

This 是这项工作的第一个提交。我被困在那里,因为我无法解决导入问题,如您所见:

Failures:

  1) #math.js Testing ceil function
   Message:
     TypeError: math.ceil is not a function
   Stacktrace:
     TypeError: math.ceil is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:419)

  2) #math.js Testing round function
   Message:
     TypeError: math.round is not a function
   Stacktrace:
     TypeError: math.round is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:755)

  3) #math.js Testing fround function
   Message:
     TypeError: math.fround is not a function
   Stacktrace:
     TypeError: math.fround is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:1104)

  4) #math.js Testing floor function
   Message:
     TypeError: math.floor is not a function
   Stacktrace:
     TypeError: math.floor is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:1469)

  5) #math.js Testing random function
   Message:
     TypeError: math.random is not a function
   Stacktrace:
     TypeError: math.random is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:1817)

  6) #math.js Testing sign function
   Message:
     TypeError: math.sign is not a function
   Stacktrace:
     TypeError: math.sign is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:2025)

  7) #math.js Testing drop digit functions
   Message:
     TypeError: math.dropFirstDigit is not a function
   Stacktrace:
     TypeError: math.dropFirstDigit is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:2366)

  8) #math.js Testing format function
   Message:
     TypeError: math.format is not a function
   Stacktrace:
     TypeError: math.format is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:3022)

  9) #math.js Testing abs function
   Message:
     TypeError: math.abs is not a function
   Stacktrace:
     TypeError: math.abs is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:3389)

  10) #math.js Testing array functions
   Message:
     TypeError: math.randomElement is not a function
   Stacktrace:
     TypeError: math.randomElement is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:3753)

  11) #math.js Testing pow function
   Message:
     TypeError: math.pow is not a function
   Stacktrace:
     TypeError: math.pow is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:4236)

  12) #math.js Testing square function
   Message:
     TypeError: math.square is not a function
   Stacktrace:
     TypeError: math.square is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:4502)

  13) #math.js Testing imul function
   Message:
     TypeError: math.imul is not a function
   Stacktrace:
     TypeError: math.imul is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:4770)

  14) #math.js Testing cube function
   Message:
     TypeError: math.cube is not a function
   Stacktrace:
     TypeError: math.cube is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:5037)

  15) #math.js Testing sqrt function
   Message:
     TypeError: math.sqrt is not a function
   Stacktrace:
     TypeError: math.sqrt is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:5299)

  16) #math.js Testing cbrt function
   Message:
     TypeError: math.cbrt is not a function
   Stacktrace:
     TypeError: math.cbrt is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:5561)

  17) #math.js Testing exp function
   Message:
     TypeError: math.exp is not a function
   Stacktrace:
     TypeError: math.exp is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:5825)

  18) #math.js Testing exp function
   Message:
     TypeError: math.expm1 is not a function
   Stacktrace:
     TypeError: math.expm1 is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:6099)

  19) #math.js Testing between function
   Message:
     TypeError: math.between is not a function
   Stacktrace:
     TypeError: math.between is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:6381)

  20) #math.js Testing trunv function
   Message:
     TypeError: math.trunc is not a function
   Stacktrace:
     TypeError: math.trunc is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:6743)

  21) #math.js Testing temperature functions
   Message:
     TypeError: math.toFahrenheit is not a function
   Stacktrace:
     TypeError: math.toFahrenheit is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:7097)

  22) #math.js Testing hypot function
   Message:
     TypeError: math.hypot is not a function
   Stacktrace:
     TypeError: math.hypot is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:7380)

  23) #math.js Testing greatestCommonDivisor function
   Message:
     TypeError: math.greatestCommonDivisor is not a function
   Stacktrace:
     TypeError: math.greatestCommonDivisor is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:7756)

  24) #math.js Testing factorial function
   Message:
     TypeError: math.factorial is not a function
   Stacktrace:
     TypeError: math.factorial is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:8063)

  25) #math.js Testing prime function
   Message:
     TypeError: math.isPrime is not a function
   Stacktrace:
     TypeError: math.isPrime is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:8491)

  26) #math.js Testing even function
   Message:
     TypeError: math.isEven is not a function
   Stacktrace:
     TypeError: math.isEven is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:8763)

  27) #math.js Testing odd function
   Message:
     TypeError: math.isOdd is not a function
   Stacktrace:
     TypeError: math.isOdd is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:9033)

  28) #math.js Common log tests
   Message:
     TypeError: math.log is not a function
   Stacktrace:
     TypeError: math.log is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:9298)

  29) #math.js Common log2 tests
   Message:
     TypeError: math.log2 is not a function
   Stacktrace:
     TypeError: math.log2 is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:9727)

  30) #math.js Common log10 tests
   Message:
     TypeError: math.log10 is not a function
   Stacktrace:
     TypeError: math.log10 is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:10308)

  31) #math.js Common log1p tests
   Message:
     TypeError: math.log1p is not a function
   Stacktrace:
     TypeError: math.log1p is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:10824)

  32) #math.js Testing unit converters
   Message:
     TypeError: math.feetToInches is not a function
   Stacktrace:
     TypeError: math.feetToInches is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:11188)

  33) #math.js Testing trigonometric functions
   Message:
     TypeError: math.sin is not a function
   Stacktrace:
     TypeError: math.sin is not a function
    at jasmine.Spec.<anonymous> (/Users/toubou91/git/math.js/spec/math-spec.js:9:12715)

Finished in 0.024 seconds
33 tests, 33 assertions, 33 fai

我怀疑这可能是因为我对两个目录(三角函数、单位)使用了相同的命名 (index.js),但我仍然无法使其工作。

有什么想法吗?

【问题讨论】:

    标签: javascript node.js import module export


    【解决方案1】:

    module.exports 是一个对象。当你这样做时

    module.exports = require('./trigonometric');
    module.exports = require('./unit');
    

    您首先为其分配三角模块,然后用单位模块覆盖它。如果我们 console.log 我们得到的数学对象:

    { yardsToFeet: [Function: yardsToFeet],
      feetToYards: [Function: feetToYards],
      ...
      yardsToMiles: [Function: yardsToMiles],
      yardsToMeters: [Function: yardsToMeters] }
    

    我们可以看到缺少三角函数,这就是测试失败的原因。

    在您的开发分支中,您还拥有:

    module.exports = [
      require('./trigonometric'),
      require('./unit')
    ];
    

    这使它成为一个你必须像这样使用的数组:

    console.log(mathjs[0].sin(0.1));
    

    或者如果我们 console.log 数学对象:

    [ { sin: [Function: sin],
        cos: [Function: cos],
        ...
        log10: [Function: log10],
        log1p: [Function: log1p] },
      { yardsToFeet: [Function: yardsToFeet],
        feetToYards: [Function: feetToYards],
        yardsToInches: [Function: yardsToInches],
        ...
        yardsToMiles: [Function: yardsToMiles],
        yardsToMeters: [Function: yardsToMeters] } ]
    

    不是很人性化。


    相反,您可以将两个模块合并到一个公共对象中,然后导出该对象:

    const trig = require('./trigonometric');
    const unit = require('./unit');
    
    module.exports = Object.assign({}, trig, unit);
    

    然后可以这样使用:console.log(mathjs.sin(0.1));

    您还可以导出两个名为 trigonometric 和 unit 的子对象:

    module.exports.trigonometric = require('./trigonometric');
    module.exports.unit = require('./unit');
    

    会这样使用:console.log(mathjs.trigonometric.sin(0.1));

    【讨论】:

    • 哇,非常感谢@MikaS!您会建议什么作为更好的设计选择?我会选择第一个选项,因为它可以让我的测试更干净
    • @toubou 我会选择我认为的第一个。在 mathjs 对象中包含子对象变得过于冗长。你也可以把不重要的函数放在子对象中,而把重要的函数放在根中,如果你有太多函数的地步。
    • 这个怎么样? module.exports = Object.assign( require('./unit'), require('./trigonometric') );
    • @toubou 这也有效,但我考虑将它们加载到单独的行更清洁。结果应该是一样的。我还将答案从module.exports = Object.assign(trig, unit); 更改为module.exports = Object.assign({}, trig, unit);。之前,它将 unit 复制到 trig 中,然后将其设置为导出对象。现在它将 unit 和 trig 复制到一个空对象中,然后导出该对象,我觉得它更干净。结果是一样的。
    • 确实,module.exports = Object.assign({}, trig, unit); 是为了更简洁,只需阅读文档即可,但我会在 Object.assign 声明中直接使用 requires。我可以再次使用逗号将它们分隔在不同的行上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多