代码设计规范


本文讨论的是一些码农劳动过程中的一些基本规范,类似于人们平时需要注意卫生才能少生病,本文讨论的级别基本处于“饭前便后要洗手”,至于“如何预防非典”之类高等级的规范不在本文范围内。

 

一、       不能报黄页,避免数据错误

每写完一个功能得运行测试一下,不要认为编译通过就没问题了。某些时候一个已经测试通过的代码,经过一个小的代码上的修改可能导致其他功能报错。有些时候编译通过的代码也有可能在运行时出错,比如1除以0这种代码。这个问题不多说了,总之用户不希望看到一堆看不懂的字符串弹出在界面上。

大多数情况编译通过,又执行一遍的代码,往往容易麻痹大意,界面上A字段的值存到了B字段里,C字段的值又存到了A字段里。以大家在大学时候都做臭了的图书馆管理系统为例,新增图书功能,往往我们编写好代码编译通过后运行一下,输入的书名都是那些“asdf”或者“qwer”之类的字符串,因为它们就在你左手位置方便又快捷,于是乎你点击添加按钮后看到书目列表中多了一条书目就感觉万事大吉了,殊不知在真正使用时发现录入一本书的信息后,在书目列表中刚刚录入的书目跑到了作者字段了,作者跑到出版社字段上去了。这里推荐一个小白的方法来进行编译后的测试。

录入书名要用“书名1”这样的字符串,作者用“作者1”,出版社就写“出版社1”,新增后在书目列表中能够清晰的看到书目、作者与出版社所对应的信息,这样比刚才的“asdf”要清晰多了,而且一旦出现字段对应错误的现象也能消化在开发阶段,避免暴漏给外人(某些时候外人指的是项目组以外的人,某些时候外人就是除自己以外的所有人)。

二、       单元测试

有些代码是写在业务层,而且前台触发时机很特别,比如某些定时任务,需要计算大量数据,一个月才执行一次,执行一次需要半个小时,这种业务层的代码测试起来就很麻烦。

还是举刚才图书馆管理系统的例子,图书馆每个月都要统计每本图书的外借次数,以统计出哪本书比较受读者欢迎,简称为书的受欢迎度。受欢迎度是通过一个复杂的公式计算得出,就是从数据库中取出数据,然后利用程序计算,再写回数据库。计算受欢迎度的程序只有每月的固定时间才能出发,而且执行一遍的时间很长。一旦某本书的受欢迎度计算出现问题,要调试一遍那就要完整的计算一遍所有书的受欢迎度,这是一件很恐怖的事情。

所以遇到这种情况我推荐大家使用单元测试工具,NUint。它相当于一个main函数,使用NUint,加上出错的图书id作为参数,执行一下业务层计算受欢迎度的代码即可调试,而且只对受欢迎度出错的图书进行计算,执行时间也不会很长。在那些没有界面的业务中,非常适合使用单元测试工具。

三、       自己感觉用起来不方便的地方一定是优化点

直接举例。

还是图书馆管理系统,查询图书后,点击查询结果跳转到本页。如果这时我想比对一下两本书的信息就只能按浏览器的后退键了,这样我刚刚点开的那本书就又看不到了。所以查询结果的连接应该设计为打开新窗口的弹出形式。

四、       函数功能要尽量单一

函数的功能要精良单一,尽量只完成一个业务操作,如果某些业务比较复杂那么最好把复杂的业务拆分为多个子函数,再用一个父函数来按一定顺序调用这些子函数。

以图书借阅为例,首先应该验证所借图书是否处于“在库”状态,其次验证读者的借阅数量是否超出限制,如果以上两条验证都通过了增加一条借阅记录,并将图书的状态置为“外借”。以上外借业务的函数中包含四个步骤,那么就可以将这四个步骤独立出来写成四个子函数。

这样做的目的是使代码结构清晰,更主要的目的是为了修改某个子函数功能的时候不影响其他子功能的代码。

还是以上面的借阅功能的验证读者的借阅数量是否超出限制为例。原始需求为所有人的借阅图书数量为5本。现在需求变更,学生只能借阅5本,非学生读者可以借阅10本。这样代码的修改只局限于验证读者的借阅数量这个函数里,不会影响其他功能的代码了。如果再新增功能的话只要再新加一个函数即可,在主函数中调用一下,天晓得哪天这个新增的小需求又要取消了,如果取消只要将主函数中调用这个子函数的语句注释掉即可,因为天晓得哪天这个被取消的小需求又要恢复使用。

