养成好的编程习惯
假设有一种编程的方法,能够克服所有的困难和改正所有的错误,而且能够避免重写代码,我相信我们都会使用这种方法。因为没有一种完美的编程方法, 我们能做的事情就只能是看我们周围的程序员是如何做的,哪些是正确的,哪些是错误的。有一些编程的方法是我从实际工作中总结而来的,也确实感到它们能够帮助我养成良好的编程习惯。其中最重要的一件事情就是记住,当你看到这些经验的时候,不要认为他们太简单和基础,觉得一种方法是不值得学习的。很多程序员认为检查错误和写程序注释是浪费时间。而我认为,这些经验能够帮助我们节省时间和精力。在实践过程中,我了解到,我能够更快的编写代码,代码也更加的有效率。
做最坏的打算
假设你是一个超级程序员,你的代码永远都不会有错误。但是,如果你的完美的代码没有得到完美的数据,事情将会如何?你的代码假设一个指针是合法的,或者它会把一个声音文件当作一个图片来处理?基本上来说,一段代码不能假设任何事情。C语言又一个标准的函数 assert, 它能够用来捕获错误。每次你的代码接收到用户数据,请注意要先确认数据是你所预想的。如果不是,使用assert并且打印消息来解释出现了什么错误。这是很重要的,这样你就能够让任何阅读你的程序的人了解到,什么是正确的数据,什么是错误的。百分之九十的错误都是一些简单的错误。所以,不要让这种错误影响你的程序浪费调试人员的时间,而只需要简单的在那些地方给出一个assert, 就能够避免。百分之九十的时候它能够容易的被改正。而另外百分之十的时候,它能够在变成一个大的错误之前被调试人员注意到并且改正。不论你采用哪种编程语言,你编写的第一个程序一般都是打印一条消息。把这个打印消息的功能作为你的程序中一个基本的函数,能够简单的打印任何错误。这样,程序就能分辨不明显的错误,你也能在任何错误可能出现的地方使用这个打印错误消息的函数。这样,就能够节省寻找错误的时间,从而让改正错误的时间减短。
注释
不要企图记住你的代码是用来做什么的。在你编写完一段程序几个月之后,你不会记得在编写程序的时候的想法,也不会记得什么代码是用来干什么的。所以,写注释是一个好的方法,特别是当你需要别人来阅读你的代码,或者是为了你半年之后还能记起来这段代码的目的。如果有一个同事告诉你,你的代码有一个错误,你将不得不重新检查并且改正它。如果你能够通过注释来回忆起什么代码用来做什么,你就能快一点找到并且改正错误。这个方法也是比较简单的,只需要注明你的那一段代码是做什么的,这就够了。而如果你不这么做,其他的阅读你的程序的人将看不懂它的意思,不知道变量是用来做什么的,哪些复杂的计算又是用来做什么的。如果你说明了它们的意义,就简单多了。比如,看这样的代码if "(frmp>10)", "(plist.bdown & x03)", "(plist.y > pond.y)"
就比看注释要复杂的多。当你写注释的时候,你会得到两种好处。
任何人都能明白你希望一段代码去做什么,而且,如果这段代码有错误,阅读代码的人就能发现,它没有执行你在注释中希望它去做的事情,那样就能尽快的发现错误和改正它。注释是程序员最重要的工具之一。而且所有的语言都支持注释。所以,记住,要写注释。
文档
当我在写一个文档的时候,我记得我花了很多篇幅来写一段关于系统和模块的文档。这个文档是正确的,但是却是没有用的。因为,没有人读过它。很多人都忘记了还有这篇文档,而是在需要的时候来问我,让我来解释给他们。
这种方法也不错,它比查阅整个文档快多了。很少有机会有人会花上一大段时间来通读整个文档。所以说,我当时写文档的时间是浪费了。而且,如果这个系统和模块要做什么改动的话,我还必须相应的修改文档。也就是说,这文档让我的劳动加倍了。但是,这并不是说文档是不重要的。相反,如果用源代码和说明来记录文档,就简单多了。在每一个函数的开头,都用一段注释来解释函数的功能,如何使用,需要注意的问题等等。如果是一段比较复杂的代码,需要解释你所采用的方法。没有必要采用另外一个文件来记录文档,而只用在源代码中间来写文档。这样你就能够在你需要文档的时候随时找到它们。其他的程序员也会很方便的使用你的代码。而且,不象一个专门的独立的文档那样,其他的程序员将会无意识的阅读你的文档,而不会置之不理。如果有人来问你关于某一段代码的意思的时候,你就会明白,那一段代码缺少明白的注释。所以,你可以尽快的补上它,而不会有另外一个程序员来问你同样的问题。
采用工具
在编程的工作中,你也许会常常遇到这样一些繁重的体力劳动,比如,编译一个程序,然后就是等待。或者你使用了别人写的API函数,而记住这些函数的名称和参数是一个很累的活儿。这些工作并没有什么技术可言,比如说编译程序,每天晚上都会有人把新增加的程序放到库里,然后第二天上班以后你需要来重新编译它们,往往都是一些重复的工作,但是由于程序很大,编译的过程很漫长,而你就要陷入等待状态。那么,为什么不采用工具呢?或者写一些这样的工具?我就这样做过。我写过一个程序,让它每天早上3点开始,重新编译程序,到了早上8点左右,差不多就编译完成了。然后捕获错误,如果有的话,就发电子邮件给相关的人。这样,到了上班的时间,每个人都能得到一个最新的,编译好的程序。如果代码中有错误,还能最快的得到错误报告。再比如,我需要使用别人写的API函数,当然,我不能指望每个人写的函数都采用同样的命名方法和参数定义方法,也不可能每次需要使用的时候都去查看文档,那样太浪费时间而且效率太低。我写了一个工具,让它来检查我的函数调用是否正确,参数是否正确。如果有错误,则从文档中找到可能的函数,并在错误日志中给予提示。然后我就能很快的编写代码,而不用担心函数拼写,参数调用的类型和顺序了。你也可以这么做,当下次有人来问你某个函数的名称,参数类型,参数顺序的时候,你就能够告诉他,该怎么做,用什么工具了。
可复用的代码
有一个好的比方,用来描述一个引擎。有一个不是程序员的朋友问过我一个问题,什么是程序引擎?有什么作用?为什么要用引擎?我尽量的用通俗的语言回答它,一个程序引擎就像一个汽车的引擎。没有它,汽车不能启动,但是,同时,一个没有轮胎的引擎,也是没有用处的。
我想,这是一个好的例子。这个朋友说,当你的引擎不能用的时候,你可以换一个。如果传动带坏了,你可以换一个新的,同时把引擎的性能调整到最好。同样,一个引擎有相同的部分,比如,传动装置,等等。它们对于一个引擎是重要的,如果某一个部分坏了,你不能不拆开引擎来更换它。
然后我的朋友总结道:如果你从头来写一个程序引擎,你就不得不从头来写所有的传动带,所有的零件。如果你能用一些以前用过的部分,你就能简单的把它们拼装到一起而不用重新写了。
没错。他并不懂得如何去写程序,但是他道出了编程的真谛。这也是一个普通的程序员和一个高级程序员的区别。采用可复用的代码,让工作变得简单。
写通用的代码的关键是,不要让你的子程序变长,不要超过一屏。关键要把你要做的事情分解开,变成小巧的,可以复用的函数,要么完成一个功能,要么调用另外的函数来完成一个完整的功能。
比如,VectorAdd()可能包含了一段代码把两个vectors的元素合并到一起,而SceneDisplay
可能包含了调用PrepRender()
, Render2dObjects()
, RenderHud()
的代码。每一个函数可能都只有几行。
当你把代码分解成小的部分的时候,你将能够集中注意力到一些在其他地方可以复用的功能上。在前一个例子中,RenderHud()和RenderDebugText()可能共享了同样的一段函数调用,因为它们都是在屏幕上描画一些对象。
版权申明
本文可以被自由转载,但是必须遵循如下版权约定:
1、保留本约定,并保留在文章的开头部分。
2、不能任意修改文章内容,或者删节,增加。如果认为本文内容有不当之处需要修改,请与作者联系。
3、不能摘抄本文的内容,必须全文发表或者引用。
4、必须保留作者署名、注明文章出处。(本文授权给www.linuxaid.com.cn)
5、如不遵守本规定,则无权转载本文。
作者
ariesram
电子邮件地址
ariesram@linuxaid.com.cn, 或 ariesram@may10.ca(完)