赫墨拉游戏-服务端-编程规范

为了方便大家交流和代码共享,现在此做出一个共同的代码风格约定。本规范适用于项目C++语言以及其他语言与C++的交集部分。

PS:本规范只对预计可能导致代码风格有较大不同的部分作出约定。

一、命名规范

对于所有类型的命名都有效的规范:

命名是非常重要的,

l  名称表述清楚,使用统一的英文词汇。

l  不使用英文简写,除非是一些固有的缩略语。

l  单词命名优先表达清楚意思,其次才考虑缩短长度,不过也不要太长。

l  对于无法用英文表述的命名,使用拼音。每个词看做一个单词,中间不用大写,

例如:

修仙副本 xiuxianCopy

炫阳套装 xuanyangSuit

因为汉字太多的话,大写太多会很乱。

l  使用驼峰命名法,严禁全字母大写并且没有”_”的命名。

l  所有函数、变量、类等,都必须要加注释,即使一看就懂的也翻译一下中文。

l  命名要一致,不同的功能,对于相同的概念,要用相同的名称。

 

1.           变量命名规范

l  变量名前不使用任何表示类型的前缀。

l  类内部数据成员,以前缀“_”开头;对于公开的数据成员,可以不使用前缀。

l  变量首字母使用小写。

2.           函数命名规范

l  函数名必须直观,并且能正确表达其内在功能。

l  对于函数参数中的引用和指针类型视情况以const修饰。

l  对于不修改数据成员的类成员函数,以const修饰。

l  函数名以小写开头。

3.           类和结构名命名规范

l  类名以C开头,结构以S开头,都以大写开头。

l  接口类的命名沿用上面规则,并以前缀“I”开头,例如:IInterfaceMgr,IModule。

4.           常量与宏命名规范

l  尽量不使用宏定义;

l  对于常数定义,尽量采用const修饰或enum定义;

l  对于简单的操作,采用inline函数方式定义;

l  常量名第一个字母大写。

5.           文件命名规范

l  目录名每个单词首字母大写,不使用任何分隔符;

6.           typedef类型命名规范

l  typedef std::vector<int> SeqInt; //vector的全部都在前面加Seq。

l  typedef ::std::map<int, int> DictIntInt;//map在cdl中加前缀Dict,在代码中用Map。

l  必须以大写开头。

二、布局规范

应当以IDE的原来的风格为优先。

l  程序体建议以TAB缩进,少使用空格缩进。

l  每一个函数(或类方法)之间至少保留一个空行。

l  在程序体内,具有语义转换时,必须保留一个空行。

l  不编写过长的函数代码,如果函数过长应该考虑分拆为多个函数。

l  多次使用的代码,尽量抽出来作为一个函数。

l  除“.”、“→”、“::”外,双目操作符(如:“+”、“*=”等),两侧各留一个空格。

l  单目操作符(如:“++”、“!”)与操作数之间不留空格。

l  逗号分隔符的左侧不留空格,右侧留一个空格。

l  当判断一个指针是否为空时,使用“!ptr”的形式判断。

l  不要在同一行了声明多个变量。

l  当一个函数的返回值是指针变量或引用变量时,类型与操作符(“*”或“&”)之间不留空格,操作符之后留一个空格;

l  对于复合语句,如:while, for, if等,无论复合语句中包含多少个语句,一律另起一行,并使用{}括起来;

l  尽量保持头文件中不包含头文件;

l  对于数据成员都公开的类,使用struct关键字来定义,否则使用class关键字。

l  对于计数器或迭代器,可使用前++(--)或后++ (--)时,一律使用前++(--)。

 

一些非常细的规则可以看这里:

http://blog.csdn.net/u012175089/article/details/51078360

 

三、编码的建议

这里只是一些建议和可能遇到的问题。

 

1.尽量把运算提前,能够在启动程序时进行的运算,就不要等到使用的时候才进行。

例如对于某些用[xxx,yyy]这样包着的字符串,应该在初始化的时候就进行分解,用DictIntInt来保存。而不是每次用到的时候拆一下。

又如每一级的属性,在升级之后,一个个再加起来。这是设计上的错误,在设计配置文件的时候,要充分考虑计算量。同时也要考虑策划的配置量,通常只要配一次,以后改动很小的数据就不需要考虑策划的工作量了。

2.内存中的配置文件,尽量使用map来代替vector。

3.代码里面的code很多,物品、技能、buff、updateCode等等,几乎每个配置都有一个,最好在使用的时候加上各自的单词,例如:itemCode,skillCode,buffCode等等,不能只写code,难以阅读,而且代码增多之后很容易造成混乱。

4.尽量使用公共的工具类函数,一般都放在Common/Public目录下,Util类是最常用的。

5.字符串拼接,一般使用“,”,如果要加多一层,建议使用“;”。使用公用的函数来构建和分解字符串。

6.DataTime转成int,可以去到2030年以后都不会出错,使用json保存的时候,可以放心使用int,方便比较,减少转换,而且减少json的长度。