五、       反复粘贴的代码请做成独立的函数调用

这基本上是一句废话,某段代码反复被粘贴使用,说明这段代码在很多功能中被使用,建议将其独立成函数来使用,是为了将来统一修改这段代码的时候方便。如果没有独立成函数使用又要修改,那么只能使用查找替换的方法来统一改代码了,这样做无形中增加了代码正确执行的风险。

六、       数据库表命名尽量不要加前缀

数据库在设计的过程中尽量不要加前缀。我们在数据库管理软件中查找表要么是用肉眼去找,要么是用键盘来定位,比如先选中第一个表,再按键盘上的“S”键,这时就选中了以S开头的第一个表上了,当数据库中的表超过50个的时候,这样定位表的位置是很快的。而且因为数据库表与表之间的关系都是平级关系,没有文件夹的概念,所以我们只能靠这种方式缩小查找范围。

还有一点,大多数时候我们的代码都是通过代码生成器自动生成的,各个代码层中的类名都是基于表名来自动命名的。在编码的过程中如果想创建某个类的对象首先输入的是类的前缀,此时编译器自动提示出来的类名不是我们最想要的,所以还得继续键入类名的下几个字母,这样无形中又增加了我们编码的时间,而且增加的是一些无意义的劳动,就因为设计数据库的时候表名有前缀。

七、       测试时反复使用的功能必是用户的重点关注的功能

软件设计中也是存在二八原则的,百分之二十的代码使用频率为百分之八十,剩下百分之八十的代码使用频率只有百分之二十。所以那些在我们测试运行时都经常使用的功能也都是用户未来使用过程中的常用功能。如果这些常用功能在开发测试阶段用起来都不方便,那么在真正使用过程中客户也一定会提出修改意见。

搜索图书信息时没有排序条件,排序规则是按照数据库默认的规则。当新建一条图书信息时会跳转到图书搜索页面,这时新建图书就不一定会出现在什么位置了。看看,我们自己开发测试用起来都不方便。所以搜索图书的查询结果应该按图书的创建时间逆序排序,新书放在前面,旧书放在后面,这样新建图书信息的时候,刚刚新增的图书就在搜索结果的第一个位置上了。我们开发人员需要的功能往往和用户的需求是类似的。

八、       两个类似的业务需要设计两套表

两个类似的业务最好设计两套数据库表,如果客户在需求分析阶段就提出有两个功能是相似的,那么就说明客户在未来的发展过程中这两个功能是独立变化的。

还是图书馆管理系统的例子。图书存放的位置称为书库。某个学校本部的图书馆只有一层楼,而新校区的图书馆有5层楼。这样书库的概念在新校区就有了楼层的属性。所以在设计楼层这个业务的时候一定要将本部和新校区分开来设计,如果某一天本部的图书馆要重盖,不仅平房变楼房,而且还是多栋楼组成,那么本部的书库概念不仅需要加上楼层的属性还要加上楼号的属性。

九、   多个属性存在依赖关系,最好选举一个主属性

当一个业务中有多个属性相互之间有关联的时候,最好能够有一个属性为主属性,其他与之有关系的属性应该能够通过主属性计算出来,不要各自为政。

以图书馆管理系统的当前所借图书催还业务为例。每个图书馆管理系统的用户都可以查到自己所借图书的催还状态,每本书外借期限为14天。如果外借时间小于13天,状态为正常,书目颜色为黑色;如果外借时间为14天,那么说明今天应该去还书了,状态为催还,书目颜色为绿色;如果外借天数大于等于14天,状态为延期未还,书目颜色为红色。如果将图书催还的状态设计为数据库中的一个字段的话,那么就必须设计一个定时任务每天刷新这个催还状态字段。如果图书信息中要显示图书的入库时长,还是将其设计为数据库中的一个字段的话,同样需要一个定时任务每天刷新这个字段。如果还有其他字段也涉及这个问题的话那么每天的服务器的定时任务的劳动一定很繁重。所以设计程序的时候只要把主属性设计到数据库中就好了,其他属性通过主属性由程序计算出来即可。催还状态可以通过借入时间计算出来,图书的入库时长可以通过图书的入库时间和当前时间计算得出。


posted @ 2012-08-15 21:59  lts8989  阅读(948)  评论(0编辑  收藏  举报