编程规范
1. 前言
1.1 文档内容
本文档介绍公司软件产品的源程序编程规范,包括:排版、注释、标识符命名、变量使用、代码可测性、程序效率、质量保证、代码编译、单元测试、程序版本与维护等。适用于公司所有产品以及对外合作委托开发产品的软件源程序。
1.2 文档目的
为了提高公司源程序的质量,提高公司产品的维护性,提高公司软件产品的生产力。
1.3 读者对象
中青宝开发人员。
1.4 本书约定
本文档中的规范是独立于具体语言的编程规则的总原则,针对不用的编程语言或应用环境的编程规则。在遵守本规则的基础上,还必须遵守相应语言和应用环境的编程规范。
2. 后端规范
2.1 协议规范
在平台服务器与平台服务器通讯,平台服务器与逻辑服务器通讯、客户端与服务器通讯时,协议命名需要遵循相应的规则。
2.1.1 协议命名
命名规则
协议命名需要遵循如下规则:
- 每个协议定义前,需要有精简的注释。
- 协议命名中,每个单词或缩写单词,首字母需要大写。
- 协议命名从左到右为:Proto关键字+业务描述+一级协议业务描述+平台通讯方式+上行/下行协议方式。
举例如下:

- Proto关键字:Proto对应的关键字。
- 业务描述:业务的具体描述。
- 一级协议业务描述:一级协议的业务描述。
- 平台通讯方式类型:
- 平台服务器与客户端之间通讯,对应值为"Pmd"。
- 区服务器服与平台服务器之间通讯,对应值为"Smd"。
- 客户端与服务器之间通讯,对应值为"Cmd"。
- 上行/下行协议方式:协议分为上行协议与下行协议。
- 上行协议即请求协议,对应值为"_C"。
- 下行协议即回复协议,对应值为"_S"。
- 上行协议与下行协议,对应值为"_CS"。
命名实例
请求注册账号举例
// 请求注册帐号
Message RequestAccountRegisterLoginUserPmd_C
{
Required string account = 1; // 账号
Required string password = 2; // 密码
Optional string code = 3; // 验证码
}
请求注册账号协议名的详细说明如下:

返回注册账号举例
// 返回注册帐号
Message ReturnAccountRegisterLoginUserPmd_S
{
Required string account = 1; // 账号
Required uint64 accountid = 2; // 账号ID
}
返回注册账号协议名的详细说明如下:

