【问题标题】:Any reason not to bind configurations to global object in Node.js?有什么理由不将配置绑定到 Node.js 中的全局对象?
【发布时间】:2014-05-13 09:42:34
【问题描述】:

我正在寻找在我的 Node 应用程序中使用全局配置设置的最佳方式。按照(我的)偏好顺序,我发现的方法是:

  1. 将配置附加到全局对象

    global.config = {
        db: require('./config/db'),
        server: require('./config/server'),
        session: require('./config/session'),
        auth: require('./config/auth')
    };
    
  2. 将配置对象传递给需要它的模块。

    var config = {
        db: require('./config/db'),
        server: require('./config/server'),
        session: require('./config/session'),
        auth: require('./config/auth')
    };
    var responder = require('./responder')(config);
    
  3. 在每个模块中都需要配置文件。因为我通常将我的配置拆分成单独的文件,所以我真的不喜欢这样做。由于我并不总是使用某些文件,因此这通常还涉及检查文件是否存在。

有什么理由应该避免使用这些方法中的任何一种吗?有什么理由应该优先于其他人吗?

【问题讨论】:

    标签: javascript node.js configuration


    【解决方案1】:

    根据我的经验,选择 No 是一种常见的用法和良好的风格。 2:将配置选项传递给您建议的需要它的模块

    原因

    • 它将配置与实际逻辑分离。如果您在其中包含配置文件 模块本身,对一个特定配置文件有不必要的依赖。
    • 仍然定义依赖于作为参数提供的特定配置值 - 而不是“神奇地”从全局命名空间中提取,这使得代码难以阅读、维护和测试。

    顺便说一句,这是几乎所有语言的经验法则,它允许诸如全局变量/对象和结构之类的东西包括“你喜欢的任何地方你喜欢的一切”。但是requirejs 至少允许exports 成为一个立即接受配置的函数,从而将您推向了正确的方向。因此,单线是一种要求和配置资源的优雅方式。

    除此之外的所有内容都可能会在关于依赖注入 (DI) 概念的讨论中结束 - 这是一个单独的主题。

    【讨论】:

    • 我传递变量的主要问题是当我将模块拆分为多个文件时,每次需要单独的文件时我都必须继续传递配置对象。有什么顺利的方法可以克服吗?
    • @sup3rman 如果您将事物拆分为由单独文件拥有的小逻辑单元,则可能不需要每次都传递整个配置对象,但它们需要一些参数 - 如果有的话。如果你分手了,例如路由段,在我看来,为每个所需资源传递所需的配置是绝对可以的。
    【解决方案2】:

    对于小型项目,所有三种方式都可以接受。对于大,我可以说下一个:

    全局变量有问题

    如果你开始使用这种方式,你需要保护像var config = {...}; config.freeze();这样的配置对象。在任何情况下,全局变量都是一种不好的做法,尤其是对于 NodeJS,因为它破坏了模块化系统。

    传递配置是最好的方法

    这是什么原因? 测试

    在测试中,您需要获取配置文件的一些状态。第一种和第三种方式为您提供了下一个代码样式:

    config.js

    module.exports= {
      a: 10
    };
    

    app.js

    var config = require('config');
    
    module.exports.func = function(){
      if (config.a > 10) return 'A';
      return 'B';
    }
    

    摩卡+柴测试

    var expect = require('chai').except,
        config = require('config'),
        app = require('app');
    
    describe('Func', function(){
      it('return "A" if a > 10', function(){
        config.a = 12; //DHOOO!!! (c) Homer Simpson
        expect(app.func()).to.equal('A');
      });
      it('return "B" if a <= 10', function(){
        config.a = 9;
        expect(app.func()).to.equal('B');
      });
      config.a = 12; //return default state of config. DHOOO!!!
    });
    

    你怎么能看到你需要有可编辑的配置,这是一个不好的做法(每个开发人员都可以在任何地方更改配置状态的大项目...... DHOOO !!!)

    第二种方式是这样的:

    config.js

    var config = {
      a: 10
    };
    config.freezy();
    module.exports = config;
    

    app.js

    module.exports.func = function(config){
      if (config.a > 10) return 'A';
      return 'B';
    }
    

    摩卡+柴测试

    var expect = require('chai').except,
        app = require('app');
    
    describe('Func', function(){
      it('return "A" if a > 10', function(){
        expect(app.func({a:12})).to.equal('A');
      });
      it('return "B" if a <= 10', function(){
        expect(app.func({a:9})).to.equal('B');
      });
    });
    

    更新

    在这个例子中func 是非常有语法的,对于实际项目你可以看到这样的:

    module.js

    var SubModule = require('submodule');
    
    function MyModule(config, someVar) {
     //Don't use full config, only options you needed.
     //Pull out config options
      this._a = config.a;
      this._b = config.b;
    
      this.doSomethink(someVar);
      this.subModule = new SubModule(config);
    }
    
    MyModule.prototype.doSomething = function(){
      if (this._a > 10) return 'A';
      return 'B';
    }
    
    module.exports = MyModule;`
    

    子模块.js

    function MySubModule(config) {
      this._c = config.c;
    }
    module.exports = MySubModule;
    

    【讨论】:

    • 我传递变量的主要问题是当我将模块拆分为多个文件时,每次需要单独的文件时我都必须继续传递配置对象。有什么顺利的方法可以克服吗?
    • 我为你更新了答案的最后一部分。这有帮助吗?
    • 是的,当然。这几乎是我现在采用的方法。您在原始示例中使用的“freezy”功能是什么?在 npm freezy 之后用 Google 搜索,一无所获……我不应该总是冻结我的配置以防止其他开发人员或其他需要配置来修改我的原始值的模块吗?
    • Object.prototype.freeze。我建议你划分global configobject for modules manipulation的逻辑,但这是非常个人的推荐。常量config 可以为您节省一些调试时间,或占用您的开发时间。
    猜你喜欢
    • 2020-04-08
    • 2017-05-21
    • 2011-05-07
    • 2021-10-06
    • 1970-01-01
    • 2020-02-20
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多