悲观程序员的五件武器
我不知道,自己现在还算不算一个程序员。如果还算程序员的话,我肯定不是那种绝顶聪明的程序员。
我不是一个聪明的程序员,不能在键盘上手指翻飞,灵光似剑,一日千行,闭目成章。大师的高度,远非我能指望,我会犯很多错误,只是一个普通的程序员。
所以,对于编程,我是一个悲观主义者。
我不相信,所编写的程序能够一次编译通过;也不相信,能在家里将程序的所有错误都找出,而不需要出差现场;更不相信,我的程序能够在不同的环境下,对各种异常,都处理得非常完美;尤不相信,我的程序没有任何内存丢失,可以连续运行一周。
我本来不是一个悲观主义者,曾经的我,是那么激扬那么狂妄,只是一次次被打击,让我越来越务实,越来越冷静,越来越清醒地看待自己。随着岁月的增长,我编程的次数已越来越少,但是,我的悲观主义思想却越来越浓。
一打开程序,我便想到,因为软件出错,而不得不给用户写检讨;便想到,因为每月死机一次,客户对我大发雷霆;便想到,因为产品质量问题,而陪客户喝酒,连饮七大瓶啤酒。
那七瓶要命的啤酒,依然不能让客户回心转意,于是,我成了一个悲观程序员。
我是悲观主义程序员,好在还有五件武器。
第一件武器:断言(ASSERT);
我希望,任何调用我的模块的程序,都能按照希望的参数格式和调用方法,正确地调用我的模块。因此,在我所编写的每一个模块内,都会大量地使用断言(ASSERT),在模块中加上了断言,我便相信,程序模块有了一个一个相对真实的调用环意,便有了一种虚幻的安全感。
第二件武器:静态代码检测工具,如PC-lint,有时也使用编译器的最严格的编译级别;
我从不认为,自己是一个对C/C++/VC等,都非常熟悉的程序员,经常会不小心使用一些不正常的语法,或是不太考虑字段的边界,因此,在程序编到一定的阶段,都会采用pc-lint,对我所编写的程序,进行严格的编译检查。
第三件武器:动态代码检测工具,如boundcheck;
对于C/C++程序员而言,最大的痛苦就是内存泄漏,或其它资源泄漏了,我对内存泄漏有天生的恐惧,也经常在内存丢失方面犯错误,因此,在产品发布给用户前,一定会采用动态代码检测工具,进行一次彻底的测试。
第四件武器:单元测试工具,如cppunit;
我没有足够的自信,认为自己能够很好地驾驭多个模块的大型程序,也不相信自己写过的、超过50行的程序会没有问题,因此,我会尽量引入单元测试,对每一个重要的函数或模块进行地毯式单元测试,当看到那一遍测试通过的绿色,才能够安心地回家睡觉。
第五件武器:调试信息;
我相信,我所编写的所有程序,都不可能一次成功,即便再认真地调试检查,再多地厂内工作,在现场还是免不了会出问题。因为,不可能在家里模拟现场所有的情况,也不能够对各种异常情况进行完整地猜测。因此,在我所编写的很多程序中,特别是与监控有关的、需要长期、连续运行的程序,都会加上尽可能多的调试信息。
在程序中加上调试信息,是我最后的稻草,有了它,我终于敢将产品战战兢兢地交给客户。
那么,调试信息应该记录哪些内容?我想说的是,调试信息应该能够记录现场所有的信息,包括:
程序的启停状态;
调用它人程序的边界参数;
被它人调用的程序的边界参数;
与外部环境的边界,包括操作系统、文件系统、硬件、数据库等;
与网络交互的两端边界;
重要模块的被调用参数;
模块内的重要过程的当前参数;
有了这些调试信息,我便可以不出差了,当现场发生了事情时,我的第一反应便是要求查看这些调试信息。
今天一位朋友问我,你如何保证你的程序能够稳定,我告诉他:我有五件武器。
宝刀配英雄,现在我已很少编写程序了,这些武器,就送给战斗在第一线的程序员吧,也许你们现在不觉得它们有多重要,但总有一天,你们会自觉地将它们带在身边的。