2.1.2 协议字段命名
协议字段命名需要遵循如下规则:
- 平台服务器协议中的协议字段名称统一小写。
- 游戏业务协议字段名称首单词小写,后续单词首字母大写。
- 每个协议字段定义后,需要有精简的注释。
- 尽可能让required类协议写在前面,同类描述字段相邻靠拢表示。(同类描述字段表示相同类型的描述字段,如:玩家的昵称、头像为一类;玩家的金币、积分为一类等。)
- 各字段之间,尽可能保证格式整齐。
2.2 游戏业务命名规范
游戏业务命名需要遵守以下规则:
- 文件内lua函数名,所有单词首字母均大写,变量名以及函数参数第一个单词首字母均小写,后续单词首字母大写。
- 游戏服务器消息回调的函数以"Cmd+消息名称"命名。
- 每个函数定义前,需要有精简的注释。
2.3 游戏业务注意事项
游戏注意事项如下:
- 游戏服务器_C消息回调函数内,return消息内容底层会回应客户端。
- 游戏服务器函数返回值中,如存在返回错误码的,可遵循如下格式:return 错误码,“错误描述”。
- 游戏服务器不引用proto协议文件,但是组装的消息“data”,字段名字与proto的字段名字保持一致。
-
断线消息回调函数是:
Tcp = Tcp or {}
Tcp.account_disconnect
3.前端规则
3.1 变量命名规则
1. 静态变量(全大写,以"_"分开各单词)。
例如:
public static CHAT\_ROOM: string="chat_room";
2. 类公共变量(开头字母小写,无前缀,驼峰式)。
例如:
public defaultLoadingView: any:
3. 类私有变量(以单下划线开头)。
例如:
private _uis: Object= new Object();
4. 类局部变量(小写开头,驼峰式)。
例如:
var onLoadSound: Function = function (data: egret.Sound) {
self._soundRes[soundName] = data;
}
类局部变量(onLoadSound)为小写开头,驼峰式。
5. 形参变量(小写,驼峰式)。
Pubic showParticle(parName:string,dyration?:number,starX?:number,starY?:number)
形参(即括号里面内容:parName:string,dyration?:number,starX?:number,starY?:number)为驼峰式,如parName中N为大写。
3.2 常用类型前缀格式
| 名称 | 类型 | 前缀缩写 |
| 字符串 | String | str |
| 布尔值 | boolean | is |
| 数组 | Array arr | arr |
| 影片剪辑 | Egret.MovieClip | mc |
| 按扭 | Button | btn |
| 文本 | TextField/label | txt |
| 声音 | Sound | snd |
| 其它实例对象 | Any | obj |
| 普通函数 | Function | func |
| 事件函数 | Event | On开头 |
3.3 类命名规则
1. 一般类(首字母大写,能简洁明了表达出类的意图)。
例如:class ChatAllView
2. 接口(以字母I作为首字母,名称的首字母也大写)。
例如:Interface IGameConfig
3.4 文件夹/模块命名规则
首字母小写。
例如:
UniLib.NetMgr.init
3.5 注释规则
1. 类注释
/**
* 音频管理
*/
export class SoundMgr
2. 属性注释:
/**
* 当前游戏接入平台id
*/
public static platId:number;
3. 函数注释:
/**
* 初始化平台网络连接
* @method uniLib.NetMgr.init
* @param url {string} 登录URL
* @param gameID {Number} 游戏ID
* @param zoneID {Number} 区服ID null:自动选区 -1:不自动选区
* @param callBack {Function}登录成功回调
* @param loginFail {Function}登录失败回调
* @param thisObj 当前对象。永远都this
*/
3.6 资源命名规则
资源命名规则是表示资源文件的命名规则。
1. 资源命名遵循:项目名_模块名_资源名。
例如:
ziyuanmingming
2. 文档类命名:项目名+Main。
例如: BPMain
3. 皮肤配置文件命名:项目名简写+thm.json。
例如: bp.thm.json
4. 资源配置文件命名:项目名简写+res.json。
5. 文档类需继承uniLib.GameDoc,需要实现preLoadEnd方法,uniLib使用前需使用uniLib.init进行初始化。
6. 皮肤配置、资源配置、预加载资源加载完成后需要调用 preLoadEnd方法。
7. 消息函数支持匿名调用和回调两种方式来调用。
3.7 组件命名规则
组件命名规则是指库文件使用时的命名规则。
| 组件 | 后缀 | Example |
| Button | _btn | example _btn |
| Label | _lbl | example_lbl |
| BitmapLabel | _blbl | example _blbl |
| CheckBox | _chk | example _chb |
| DataGroup | _dgrp | example _dgrp |
| EditableText | _etxt | example _etxt |
| Image | _img | example_img |
| List | _lst | example_lst |
| ProgressBar | _pb | example_pb |
| HscrollBar | _hsb | example_hsb |
| HSlider | _hsl | example_hsl |
| Rect | _rect | example_rect |
| RadioButton | _rdo | example_rdo |
| TabBar | _tb | example_tb |
| TextInput | _txt | example_itxt |
| toggleButton | _tbtn | example_tbtn |
| ToggleSwitch | _tswc | example_tswc |
| vScrollBar | _vsb | example_vsb |
| vslider | _vsl | example_vsl |
| Panel | _pnl | example_pnl |
| Group | _grp | example_grp |
| Scroller | _scr | example_scr |
| ViewStack | _vst | example_vst |
| Bitmap | _bmp | example_bmp |
3.8 动画命名规范
使用dragonbones制作的动画资源命名方式与导出方式需要遵守以下规则。
命名方式
文件类型与文件名的命名规范如下:
| 文件类型 | 文件名 |
|---|---|
| Drag数据文件 | 项目名_模块名_资源名_effect |
| 材质图片 | 项目名_模块名_资源名 |
| 材质集 | 项目名_模块名_资源名 |
其中,项目名与资源名的命名规则如下:
| 项目 | 项目名 | 资源名 |
|---|---|---|
| AAA大厅 | Lobby | lb |
| 百家乐 | BaiJiaLe | bjl |
| 二八杠 | ThisBar | tb |
| 老虎机 | SuperSlot | sl |
| 斗牛 | BullPoker | bp |
| 麻将 | MaJiang | mj |
| 扎金花 | JinHua | jh |
| 梭哈 | FiveCardStud | fc |
| 海外老虎机 | Slot | slt |
| 翻牌机 | Att | att |
模块名根据具体情况添加。
导出方式
-
无特殊情况下,动画动画统一使用骨骼动画的格式导出,不要选其他类型导出方式。
-
无特殊情况,动画的根骨架名不要修改。
- 当一个动画文件中只有一个动画时,不要修改动画名。
- 当一个动画文件中有多个骨架和动画时,需商定骨架和动画名。
4. lua规范
4.1 lua命名规范
lua命名有如下规范:
1. 所有lua文件,命名时使用小写字母。
例如:
unilight.lua
2. 变量名、函数参数名第一个单词首字母均小写,后续单词首字母大写,尽可能使用有意义的英文。
例如:
local pokerArray= {}
3. 函数名所有单词均首字母大写。
例如:
function OnTimer()
4. 常量定义时用大写,单词间_分割
例如:
GAME_TIME_WAIT = 30 -- 等待时间为30秒
5. 枚举值定义时加前缀ENUM_。
例如:
ENUM_ROOM_TYPE = {
BRONZE = 1, -- 青铜场
SILVER = 2, -- 白银场
GOLD = 3, -- 黄金场
DIAMONDS = 4, -- 钻石场
MASTER = 5, -- 大师场
KING = 6, -- 王者场
}
4.2 lua文件规范
lua文件有如下规范:
1. 文件开头加上此文件的功能、职责的简要描述;每个文件都加module 限定词;
2. 导入的模块都加local 限定词;
3. 被用来公共调用的函数都加如下格式的注释。
例如:
--此函数检测是否可以从A(oldx, oldy)点走到B 点(newx, newy)
--@param oldx 当前所在点x
--@param oldy 当前所在点y
--@param newx 目标点x
--@param newy 目标点y
--@return 若可以到达,返回true;否则返回false
function obj:CheckBar(oldx, oldy, newx, newy)
…
end
4. 函数与函数之间、以及一些定义之间加上空行。
5. 文件内不允许出现全局变量,_G.instance 例外。
6. 函数内的临时变量、文件内的局部函数都加上local 限定词。
7. 函数的行数过长(大于100 行)时,尽量拆分为多个子函数;函数中一些晦涩的部 分,一定要加上注释。
8. 短小的注释使用--;较长的注释使用--[[ ]]。
9. assert 函数开销不小,请慎用。
4.3 分隔和缩进
1. 使用空行。 在下述情况下使用单行的空白行来分隔:
-
在函数之间。
-
在函数内部代码的逻辑段落小节之间。
例如: 函数A中 下面两个if语句段间 用空白行分隔,
function FuncA(a, b)
local c = 0
if a > 1 then
c = c + a
end
if b > 0 then
c = c + b
end
return c
end
2. 使用空格符。
除正常的成分之间以空格符分隔外(如数据类型和变量名之间),在下述情况下也 应使用一个空格符来分隔:
- 运算符和操作数之间,
如:c = a + b;
- 在参数列表中的逗号后面,
如: function m1(year,month) end
3. 在下列情况下不要使用空格。
例如:
函数定义时:
function test1(a)
end
而不是:
function test1( a )
end
函数调用时:
test1(3)
而不是:
test1( 3 )
不能如此的原因在于:
- 容易忘记相关空格,导致风格不统一,这样不如不加;
- lua 解析语法时是采用空格等分割来解析的,某些情况下,若不小心加空格会导致 非预期的结果。
4. 使用换行符。
一行中只写一条语句; 一条语句的长度一般超过了80 个字符时,可拆分成多条语句; 5. 使用小括号。 可以使用小括号来强行规定运算顺序 6. 使用缩进。 在下述情况下应用缩进:
-
方法体或语句块中的成分。
-
换行时的非起始行。 缩减量一般为在上一级成分的基础上跑到下一个制表位。
4.4 代码建议
1. 代码中使用的一些函数尽可能在文件开头或者当前局部环境中加local前缀重新定 义下。
例如:
local assert = assert
2. 不要使用元表来实现继承。
3. 高级特性尽可能不用。
4. 写代码时尽可能写的简单,考虑性能时先做好推断,看看能提升多少,增加的复杂度以及造成的代码晦涩有多严重,然后再决定如何做。
5. 加载的xml 数据表,尽可能的做好数据校验,若校验失败,要出发断言,使服务器无法启动;不要等出错时,回过头来检查是数据表问题还是逻辑问题。
6. 出错时,记录好错误日志。 有的函数开销比较大,而调用的频率很低,那么可以不对他做优化; 反之,有的函数开销较小,但是调用的频率很高,从如何降低调用频率以及减少函数开销两个角度去思考,然后定下优化方案。
7. 提交代码之前,去掉或者注释掉无关的代码;测试下保证服务器可以正确启动。
8. 尽量减少表中的成员是另一个表的引用。考虑lua 的垃圾收集机制、内存泄露等。