什么是防御性编程
防御性编程是一种细致、谨慎的编程方法。为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地“保护”自己。我们通过明确地在代码中对设想进行检查,击碎了未记录下来的设想。这是一种努力,防止(或至少是观察)我们的代码以将会展现错误行为的方式被调用。
防御性编程是一种编程习惯,是指预见在什么地方可能会出现问题,然后创建一个环境来测试错误,当预见的问题出现的时候通知你,并执行一个你指定的损害控制动作,如停止程序执行,将用户重指向到一个备份的服务器,或者开启一个你可以用来诊断问题的调试信息。这些防御性编程环境通常的构造方法有:添加声明到代码中,执行按契约进行设计,开发软件防御防火墙,或者简单添加用来验证用户输入的代码。 应用防御性编程技术,你可以侦测到可能被忽略的错误,防止可能会导致灾难性后果的“小毛病”的出现,在时间的运行过程中为你节约大量的调试时间。 比如说,你有一个基于WEB的期货交易系统,你已经建造了一个环境来不断检测应该程序与期货市场的连接。当这个环境侦测到一个连接失败,它会改变程序的执行,以使用被带到一个报告错误的页面,并指导他们可以使用电话交易系统。这种问题是被立即侦测到的,而损害控制的动作确保了你的客户可以有一个候选的方法来完成他们希望的动作。 防御性编程使我们可以尽早发现较小的问题,而不是等到它们发展成大的灾难的时候才发现。你常常可以看到“职业”的开发人员不假思索飞快地编写着代码。他们开发软件的过程可能是这样的: 他们不断地受到那些从未有时间验证的错误的打击。这很难说是现代软件工程的进步,但它却不断地发生着。防御性编程帮助我们从一开始就编写正确的软件,而不再需要经历“编写-尝试-编写-尝试……”的循环过程。在采用了防御性编程之后,开发软件的过程将变成: 当然,防御性编程并不能排除所有的程序错误。但是问题所带来的麻烦将会减少,并易于修改。防御性程序员只是抓住飘落的雪花,而不是被埋葬在错误的雪崩中。 防御性编程是一种防卫方式,而不是一种补救形式。我们可以将其与在错误发生之后再来改正错误的调试比较一下。调试就是如何来找到补救的办法。 对防御性编程的误解 关于防御性编程,有一些常见的误解。防御性编程并不是: 检查错误 如果代码中存在可能出现错误的情况,无论如何你都应该检查这些错误。这并不是防御性编码。它只是一种好的做法,是编写正确代码的一部分。 测试 测试你的代码并不是防御,而只是开发工作的另一个典型部分。测试工作不是防御性的,这项工作可以验证代码现在是正确的,但不能保证代码在经历将来的修改之后不会出错。即便是拥有了世界上最好的测试工具,也还是会有人对代码进行更改,并使代码进入过去未测试的状态。 调试 在调试期间,你可以添加一些防御性代码,不过调试是在程序出错之后进行的。防御性编程首先是“防止”程序出错的措施(或在错误以不可理解的方式出现之前发现它们,不然就需要整夜的调试)。 防御性编程真的值得我们来讨论吗?下面是一些支持和反对的意见: 反对意见 防御性编程消耗了程序员和计算机的资源。 — 它降低了代码的效率;即使是很少的额外代码也需要一些额外的执行时间。对于一个函数或一个类,这也许还不要紧,但是如果一个系统由10万个函数组成,问题就变得严重了。 — 每种防御性的做法都需要一些额外的工作。为什么要做这些工作呢?你需要做的已经够多的了,不是吗?只要确保人们正确地使用你的代码就可以了。如果他们使用的方式不正确,那么任何问题也都是他们自己造成的。 支持意见 反驳很有说服力。 — 防御性编程可以节省大量的调试时间,使你可以去做更有意义的事情。还记得墨菲吗:凡是可能会被错误地使用的代码,一定会被错误地使用。 — 编写可以正确运行、只是速度有些慢的代码,要远远好过大多数时间都正常运行、但是有时候会崩溃的代码(显示器闪烁高亮彩色火花)。 — 我们可以设计一些在版本构建中物理移除的防御性代码,以解决性能问题。总之,我们这里所考虑的大部分防御性措施,并不具有任何明显的开销。 — 防御性编程避免了大量的安全性问题,这在现代软件开发中是一个重大的问题。避免这些问题可以带来很多好处。 由于市场要求软件的开发更加快速和廉价,我们就需要致力于实现这一目标的技术。不要跳过眼前的这些额外工作,它们可以防止将来的痛苦和项目延迟。 防御性编程有助于程序的安全性,可以防范诸如此类恶意的滥用。黑客和病毒制造者常常会利用那些不严谨的代码,以控制某个应用程序,然后实施他们蓄意的破坏计划。这对软件开发的现代世界而言,无疑是个严重的威胁;这个问题涉及到诸如生产效率、金钱和个人隐私等方方面面。 软件滥用者形形色色,从利用程序小缺陷的不守规则的用户,到想尽办法非法进入他人系统的职业黑客。有太多的程序员在不经意间为这些人留下了可随意通过的后门。随着网络化计算机的兴起,粗心大意所带来的后果变得愈来愈显著了。 许多大型软件开发公司终于意识到了这种威胁,开始认真思考这个问题,将时间和资源投入到严谨的防御性编码工作中。事实上,在受到恶意进攻之后才亡羊补牢是很困难的。 |