Board logo

Subject: 如何让代码的可读性更高 [Print This Page]

Author: bahamut8348    Time: 2008-3-21 19:57     Subject: 如何让代码的可读性更高

今天晚上失眠了,写点什么吧!呵^_^
    关于代码规范的文章,网上真的有太多太多。我只是想写点我自己的看法而已,当然不一定正确:
    在网上有许多可以下载源程序的网站,不管是C++的还是DELPHI的,又或者是JAVA的。当然,我的硬盘里也有许多在网上DOWN下来的源程序,在这里先要感谢一下各位的开源精神。但是有非常多的源程序的书写格式是非常糟糕的,有种让人看了头晕目眩的感觉。
    如何让自己的代码看上去更漂亮呢?其实,我认为做好几点就可以了:

  一、规范书写习惯;
    至于书写格式的规范,到现在为止应该都没有一个统一的标准;其实,你根本不需要去理会什么标准,只要在一个工程里,书写风格统一就很好了;但是首先要注意代码行的缩进;也就是不要所有的代码都顶头。例如:
if xxx then
a:=0;
    像这种书写习惯是非常不好的,我们想象一下,如果一个项目中有上万行代码,而你所有的代码完全没有缩进的话,你该怎么去管理这些源程序呢?
if xxx then
  a:= 0;
    这样最少应该比上边的好看多了;在DELPHI里,一般一次缩进是2空格,当然这只是一个约定而已,你也可以想C中缩4空格也是可以的,但是最好缩进位置不要太大,否则的话也是非常难看的。

  二、选择合适的语句块:
    我们看一个例子:
if Value = 1 then
  ...
else if Value = 2 then
  ...
else if Value = 3 then
  ...
...
    我们看到,这个IF……ELSE语句有多个判断,这样的话我们完全可以选择一个多分支语句来替代这个IF语句:
case Value of
  1: ...
  2: ...
  3: ...
  ....
end;
    这样的话,我想在感觉上要好很多了。还有,我不推荐使用With语句,当With语句多的时候是会破坏代码的可读性的。

  三、尽量减少单个语句块或子程序中的代码数量:
    当一个语句块或者一个子程序(函数)中,代码行书超过10行的话,这个时候如果一直往里面添加代码的话,到后期维护的时候是相当难懂的,我们可以另外创建几个单独的子程序来替代其中目标相同的一些代码,比如:
  FValue:= 0;
  FAName:= '';
  ...
    像这些初始化变量的语句,我们完全可以定义一个单独的子程序来完成,而避免在一个子程序或语句块中的代码过长。

  四、尽量使用有意义的单词来做变量名:
    首先,用拼音来做变量名是非常不好的习惯,因为在汉字中同音字实在太多了,而且又分音调,像ck这种变量名估计当时记得,到第二天应该就没什么人还记得他到底是什么东西了。还有,我非常不喜欢“匈牙利”命名法,因为当改了一个变量的类型后,变量标识符本身也要修改,这样经常需要浪费许多时间来修改几个变量。当然也最好不要出现这种: a,b单字母的变量名(当然如果作为无意义的循环变量的话,个人认为倒无所谓)

  五、应该控制一行最多只有一条语句:
    有很多朋友,当语句简短的话,喜欢把几条简短的语句并列写在同一行,这样是不好的习惯,因为没有人很保证代码从一写完就不需要修改的,那么像下面的语句:
begin i:= 0; j:= 0; k:= 0; end;
    如果这种语句藏在大量的代码中的时候往往不容易被发现,那么也就存在隐患。

  六、适当的写一些注释:
    一段代码完全没有注释的话,在过了一段时间后,估计连作者看了都会有点困难了,毕竟有的时候代码是写给别人看的(PS:这点我做的非常不好,还需要加强啊-_-),应该在适当的地方加上简短的注释以便提高代码的可读性。至少,每个自定义子程序应该有一个简短的说明文字;例如:
函数名:。。。
功能:。。。
参数:。。。
返回值:。。。
    尤其是返回值的说明最重要,因为你需要明确的知道在调用函数后,函数返回什么表示成功。
    我还想说一下,建议大家尽量把子程序定义成函数,而不是过程,呵。

  七、不要使用全程变量(类以外的那种):
    尽可能的不使用全程变量,如果子程序间需要共享变量的话,我们完全可以用变参的形式来替代。


  八、尽可能的使一个语句更简短
    在DELPHI的IDE里,我们可以注意到,在代码编辑框的右边有一条竖线,我们应该尽量控制代码不要超过到那条线的右边,如果一个表达式过长,我们可以采用利用临时变量的形式减少单句代码的长度,这样虽然会稍微影响一点执行效率,但是却可以在很大程度上提高代码的可读性。
    这其实和我们在看网页一样,我想大多数的人都非常讨厌看那种需要拉横向滚动条才能完全浏览的页面吧


    另外,我还想说一下,在看VCL的代码会有下面的写法:
  if xxx then
  begin
  end
  else
  begin
  end;
    个人认为,begin...end也缩进更好,因为那样可以更突出if和else的对应关系。还有,最好不要写成:
if xxx then begin
end;
这样,如果这样的话,当IF条件过长的话,往往会很难发现与END对应的BEGIN的正确位置。

    最后还要说几条(呵,不要说我罗嗦啊):
  1:尽量少用小括号(),当小括号过多的时候不仅会使代码看上去更乱,而且会影响执行效率的(虽然不明显);
  2:Copy(s, Pos('.', s), Length(s) - Pos('.', s) + 1);这样不好,这样不仅会多运算几次而且也难看,可以写成 Copy(s, Pos('.', s), MaxInt); 这样既易读,又节省了几次运算的时间
  3:i:= i + ...;这样完全可以写成Inc(i, ...); 等同于C里的i+=...;

    写着写着想睡了,各位,先到这里,晚安!^_^

[ 本帖最后由 bahamut8348 于 2008-3-21 20:01 编辑 ]
Author: Passion    Time: 2008-3-21 22:29

小括号如果能增加可读性,还是推荐写的。
要不然自己记不住诸多运算符的优先级,尤其是C里头。
Author: bahamut8348    Time: 2008-3-21 23:24

我这里说的是这种:
if ((Pack[n].ObjectVersion = 0) and (TPacketHeader(Pack[n]).Flags = 2)) and ((NewRM.HeaderMDPR[Map[ i ].Dest].MIMEType = 'audio/x-pn-realaudio') and ( (Pack[n].Timestamp - Map[ i ].Time >= 1857) or (Map[ i ].Time = $FFFFFFFF) ) or (NewRM.HeaderMDPR[Map[ i ].Dest].MIMEType = 'video/x-pn-realvideo') and ( (Pack[n].Timestamp - Map[ i ].Time >= 83) or (Map[ i ].Time = $FFFFFFFF) )) then

其实像这种判断就可以用一个变量来提高可读性了(虽然多次赋值会浪费一些效率,但是我认为还是值得的)

[ 本帖最后由 bahamut8348 于 2008-3-21 23:27 编辑 ]
Author: jacksonhe702    Time: 2008-4-1 19:16

begin...end我还是喜欢这样用

if xxx then
begin
  ...
end else
begin
  ...
end

呵呵,个人感觉这样子写很清晰..




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0