最近花了一些时间看了这本书,书名是
《Writing Clean Code ── Microsoft Techniques for Developing Bug-free C Programs》

这里主要总结了一些里面的编程思想。

为空语句加上NULL

当需要使用空语句的时候,最好写上NULL, 比如:
  1. if (music_on())
  2. NULL;
  3. else
  4. turn_it_on();

参数类型相同的问题

如果函数中两个参数的类型相同,如果用户调用这个函数时错误替换了参数的顺序,就会出现问题。

比如
  1. bool are_you_that_guy(int id, int year)
这里如果可以修改其中一个类型的话(比如把int改成short),当写反参数时,编译器会做出警告,进而可以避免这种问题。

代码查错

不要依赖测试人员帮你查出代码中的问题,在写代码的时候要尽量做单元测速,保证每个单元都没有问题,这样做似乎会花费大量精力,而且会拖延进度,但是对于最后是由很大好处的,要知道程序员一般会花大部分时间来解bug,让bug在摇篮中被扼杀是一个好事情。不过对于维护一堆庞大代码的程序员来说就不一样了。

再写代码的时候要善用ASSERT,做好一个DEBUG开关,当release给客户的时候将ASSERT去掉。ASSERT的作用是将真正的错误显露出来(比如向函数传入了一个NULL指针),断言的是真正的用法不当,而不是一般的错误(比如内存分配失败,返回NULL)。

使用lint等工具也可以帮忙分析代码中的问题。(我没用过,后面试试)。实际上使用GCC的Wall开关就可以得到很多warning,进而解除一些问题。

可以写两个不同版本的代码来查错,一个是效率较低的,用于验证的代码,另一个是需要release的代码。

对代码进行逐条跟踪,对于每一种情况进行单元测试,这一点可能很多人做不到。

代码风格

不要让函数既返回结果,又返回错误代码。最具表现性的是

  1. int getchar ( void );
当正确的时候返回一个int。getchar为什么返回int而不是返回char,这让人感到不可思议,实际上int值是为错误的情况准备的,也就是EOF

EOF的定义:
It is a macro definition of type int that expands into a negative integral constant expression (generally, -1).

这里可以认为它是-1.所以这样一来就很容易出问题了。好的做法应该将数据传入到函数的括号中,函数调用正确与否赋给返回值,比如:

  1. int getchar(char *char_val);


不要写稀奇古怪的代码

好的代码应该是具有可维护性的,因为总会有新手来维护你的代码。当你把所有
代码都挤在一行,比如这种类型:

  1. plan = planA ? (planB ? planC : planX) : (planD ? planE : planY)
这样会让人摸不着头脑。应该将它们拆成if和else语句,如果if和else嵌套太深,那么就是自己的设计问题了。
实际上不要用类似名称的变量,比如planA和planB,很容易搞混。


不要随便改别人代码

这个条款看起来不可理喻,有时候也会该出问题,除非你进行了详尽的测试。

比如将 
  1. int identity;
  2. identity = whois(tanhangbo);
  3. TELL(identity );
改成
  1. TELL(whois(tanhangbo))
如果TELL的定义是
  1. #define TELL(x) (x + x*2)
那么whois会被调用两次。



知错能改

当然了,最重要的准则,同一个错误不要犯两遍。



--------------------
需要注意的东西还是很多的,这里只是提到了一部分。
写代码的时候还是要多思考的,如何能写出好代码,容易维护,bug少。这本书还是不错的,推荐看一看。



为知笔记的内容发到博客园还是有点问题,其中代码格式化好之后再发上去,格式就没了。不过能够方便地发上去已经不错了。




05-07 15:08