Node.JS

Node.js最佳实践(3)

上页

 前面两个章节介绍了Node的代码风格和开发流程上一些约定,遵循这些Node社区成熟经验模式,可以让你用Node.js支撑更加大型的应用系统开发,也会帮助你成为一个真正的Node.js高手。下面继续介绍这方面的最佳实践。

一致风格

 前面章节推荐了:Javascript风格编程指南 ,当开发更大型的Javacript项目时,开发团队也比较大,这个时候最重要的是创建统一的大家都能接受的编码标准,但是这仅仅是第一步,在你们形成标准以后,你的团队所有成员还必须使用一致风格编写代码,这就引入了JSCS。

 JSCS是一种Javascript的代码风格检查器,将JSCS增加到你的项目对于项目管理是有好处的:

npm install jscs --save-dev  

 下面一部是在package.json文件中激活它,这是通过增加下面定制脚本实现的:

scripts: {
"jscs": "jscs index.js"
}

 当然你可以加入多个用来被检查的文件和目录,但是为什么我们要在package.json中增加定制脚本呢?我们安装jscs仅仅作为本地依赖,这样我们可以有一个应用系统的多个版本,这些会正常工作,因为NPM将把node_modules/.bin目录放入PATH路径中。

 你能在.jscs文件中设置定制自己的校验规则,你能在这里here发现预设的样本,可以通过--preset=[PRESET_NAME]使用它们。

 

实施JSHint / JSCS规则

 你可以将JSHint和JSCS链接起来,但是在开发者机器上运行pre-commit checks也许是个好主意:

 非常容易使用pre-commit NPM包:

npm install --save-dev pre-commit  

 在你的package.json文件中配置它:

pre-commit": [ 
"jshint",
"jscs"
],

 请注意,pre-commit将在你的package.json的脚本section段落寻找可执行的脚本,通过这样激活,每次在提交commit之前都会运行。

 

配置使用JS优先于JSON

 通常我们看到大量项目使用JSON文件作为配置格式,但是JS文件提供更加灵活的实现,鼓励你使用config.js文件:

var url = require('url');
var config = module.exports = {};
var redisToGoConfig; 
config.server = {
  host: '0.0.0.0',
  port: process.env.PORT || 3000
}; 
// look, a comment in the config file!  // would be tricky in a JSON ;) 
config.redis = {
  host: 'localhost',
  port: 6379,
  options: { 
  }
};
 
if (process.env.REDISTOGO_URL) {
  redisToGoConfig = url.parse(process.env.REDISTOGO_URL);
  config.redis.port = redisToGoConfig.port;
  config.redis.host = redisToGoConfig.hostname;
  config.redis.options.auth_pass = redisToGoConfig.auth.split(':')[1];
}

使用NODE_PATH

 你是否碰到过如下情况:

var myModule = require('../../../../lib/myModule');
 myModule.doSomething(function (err) {
  });

 当你碰到一个非常复杂的项目结构时,需要的模块非常多而混乱,为了解决这个问题有两个选择:

  1. 链接你的模块到node_modules目录
  2. 使用NODE_PATH

 

设置NODE_PATH

 假设有如下项目目录:

 这里我们不使用相对路径,而是使用NODE_PATH,指向lib目录,这是在package.json的start脚本中设置的,如下,然后通过npm start运行应用。

{
  "name": "node_path",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_PATH=lib node index.js" 
  },
  "author": "",
  "license": "ISC"
}

 假设lib/model/Car.js的内容是:

console.log('I am a Car!');

 在index.js引用这个Car.js直接使用:

var Car = require('model/Car');

 

依赖注入

 依赖注入是将一个或多个依赖注入或通过引用传递给需要的对象中,依赖注入对于测试是非常有帮助的,你能使用模拟对象注入到被测试的业务场景中,从而摆脱对数据库等生产环境的依赖进行测试。

 假设User.js内容如下:

function userModel (options) {
  var db;  
  if (!options.db) {
    throw new Error('Options.db is required');
  }
   db = options.db;  
  return {
    create: function (done) {
      db.query('INSERT ...', done);
    }
  }
} 
module.exports = userModel;

 该User.js中对Db依赖,在生产环境我们可以加入真正的Db:

var db = require('db');
// do some init here, or connect 
db.init(); 
var userModel = require('User')({
  db: db
});
userModel.create(function (err, user) {  
});

 而在测试test.js中我们可以模拟一个Db的实现fakeDb:

var test = require('tape');
var userModel = require('User'); 
test('it creates a user with id', function (t) {
  var user = {
    id: 1
  };
  var fakeDb = {
    query: function (done) {
      done(null, user);
    }
  } 
  userModel({
    db: fakeDb
  }).create(function (err, user) {
    t.equal(user.id, 1, 'User id should match');
    t.end();
  })
});

 

 上面案例有两个不同db,在index.js中有真实的db,而在第二个是创建的fake,我们可以通过注入fake到模块中进行测试。

 

 

 

 

依赖注入模式

Node.js编程之道