11 July 2013

近期参加了一次编程比赛,比赛并不是考算法,而是考察我们是否能够按照开发软件的一些重要步骤进行规范的开发。基本过程包括编码——测试——文档。这次比赛让我学到了很多,在此略做总结:

1.数据结构很重要

在《编程人生》中曾看到过很多神牛编程首先都是从数据结构着手,这次比赛有了深刻的体会。一个好的数据结构不仅能节省空间,还能够提高效率。

这次比赛中,我使用了单向链表,而据我了解,很多选手使用了数组。对于数量为100的数据,使用单向链表只需要长度为101的链表(包括头节点),而使用数组可能需要100×100的空间。从空间上来说,链表大大降低了存储空间的开销。而在后续处理上,需要删除数据时,链表操作非常容易,查找时也仅需要遍历一遍链表即可。

2.使用宏

比如我们写一个处理异常的代码,你可能会这么写:

int *p;
if (NULL == (p = (int *) malloc(sizeof(int)))) {
	printf("malloc failed\n");
	exit(1);
}

每当你需要创建新的空间时都需要添加上述4行代码,处理异常很重要,但随着代码行数的增加,这四段代码会随处可见。如果我们想简化这一过程该怎么办,使用子函数?其实使用宏是一个好办法,毕竟宏仅仅在预处理阶段被展开,不会增加编译器的负担。

我们可以写个这样的宏:

#define MALLOC(p) \ 
if (NULL == (p = (int *) malloc(sizeof(int)))) {  \
	printf("malloc failed\n");\
	exit(1);\
 }
int *fp;
MALLOC(fp);

遇到需要创建空间的地方我们只需要调用这个宏即可,四行变成了一行,即简洁明了,又节省了编码时间。这种说法是有根据的,Paul Graham在他的《黑客与画家》说过这么一段话:

代码的数量很重要,因为开发一个程序耗费的时间,主要取决于程序的长度。如果同一个软件,一种语言写出来的代码比另一种语言长三倍,这意味着你开发它耗费的时间也会多三倍。

所以我们还是期望自己的代码少一点吧。

3.变量名

一个好的变量名绝对可以事半功倍,有时比注释都要重要。

在编程过程中,由于需要处理一些数据,我定义了几个变量,但是命名都很模糊,有的很相似,有的容易把理解变量理解错误。也许你会问我为什么不把变量名起的明白一些,其实能起个好的变量名也需要学习,变量名不能太长也不能太短,要让人容易理解变量代表的意思。经过这次比赛,让我对起名这件“小事”有了更深刻的理解,以后一定找几本书专门学习学习。

4.基础和细节

其实这是做好任何事情所必备的。我觉得有机会参加实战是对自己很好的检验,它能够让你知道你哪些地方看似懂了实际上很多都没弄透,这就要在平时多加修炼,打好牢固的基础。所以别去羡慕那些会新技术新名词的人,学习这些本身并没有错,但真正扎实的基础才是最终要的,当你任督二脉都打通了,还怕学东西不快么?

代码中有一段需要读取目标文件的信息并保存在各个变量中,由于我的疏忽,认为只需要读取1位数和两位数而忽略了可能存在的第三位数,而这个细节问题困扰了我很久。所以开始细心的读好题目绝不是浪费时间,因为你节省的时间也许远远少于因为细节没注意到而浪费的时间。

5.测试

对于很多软件,测试代码会占很大的比重。就在这次比赛的测试代码中,我用上了不久前讲过的断言。之所以很多人不会去写测试代码,大多觉得这部分不会出问题,而事实上很多大的问题就出现在当初觉得不会出问题的地方,对于关键的代码写好测试是非常重要的,修改BUG不难,但是寻找BUG非常难,很多问题隐藏在我们看不到的地方,我们需要测试代码来帮我们找到这些问题。

6.文档

文档的作用是对代码或功能提供说明,但是文档到底应该如何写呢?在网上搜索了一阵子并没有一个满意的答复,在此就说下我自己的理解吧。首先,文档可以不用写,如果你代码注释的很清晰,功能介绍的很全面,那基本上就相当于文档,根本不需要浪费时间去写文档。如果你觉得你还需要文档去说明你的程序,那文档一定要保证很清晰,让读者能够读懂。我在文档中的一部分分析了关键算法的代码,写了很长一段,罗列了各种变量的变化,感觉自己站在读者的角度上都很可能看不懂。这说明自己在分析代码的能力上有很大的欠缺,同时也暗示了自己的代码本身也不够清晰易读。


当然还有其他收获,在此不一一列举了。我们需要的是找到问题,解决问题。就如同BUG一样,有些问题你很难发现,这就需要我们不断去实践,在实践中找到问题的所在。希望本文对你有所帮助。



blog comments powered by Disqus