2012-06-12 晚上 at Taobao
质量好的代码,通常都是有观赏性的。
让代码能在眼睛里运行,无须猜测运行结果。
参与团队开发或者给开源项目提交pull request之前,必须了解项目的编程规范。
Coding
也是一门 艺术
(link)。
tab
=> 2 space
避免代码显示差异,入乡随俗,这是 nodejs
源码及 module
采用的标准。
必须让编辑器自动转换:
function
关键词与函数名
之间有一个空格
函数名
与左括号
之间没有空格
// right
function foo(bar) {...}
foo(bar);
foo(function callback(err, data) {...});
foo(function (err, data) {...});
// wrong
function foo (bar) {...}
foo (bar);
foo(function callback (err, data) {...});
foo(function(err, data) {...});
语法元素
与左括号
之间,都有一个空格
// right
return (a + b);
if (a === 0) {...}
for (var k in map) {...}
while (i > 0) {...}
// wrong
return(a + b);
if(a === 0) {...}
for(var k in map) {...}
while(i > 0) {...}
操作符
号与参数
之前有一个空格
// right
var a = 1 + 2;
for (var i = 0, l = items.length; i < l; i++) {...}
//wrong
var a=1+2;
for(var i=0,l=items.length;i<l;i++){...}
好的变量与函数命名,可以避免大量的注释,以及让圈内的同学感到熟悉。
驼峰式:
functionNamesLikeThis
, variableNamesLikeThis
ClassNamesLikeThis
, EnumNamesLikeThis
methodNamesLikeThis
SYMBOLIC_CONSTANTS_LIKE_THIS
// var definition
var adminUser = db.query('SELECT * FROM users ...');
// function definition
function run() {...}
// Class definition
function BankAccount() {...}
===
你能只看到代码,就能保证下面对比的结果吗?
0 == ''
1 == true
2 == true
0 == '0'
false == 'false'
false == '0'
" \t\r\n " == 0
===
结果绝对是 坑爹
的:
> 0 == ''
true
> 1 == true
true
> 2 == true
false
> 0 == '0'
true
> false == 'false'
false
> false == '0'
true
> " \t\r\n " == 0
true
callback(err, data)
在 nodejs 的代码里面,异步IO回调方法必须遵循的潜规则: callback(err, data)
var fs = require('fs');
fs.readFile(__dirname + '/foo.txt', 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
console.log(data);
});
dns 域名查询ip: dns_dns_lookup_domain_family_callback
var dns = require('dns');
dns.lookup('taobao.com', function (err, address, family) {
console.log(err, address, family);
});
Error
function request(url, callback) {
requestURLAsync(url, function () {
// ...
if (isTimeout) {
return callback('Request `' + url '` timeout.');
}
callback(null, ...);
});
}
将 String
当 Error
使用,会有什么问题呢?
Error
使用 String
会丢失了 Error
的上下文堆栈信息: A String is not an Error
正确的方式:
function request(url, callback) {
requestURLAsync(url, function () {
// ...
if (isTimeout) {
var err = new Error('Request `' + url '` timeout.');
err.name = 'RequestTimeout';
return callback(err);
}
callback(null, ...);
});
}
demo场景: 复制文件 foo.txt
内容到 bar.txt
function copyfileNestedCallback(from, to, callback) {
fs.stat(from, function (err, stats) {
if (err) {
return callback(err);
}
fs.readFile(from, function (err, content) {
if (err) {
return callback(err);
}
fs.writeFile(to, content, function (err) {
if (err) {
return callback(err);
}
return callback(null, content.length);
});
});
});
}
事件驱动
方式: EventEmitter
function copyfileEventEmitter(from, to, callback) {
var ep = new EventEmitter();
ep.on('stats', function (stats) {
fs.readFile(from, function (err, content) {
if (err) {
return ep.emit('error', err);
}
ep.emit('content', content);
});
});
ep.on('content', function (content) {
fs.writeFile(to, content, function (err) {
if (err) {
return ep.emit('error', err);
}
return callback(null, content.length);
});
});
ep.once('error', function (err) {
ep.removeAllListeners();
callback(err);
});
fs.stat(from, function (err, stats) {
if (err) {
return ep.emit('error', err);
}
ep.emit('stats', stats);
});
}
更多解决方案: Control flow / Async goodies
/
#