Skip to content

编程规范

1. 前言

1.1 文档内容

本文档介绍公司软件产品的源程序编程规范,包括:排版、注释、标识符命名、变量使用、代码可测性、程序效率、质量保证、代码编译、单元测试、程序版本与维护等。适用于公司所有产品以及对外合作委托开发产品的软件源程序。

1.2 文档目的

为了提高公司源程序的质量,提高公司产品的维护性,提高公司软件产品的生产力。

1.3 读者对象

中青宝开发人员。

1.4 本书约定

本文档中的规范是独立于具体语言的编程规则的总原则,针对不用的编程语言或应用环境的编程规则。在遵守本规则的基础上,还必须遵守相应语言和应用环境的编程规范。

2. 后端规范

2.1 协议规范

在平台服务器与平台服务器通讯,平台服务器与逻辑服务器通讯、客户端与服务器通讯时,协议命名需要遵循相应的规则。

2.1.1 协议命名

命名规则

协议命名需要遵循如下规则:

  • 每个协议定义前,需要有精简的注释。
  • 协议命名中,每个单词或缩写单词,首字母需要大写。
  • 协议命名从左到右为:Proto关键字+业务描述+一级协议业务描述+平台通讯方式+上行/下行协议方式。

举例如下:

  1. Proto关键字:Proto对应的关键字。
  2. 业务描述:业务的具体描述。
  3. 一级协议业务描述:一级协议的业务描述。
  4. 平台通讯方式类型:
  5. 平台服务器与客户端之间通讯,对应值为"Pmd"。
  6. 区服务器服与平台服务器之间通讯,对应值为"Smd"。
  7. 客户端与服务器之间通讯,对应值为"Cmd"。
  8. 上行/下行协议方式:协议分为上行协议与下行协议。
  9. 上行协议即请求协议,对应值为"_C"。
  10. 下行协议即回复协议,对应值为"_S"。
  11. 上行协议与下行协议,对应值为"_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 游戏业务注意事项

游戏注意事项如下:

  1. 游戏服务器_C消息回调函数内,return消息内容底层会回应客户端。
  2. 游戏服务器函数返回值中,如存在返回错误码的,可遵循如下格式:return 错误码,“错误描述”。
  3. 游戏服务器不引用proto协议文件,但是组装的消息“data”,字段名字与proto的字段名字保持一致。
  4. 断线消息回调函数是:

    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

模块名根据具体情况添加。

导出方式

  1. 无特殊情况下,动画动画统一使用骨骼动画的格式导出,不要选其他类型导出方式。

  2. 无特殊情况,动画的根骨架名不要修改。

- 当一个动画文件中只有一个动画时,不要修改动画名。

- 当一个动画文件中有多个骨架和动画时,需商定骨架和动画名。

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 的垃圾收集机制、内存泄露等。