当前位置: 首页 > 编程驿站 > 程序人生 > 正文

你不可能写出完美的软件

2018-04-23 来源:佚名

下面这段文字来自《程序员修炼之道——从小工到专家》的摘抄。

你不可能写出完美的软件

当每个人都要确实对你不利是,偏执就是一个好主意。

——Woody Allen

那么,给定了这个让人压抑的现实,注重实效的程序员怎样把它转变为有利条件?

……

每个人都知道只有他们自己是地球上的好司机。所有其他的人都等在那里要对他们不利,这些人乱冲停车标志、在车道之间摇来摆去、不作出

转向指示、打电话、看报纸、总而言之就是不符合我们的标准。预示我们防卫性地开车。我们在麻烦发生之前小心谨慎、预判以外之事、从不让自己陷入无 法解救自己的境地。

编码的相似性相当明显。我们不断地与他人代码接合——可能不符合我们的高标准代码——并处理可能有效、也可能无效的输入。所以我们被教导说,要防 卫性地编码。如果有任何疑问,我们就会验证给予我们的所有信息。我们使用断言检测坏数据。我们检查一致性,在数据库的列上施加约束,而且通常对自 己感到相当满意。

但注重实效的程序员会更进一步。他们连自己也不信任。知道没有人能编写完美的代码,包括自己,所以注重实效的程序员针对自己的错误进 行防卫性的编码。

我们将在“按合约设计”中描述第一种防卫措施:客户与供应者必须就权利与责任达成共识。

在“死程序不说谎”中,我们想要确保在找出bug的过程中,不会造成任何破坏。所以我们设法经常检查各种事项,并在程序出问题时终 止程序。

“断言式编程”描述了一种沿途进行检查的轻松方法——编写主动校验你的假定的代码。

与其他任何技术一样,异常如果没有得到适当使用,造成的危害可能比带来的好处更多。我们将在“何时使用异常”中讨论各种相关问题。

随着你的程序变得更为动态,你会发现自己在用系统资源玩杂耍——内存、文件、设备,等等。在“这样配平资源”中,我们将提出一些方 法,确保你不会让其中任何一个球掉落下来。

不完美的系统、荒谬的时间标度、可笑的工具、还有不可能实现的需求——在这样一个世界上,让 我们安全“驾驶”。

按合约设计

没有什么比常识和坦率更让人感到惊讶。

——拉尔夫·沃尔多·爱默生

与计算机系统打交道很困难。与人打交道更困难。但作为一个族类,我们花费在弄清楚人民交往的问题上的时间更长。在过去几千年中我们得出的一些解决 办法也可以应用于编写软件。确保坦率的最佳方案之一就是合约。

合约既规定你的权利与责任,也规定对方的权利与责任。此外,还有关于任何一方没有遵守合约的后果的约定。

或许你有一份雇佣合约,规定了你的工作时数和你必须遵循的行为准则。作为回报,公司付给你薪水和其他津贴。双方都履行其义务,每个人都从中受益。

全世界都——正式地或非正式地——采用这种理念帮助人们交往。我们能否采用同样的概念帮助软件模块进行交互?答案是肯定的。

DBC

……

什么是正确的程序?不多不少,做它声明要做的事情的程序。用文档记载这样的声明,并进行校验,是按合约设计(简称DBC)的核心所在。

在“正交性”中,我们建议编写“羞怯”的代码。这里,强调的重点是在“懒惰”的代码上:对在 开始之前接受的东西要严格,而允诺返回的东西要尽可能少。记住,如果你的合约表明你将接受任何东西,并允诺返回整个世界,那么你就有大量 代码要写了!

……

实现DBC

使用DBC的最大好处也许是它迫使需求与保证的问题走到前台来。在设计时简单地列举输入域的范围是什么、边界是什么、例程允诺交付什么——或者, 更重要的,它不允诺交付什么——是向着编写更好的软件的一次飞跃。不对这些事项作出陈述,你就回到了靠 巧合编程,那是许多项目开始、结束、失败的地方。

……

思考这样的问题:如果DBC如此强大,它为何没有得到更广泛的使用?制定合约困难吗?它是否 会让你思考本来想放在一边的问题?它迫使你思考吗?显然,这是一个危险的工具!

……

死程序不说谎

你是否注意到,有时别人在你自己意识到之前就能觉察到你的事情出了问题。别人的代码页是一样。如果我们的某个程序开始出错,有时库例程会最先抓住 它。一个“迷途的”指针也许已经致使我们用无意义的内容覆写了某个文件句柄……

我们很容易掉进“它不可能发生”这样一种心理状态。我们中的大多数人 编写的代码都不检查文件是否能成功关闭,或者某个跟踪语句是否已经按照我们的预期写出。而如果所有的事情都能入我们所愿,我们很可能就不需 要那么做——这些代码在任何正常的条件下都不会失败。但我们是在防卫性地编程,我们在程序的其他部分中查找破坏堆栈的“淘气指 针”……

所有的错误都能为你提供信息。你可以让自己相信错误不可能发生,并选择忽略它。但与此相反,注重实效的程序员告诉自己,如果有一个错误,就说明非 常、非常糟糕的事情已经发生了。

……

断言式编程

在自责中有一种满足感。当我们责备自己时,会觉得再没人有权责备我们。

——奥斯卡·王尔德:《多里安·格雷的画像》

每一个程序员似乎都必须在其职业生涯的早期记住一段曼特罗(mantra)。它是计算技术的基本原则,是我们学着应用于需求、设计、代码、注释 ——也就是我们所做的每一件事情——的核心信仰。那就是:

这绝不会发生……

“这写代码不会被用上30年,所以用两位数字表示日期没问题。”“这个应用决不会在国外使用,那么为什么要使其国际化?”“count不能为 负。”“这个printf不可能失败”。

我们不要这样自我欺骗,特别是在编码时。

如果它不可能发生,用断言确保它不会发生(If it can't happen, use Assertions to ensure that it won't)

无论何时你发现自己在思考“但那当然不可能发生”,增加代码检查它。……

怎样配平资源

“我把你带进这个世界,”我的父亲会说:“我也可以把你赶出去。那没有我影响。我要再造另一个你。”

——Bill Cosby, Fatherhood

只要在编程,我们都要管理资源:内存、事物、线程、文件、定时器——所有数量有限的事物。大多数时候,资源使用遵循一种可预测的模式:你分配资 源、使用它,然后解除其分配。

但是,对于资源分配和解除分配的处理,许多开发者没有始终如一的机会。所以让我们提出一个简单的提示:

要有始有终(Finish waht 有 start)