7.智能指针不要互相指引,否则无法自动析构。

8.json原则上是用来保存一些比较散乱的字段,如果是有多个字段的结构的数组,可以考虑构建一个新的表。Json字段通常很大,如果是数组,很容易会超过最大长度。而且,很难调试和查看内存。Json最大的用途是用来存储和传输,不要过分依赖。无法调试的。

9.保存到数据库的数据,尽量使用延时保存。

10.不要写依赖于顺序而毫无逻辑的代码。

sCodeAttribute.attribute.push_back(attr.attack);  
sCodeAttribute.attribute.push_back(attr.life);  
sCodeAttribute.attribute.push_back(attr.physicalDefense);  
sCodeAttribute.attribute.push_back(attr.magicalDefense);  
sCodeAttribute.attribute.push_back(attr.wreck);  
sCodeAttribute.attribute.push_back(attr.block);  
sCodeAttribute.attribute.push_back(attr.miss);  
sCodeAttribute.attribute.push_back(attr.demiss);  
sCodeAttribute.attribute.push_back(attr.crit);  
sCodeAttribute.attribute.push_back(attr.decrit);  

这样的代码,中间加个字段,就会完全乱了。

11.推送数据要尽量缩减,通常一个功能的全部数据在登录的时候推一次,之后更新某个字段才逐个字段推送更新。

12.声明变量的时候顺手初始化一下。

13.循环用的迭代器,如果是后面没有使用到,就应当放到循环内部。不同循环不要共用迭代器。

14.配置文件还是服务端来设计,策划只是给建议和参考。我们要充分考虑策划的命名,绝大部分是不能直接使用的,通常口头说的是一个名称,写到文档又是一个,等上线后又是一个命名。如果不理想,还会改很多次。而且,一个名称可能会改掉,用在其他系统上面。这个时候就非常混乱了。

15.要考虑卡顿的问题。出现卡一般可以分为几种情况:

(1)玩家实在是太多,现在的行业情况,几乎不可能出现了,只有在游戏后期,很多个服合成一个服才会出现。但是这样的玩家,在线的还是很少的。所以平时一般不考虑。

(2)功能业务上设计有问题,让玩家同一个非常短的时间段内必须做某件事情。例如设个5分钟的运镖3倍时间,这个时刻一到,所有玩家都在运镖。碰到这种问题,要主动跟策划商量,让其认识到可能发生的情况。这种错误很很明显,可能每天到这个时间段,就会卡,也会有很多玩家反映。但是修改的目标也很明确。

(3)代码逻辑问题,最容易出现的就是for循环。例如300级的坐骑,如果每级的属性都是独立计算,每次访问,升级,甚至走一步都检测一下。还得循环几百次,累计起来的计算量会很大的。这种错误非常隐蔽,多少次循环才算是有问题?这个无法下定论,但是计算量肯定是累计在那里,这个功能累积一下,那个功能累积一下,整个系统就会很卡。这种卡是无时无刻,偶尔爆发一下完全动不了,难以寻找,也不知服务端还是客户端的问题。通常都是伴随着游戏的整个生命周期。几乎无法根治,只能在设计和编写代码的时候有意识地避免。

16.独立的功能尽量独立管理自己的数据,如果使用了一些写死的数据,也要改成常量。

17.除数必须检测是否为0,不管是否从业务上看起来不可能为0.

18.概率的问题,C++随机数最大值是30000多。另外,涉及到战斗和属性相关的,统一使用1000,用常量FIGHT_RATING。其他的没什么特殊要求用100就行了。

19. 在一段程序里面,对于一些检测判断,比较容易return或者抛异常的,应该放在前面。变量尽可能放到要用的时候才声明。

20. 尽量不要把int当bool来使用。代码有变动之后很容易出错,而且就算用int来存放结果,很多时候0不一定代表错误。

21.同一个功能的配置,建议放在同一个表里面。当然,东西很少的小功能,可以放到t_const里面。但是也有很多功能,可能内容很散,有多种配置,而且数据量不是很大,可以放到同一张表里面。

通常用这种格式来写,但是要注意几点:

    1.必须有desc字段,写清楚每个字段的意义,上面的还不是很详细。应该这样:

    type类型value1:阶数,value2:星数,value3:exp,value4:属性id

    2.在代码里面,要写自己功能的结构,不能直接使用value1,value2,value3.在loadConfig函数里面就应该转换完成。这种通用表格的内容不应该出现在业务层的代码里面。

 

22.一般情况下,只有接口访问才能够直接抛异常,其他地方抛异常会出问题的,例如登录。

23. 对于某些属性,过了某个时间失效的情况。设个定时器,到了这个时间点,就把所有的都改掉,这是策划的思想。我们通常在使用到的时候检测一下是否失效了就行了。

 

posted @ 2017-02-07 19:38  肥宝游戏  阅读(399)  评论(0编辑  收藏  举报