Skip to content

Instantly share code, notes, and snippets.

@stableShip
Last active March 3, 2017 08:05
Show Gist options
  • Save stableShip/0b3deabd159f2ea2ff9889313cf8bd7b to your computer and use it in GitHub Desktop.
Save stableShip/0b3deabd159f2ea2ff9889313cf8bd7b to your computer and use it in GitHub Desktop.
Node编程规范
# Node编码规范
## 注释
使用代码注释的目的是用文字说明代码的作用(即为什么要用编写该代码,而不是如何编写),说明何时可能出错和为什么出错。通常在编写代码前进行注释,在要注释的代码前书写注释。
1. 注释可以采用`/*注释内容*/ `和`//注释内容`两种注释符号,涉及到多行注释时采用前者的方式。
2. 对于一行代码的注释可放在前一行及本行上,不允许放在下一行,更不允许在一行语句的中间加入注释。
3. “路由” 注释:
```
/**
* @api {请求方法: get|post} 请求路由名称
* @apiVersion api适用版本
* @apiName 请求唯一名称
* @apiGroup api所属组
* @apiDescription api描述
* @apiHeader {参数类型} 请求头参数名称 请求头参数值
* @apiHeader {String} accept application/json;charset=utf-8
*
* @apiParam {参数类型} 请求参数名称 请求参数值
* @apiParam {Number} token 登陆凭证
*
* @apiSuccess {返回值类型} 返回值名陈 返回具体值
* @apiSuccess {Number} err 错误码:`0`-成功,`!0`-失败
*
*/
```
api注释语法参照: http://apidocjs.com/
4. 函数注释:
```
/**
* 方法的功能描述
* @param args 参数的含义
* @return 返回的数据格式
*/
```
5. 局部变量、字段、属性的注释:主要变量必须有注释。
6. 不必每行都加注释,在3~10行左右的段落做注释要好于每行都做注释。
7. 代码删除,不要使用注释的形式, 直接进行删除.
-----
## 代码排版格式
要上传时使用webstorm选择要提交的代码, 进行格式化后再进行上传.
1. 每一个开始括弧在源程序中紧跟逻辑代码,结束的括弧需要独占一行。如:
```
for (int i = 0; i < 10; i++) {
//逻辑代码
}
```
2. 对于if,if-else,while,for,switch,case这些语句都必须使用{}扩起来。不要只有一行就不使用{}
```
if (true) {
console.log('winning');
}
```
3. 代码长度
每行只能有一个语句
每行代码最多不得操作120个字
每个函数方法内代码长度尽量控制到不超过70行。
4. 使用标准回调
Node 的异步回调函数的第一个参数应该是错误指示
```
function cb(err, data) {...}
```
5. 立即返回
对 满足退出条件的立即返回, 不要使用if, else进行处理
Right:
```
if(true){
return true;
}
// 执行false处理
```
Wrong:
```
if(false){
// 执行false处理
}
return true;
```
6. 大括号的使用约定
如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果
是非空代码块则:
* 左大括号前不换行
* 左大括号后换行
* 右大括号前换行
* 右大括号后还有else等代码则不换行;表示终止右大括号后必须换行
-----
## 命名规范
1. 文件命名
文件命名采用下划线命名法
```
java_script.js
```
2. 类
采用大驼峰命名法, 尽量避免使用单词的缩写,除非它的缩写已经广为人知,如HTTP
```
// 大驼峰
JavaScript
```
3. 方法
采用小驼峰命名法, 尽量避免使用单词的缩写, 异步方法必须添加Async后缀.
```
// 小驼峰
javaScript
// 同步方法
set
// 异步方法
setAsync
```
4. 变量
采用小驼峰命名法, 变量必须起有意义的名字,使其他组员可以很容易读懂变量所代表的意义,变量命名可以采用同义的英文命名,可使用几个英文单词,第一个单词首字母小写,其他单词首字母大写。
```
// 小驼峰
userName;
```
5. 常量
所有常量名均全部大写,单词间以‘_’隔开
避免在程序中直接出现常数,使用超过一次的应以常量定义替代。
```
{
JAVA_SCRIPT: 1
}
```
6. 数据库字段
所有字段使用小驼峰进行命名
```
// 小驼峰
javaScript;
```
## 文件规范
1. 所有模块分为 数据库表结构层`schema`(lib文件夹), 数据库服务层`service`(model文件夹), 路由层'router'(router文件夹),
2. 数据库表结构层`schema`(lib文件夹), 定义数据库表数据结构
3. 数据库服务层`service`(model文件夹), **所有和数据库交互的, 都定义在该层, 必须定义操作基础方法(增删改查)**, 其他方法自行扩展:
* 获取模块列表方法 getXXXListByCondictionAsync , conditon包含查询的基础条件, 示例:
```
/**
* 根据条件查询banner列表
* @param condition
* @returns {*}
*/
static getBannerListByCondictionAsync(condition) {
return co(function*() {
yield BannerService.updateBannerStatusAsync();
var limit = condition.rows && parseInt(condition.rows) || 10;
var pages = condition.pages && parseInt(condition.pages) || 1;
var skip = (pages - 1) * limit;
var query = {};
if (condition.name) {
query.name = new RegExp(name);
}
if (condition.begin) {
var begin = new Date(condition.begin);
begin = new Date(begin.getFullYear(), begin.getMonth(), begin.getDate());
query.startdatetime = {$gte: begin};
}
if (condition.end) {
var end = new Date(condition.end);
end = new Date(end.getFullYear(), end.getMonth(), end.getDate() + 1);
query.enddatetime = {$lte: end};
}
if (condition.status && !_.isEmpty(condition.status) && _.isArray(condition.status)) {
var status = _.map(condition.status, (status) => {
return parseInt(status)
});
query.status = {$in: status};
}
var banners = yield model.banner.aggregate()
.match(query)
.sort({sort: -1})
.skip(skip)
.limit(limit)
.project({
name: 1,
bannerImage: {$concat: ["http://", config.ALIOSS.imageHost, "/", "$bannerImage"]},
startDateTime: 1,
endDateTime: 1,
status: 1,
jumpType: 1,
sort: 1,
jumpTo: 1,
businessType: 1,
jumpParams: 1,
eduit: 1,
makeDate: 1,
editDate: 1
});
return banners;
})
}
```
* 获取模块列表总数 getXXXListCountByCondictionAsync, 示例:
```
/**
* 根据条件查询banner列表总数
* @param condition
* @returns {*}
*/
static getBannerListCountByCondictionAsync(condition) {
return co(function*() {
var query = {};
if (condition.name) {
query.name = new regexp(name);
}
if (condition.begin) {
var begin = new date(condition.begin);
begin = new date(begin.getfullyear(), begin.getmonth(), begin.getdate());
query.startdatetime = {$gte: begin};
}
if (condition.end) {
var end = new date(condition.end);
end = new date(end.getfullyear(), end.getmonth(), end.getdate() + 1);
query.enddatetime = {$lte: end};
}
if (condition.status && !_.isEmpty(condition.status) && _.isArray(condition.status)) {
var status = _.map(condition.status, (status) => {
return parseInt(status)
});
query.status = {$in: status};
}
var count = yield model.banner.count(query);
return count;
})
}
```
* 更新模块某条数据 updateXXXAsync, 示例:
```
/**
* 更新banner
* @param banner
* @returns {*}
*/
static updateBannerAsync(banner) {
return co(function*() {
var id = ObjectId(banner._id);
// 删除banner空值
for (var key in banner) {
if (_.isUndefined(banner[key]) || _.isNull(banner[key])) {
delete banner[key];
}
}
var result = yield model.banner.findOneAndUpdate({_id: id}, banner, {new: true});
return result;
})
}
```
* 删除模块某条记录 deleteXXXByIdAsync, 示例:
```
/**
* 根据id删除某个banner
* @param id
* @returns {*}
*/
static deleteBannerByIdAsync(id) {
return co(function*() {
id = ObjectId(id);
var banner = yield model.banner.remove({_id: id});
return banner;
})
}
```
* 增加模块一条数据, createXXXAsync 示例:
```
/**
* 创建banner
* @param banner
* @returns {*}
*/
static createBannerAsync(banner) {
return co(function*() {
if (!banner.sort) {
var banners = yield model.banner.find().sort({sort: -1}).limit(1);
banner.sort = !_.isEmpty(banners) && banners[0].sort + 1 || 1;
}
// 删除banner空值
for (var key in banner) {
if (_.isUndefined(banner[key]) || _.isNull(banner[key])) {
delete banner[key];
}
}
var result = yield model.banner.create(banner);
return result;
})
}
```
4. 路由层'router'(router文件夹), 调用service层提供的方法, 所有涉及数据库查询**都不要写在router层.**
-----
## 路由定义规则
1. 在 路由层'router'(router文件夹) index.js文件夹, 定义不同版本的路由索引, 如:
`app.use('/v4', v4_route);`
2. 在各个版本index.js文件夹中, 定义该版本包含的路由, **所有的路由定义都在index.js文件中, 不要再继续在下一层传播, 方便查阅**, 如:
`router.use("/admin/banner", require('./admin/banner'));`
3. 每个不同模块尽可能使用单独一个文件进行相应路由编写, 如:
```
// banner.js
router.post("/findOne", ...)
router.post("/list", ...)
router.post("/delete", ...)
router.post("/update", ...)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment