繁体   English   中英

有什么理由不将配置绑定到Node.js中的全局对象?

[英]Any reason not to bind configurations to global object in Node.js?

我正在寻找在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. 在每个模块中都需要配置文件。 由于我通常将配置分成单独的文件,因此我真的不喜欢这样做。 由于我并不总是使用某些文件,因此这通常也涉及检查文件是否存在。

有什么理由可以避免使用这两种方法中的任何一种? 有什么理由为什么一个人应该比其他人更受青睐?

以我的经验,选择No.2:将配置选项传递给您建议的模块是常用的,也是不错的样式。

原因

  • 它使配置与实际逻辑脱钩。 如果在模块本身中包含配置文件,则不需要依赖一个特定的配置文件。
  • 仍然存在对特定配置值的定义依赖性,这些特定配置值作为参数提供-而不是“魔术”地从全局命名空间中提取,这使得代码难以阅读,维护和测试。

顺便说一下,这几乎是每种语言的经验法则,它允许诸如全局变量/对象之类的东西以及包含“您喜欢的任何东西”的构造。 但是requirejs已经通过至少允许exports成为可以立即接受配置的功能,将您带向正确的方向。 因此,单线是要求和配置资源的一种优雅方法。

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

对于小型项目,所有三种方式都是可以接受的。 大我可以接着说:

全局变量是一个问题

如果您开始使用这种方式,则需要保护配置对象,例如var config = {...}; config.freeze(); 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');
  });
});

UPDATE

在此示例中, 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;`

submodule.js

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

暂无
暂无

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

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