一、前言

首先要知道为什么要有代码规范呢?线代软件产业经过几十年的发展,一个软件由一个人完成已经很少见了,软件都是在相互合作中完成的。那么合作就意味着你需要“看同伴代码”,并发表意见看法。
试想如果你的队友接手到这样的代码,有何感想?

#include<stdio.h>
int v, i, j, k, l, s, a[99]; 
int main() {       for(scanf("%d",&s); *a-s; v=a[j*=v]-a[i], k=i<s, j+=       (v=j<s&&(!k&&!!printf(2+"\n\n%c"-(!l<<!j)," #Q"[l^v?(       l^j)&1:2])&&++l||a[j]<s&&v&&v-i+j&&v+i-j&&v+i-j))&&!(       l%=s),v||(i==j?a[i+=k]=0:++a[i])>=s*k&&++a[--i])                   ; }

这是每年一次的国际模糊C代码大赛于1991年的“最佳小程序”,这个程序的功能是打印出八皇后问题的全部解决方案。我想一个正常人都会觉得这样的代码是不可读的。然而当你的同伴写出类似如此的代码,那么你只能带把40米的大砍刀了吧!
虽然计算机只关心编译生成的代码你的程序采用什么缩进风格,变量名有无统一等等与执行无关。但是在一个团队里面,代码规范却十分重要,甚至影响项目的成败。

代码规范分为两个部分:
1.代码风格规范
2.代码设计规范


二、代码风格规范

代码风格规范原则:简明易读,无二义性
源文件结构

一个源文件包含(按顺序地):
1、package语句
2、import语句
3、一个顶级类(只有一个)

1、package语句不换行(即package语句写在一行里)

2、 import不要使用通配符
即,不要出现类似这样的import语句:import java.util.*;

不要换行
import语句不换行,列限制(4.4节)并不适用于import语句。(每个import语句独立成行)

顺序和间距
import语句可分为以下几组,按照这个顺序,每组由一个空行分隔:

所有的静态导入独立成组
com.google imports(仅当这个源文件是在com.google包下)
第三方的包。每个顶级包为一组,字典序。例如:android, com, junit, org, sun
java imports
javax imports

3、 只有一个顶级类声明
每个顶级类都在一个与它同名的源文件中(当然,还包含.java后缀)。
例外:package-info.java,该文件中可没有package-info类。

缩进:我们不采用Tab键,而是手动输入4个空格。

虽然Tab键一般为4个空格键,但在很多的编辑器中都可以拓展Tab键为多个空格键。不采用Tab键理由是不同情况可能显示不同的长度,严重影响阅读体验。

行宽:限定为100个字符
以前一些规定的行宽为80个字符太小了,但也不宜过长,影响阅读质量,因此确定为100字符

括号:在复杂的表达式中,用括号清楚地表示逻辑优先级
使读者能够快速、清楚看出表达式的运算顺序

断行与空白行{}

if(condition) IsFool();
else IsNotFool();

有人喜欢以上的风格,因为这样可以省去几行,似乎显得代码很精简,看似很高效。但是非常不利于程序的调试,难以有效观察程序变量的值。因此需要断行。于是得到以下代码:

if(condition){ 
	IsFool();
}
else {
	IsNotFool();
}

这个改进确实不错,也很清晰美观。但是还不够,这样的程序在多层嵌套时就显得很无力,难以找到结构的对应关系。于是得到以下的程序:

if(condition)
{ 
	IsFool();
}
else 
{
	IsNotFool();
}

这样的排版不仅美观,而且清晰,很容易找到结构的对应关系。所以我们确定为这样的模式:每个“{”“}”各占一行。

分行:多条语句不要放在同一行,如下:

a=b;b=c;
if(a == b) printf("%d\n",c); 

命名:首要原则--见名知意。普通变量采用Camel法,并采用名词或者组合名词来命名。而类型、类、函数名采用Pascal法,并采用动词或者动宾的方式命名。宏则全部采用大写字母,采用名词或者组合名词来命名,多个词之间用下划线连接。例子如下:

