正文
—–赵岩
先做个广告置入,如果喜欢这篇文章,你可以到
zhaoyan.website/blog
去查看于此类似的C/C++文章。
我承认有点标题党了,不过这真的是一篇写软件的文章,所以如果你已经抽出了一张面巾纸,那么趁早再把它完美的放回去。这篇软件文章很软,源代码不多,而且大部分都是伪代码。所以很适合所有人看。我特别推荐年轻的初学者,把纸巾放回去后,继续看下去。如果把这几个概念理清楚,对未来的工作非常有帮助。
先说失败(failure)。常见的软件的失败主要分为三种,编译失败,运行失败,结果失败。下面通过一个程序的例子来说明:
—————————————
int l1 = 0;
ll= 23; //compile fail
int a[10];
a[10] = l1; //run time fail
if(l1=1){
… // result fail.
}
——————————————
你可以把编译失败理解成世界上最聪明的一堆程序员在帮你审核你的代码。如果审核失败,他们会提醒你在造成严重错误之前修改你的问题。单从这一点看,C++也比一些解释性的语言更加安全。例如源码中你想把变量l1修改一下。但是由于笔误写成了ll。C++的编译器会对你大吼的。但是Python一声也不吭,看你运行时候的笑话。
运行失败是指你已经有了可执行程序,当你运行它的时候,它crash了,挂了,死了,kick the bucket了。一个你最经常看见的输出就是访问越界内存带来的Segmentation Fault。所以请记住:男人头,女人腰,还有越界内存。这三样东西永远不要摸,否则会挂掉。
比起结果失败,你会发现运行失败是多么美好的一件事。上面的if语句是C++中非常著名的一个结果失败的例子。你的程序编译正常,运行正常,就是结果不对。而且你还不知道原因所在。另外一个常见的原因就是C++的数值计算溢出。这在C++中是非常著名的“未定义”。 C++标准委员会乐观的认为如果我“未定义”,那么天才的编译器程序员会发明一种最聪明的方法来解决这个问题。但是实际的情况是:天才的编译器程序员是最懒惰的程序员!如果你“未定义”,那么他们就什么也不干。结果就是到底发生什么,鬼知道!!!
如果你还没看懂,没关系!我再给你举了生活的例子。一个程序员根本就没有女朋友。这个就类似于编译时失败。一个程序员有个女朋友,但是他第一天就去摸人家女孩子的腰。有些地方还真是和尚摸得,你却摸不得,结果女朋友愤然离去,这可以对应运行时错误。最后一种情况当然就是结果错误了。程序员有了一个漂亮的女朋友,第一天他去摸人家的腰,女孩子不仅没有生气,还娇羞的把头靠在程序员的肩旁上,对他说:“讨厌了,你刚才把人家摸怀孕了啦!”
现在的问题就是:如何能尽早的发现女朋友是否环孕?不对,我说错了,我是想说如何能够更早的发现失败?
首先,常见的失败的原因主要有两种,一种是缺陷(bug),另外一种是异常(exception, error)。好多人搞不清楚,所以我上段代码:
———————————
String key = name;
If(key = “Yan”){
handle = openFile(key);
salary = handle.read();
}
———————————
请注意,我说的缺陷就是bug的含义。也就是常说的虫子。缺陷主要有两种,设计缺陷和实现缺陷。上面的代码中,用名字来做为查找键值就是一种明显的设计缺陷。如果你在办公室喊一声“狗蛋”,会有好多同事答应的。另外一种实现缺陷我们上面介绍过,key==“Yan”写成了“key=Yan”。这些都会造成程序的失败。
那么我们如何能尽早的发现bug呢?一个很牛逼的工具就是unit test。不过C++也提供另外一个有力的工具,那就是assert。Assert用法是最简单的。下面我们看看它是如何发现我们的缺陷的。
—————————————
PrintSalary(string name, int salary){
Assert(name == “Yan” && salary<=200,000);
}
————————————-
Assert的基本理念可以应对成一句话:“反常必有妖”。上面这段代码的含义是如果发现Yan赚的钱超过了20万,那程序一定是哪里出现问题了。就像你发现你的名字出现在福布斯富豪榜上了,那富豪榜一定是印错了。你最好复查一下计算薪水的代码。如果你再阅读一下上面计算salary的代码,你就会发现是重名的设计缺陷和if的实现缺陷才让Yan的salary那么多。