变量(variables)采用Camel命名法。类中控件名称必须与xml布局id保持一致。用统一的量词通过在结尾处放置一个量词,就可创建更加统一的变量,它们更容易理解,也更容易搜索。例如,请使用strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。
量词列表 量词后缀说明
First 一组变量中的第一个
Last 一组变量中的最后一个
Next 一组变量中的下一个变量
Prev 一组变量中的上一个
Cur 一组变量中的当前变量
包(packages): 采用反域名命名规则,全部使用小写字母。一级包名为com,二级包名为xx(可以是公司或则个人的随便),三级包名根据应用进行命名,四级包名为模块名或层级名
包名 此包中包含
com.xx.应用名称缩写.activities 页面用到的Activity(activities层级名用户界面层)
com.xx.应用名称缩写.base 页面中每个Activity类共享的可以写成一个i额BaseActivity类 (基础共享的类)
com.xx.应用名称缩写.adapter } 页面用到的Adapter类 (适配器的类)
com.xx.应用名称缩写.tools 此包中包含:公共工具方法类(tools模块名)
com.xx.应用名称缩写.bean(或则 com.xx.应用名称缩写.unity ) 此包中包含:元素类
com.xx.应用名称缩写.db 数据库操作类
com.xx.应用名称缩写.view(或则 com.xx.应用名称缩写.ui ) 自定义的View类等
com.xx.应用名称缩写.service Service服务
com.xx.应用名称缩写.broadcast Broadcast服务
类(classes):名词,采用Pascal命名法,尽量避免缩写,除非该缩写是众所周知的,  比如HTML,URL,如果类名称中包含单词缩写,则单词缩写的每个字母均应大写。
描述 例如
activity 类 Aty或者Activity为后缀标识 欢迎页面类WelcomeAty.或者WelcomeActivity
Adapter类 Adp或者Adapte 为后缀标识 新闻详情适配器NewtDetailAdp或则直接 NewDetailAdapter
解析类 Hlr为后缀标识 首页解析类HomePosterHlr
公共方法类 Tools或Manager为后缀标识 线程池管理:ThreadPoolManager 日志工具类:LogTools
数据库类 以DBHelper后缀标识 新闻数据库:NewDBHelper
Service类 以Service为后缀标识 时间服务TimeService
BroadcastReceive类 以Broadcast为后缀标识 时间通知TimeBroadcast
ContentProvider 以Provider为后缀标识
直接写的共享基础类 以Base开头 BaseActivity,BaseFragment
layout中的id命名
命名模式为:view缩写_模块名称_view的逻辑名称
控件 缩写
LayoutView lv
RelativeView rv
TextView tv
Button btn
ImageButton imgBtn
ImageView mgView 或则 iv
CheckBox chk
RadioButton rdoBtn
analogClock anaClk
DigtalClock dgtClk
DatePicker dtPk
EditText edtTxt
TimePicker tmPk
toggleButton tglBtn
ProgressBar proBar
SeekBar skBar
AutoCompleteTextView autoTxt
ZoomControls zmCtl
VideoView vdoVi
WdbView webVi
RantingBar ratBar
Tab tab
Spinner spn
Chronometer cmt
ScollView sclVi
TextSwitch txtSwt
ImageSwitch imgSwt
listView lVi 或则lv
ExpandableList epdLt
MapView mapVi

注释:说明程序做什么,为什么这么做。但是不说明怎么做,因为程序本身就可以说明。尽量采用ASCII码字符,不采用中文或者其他字符,否则会极大影响程序的可移植性。
1、短注释采用 //
2、较长注释用 /* */

错误示例:
	int sum = 0;
	//i从0开始到9,循环10次,sum依次与i相加
	for(int i = 0;i < 10;i++)
		sum += i;
不应该采用中文,并且注释没有必要说明如何做,程序可以说明

正确示例:
int sum = 0;
	//calculate the sum from 0 to 9
	for(int i = 0;i < 10;i++)
		sum += i;

复杂的注释应当放在函数头,很多函数头的注释用来说明参数的类型等。
程序注释必须正确,否则必没有注释更糟
注释不宜过长


三、代码设计规范

代码设计规范不仅是程序书写的格式问题,而且牵扯到程序设计、模块之间的关系,设计模式等等。因为我们设计出的程序可能将被许多人使用,并且需要不断调试程序,因此遵循以下规范是正确的选择。

函数:程序的功能绝大部分都由函数来完成。关于函数,最重要的原则就是“只做一件事,并且做好”。

错误处理:可能大家觉得主要功能设计完成之后,只需要花很少的一部分时间来给代码加上一些错误处理。而事实上则是相反的,错误处理往往要花上整个项目80%的时间。
参数处理:在debug版本,所有参数都要验证其正确性。正式版本,从外部传递来的参数要验证其正确性

断言:当你很确切某事会发生时,那么就可以断言!如下:

……
assert(p == NULL)
……

当你不确定某事是否发生时就需要修改相应的代码,如下:

……
p = AllocateNewSpace();    //could fail
if(p == NULL)
……
posted on 2016-10-28 00:00  火尘降  阅读(234)  评论(4编辑  收藏  举报