代码大全学习-11-防御式编程(Defensive Programming)

概念

防御式编程,顾名思义,就是保护自己不受其他人错误的影响,防御那些意料之外的错误。比如对一个函数来说,即使它被传递了一个错误的数据,它还是可以继续正常工作,哪怕这个错误数据是其它函数的错,好的程序永远不会输出垃圾信息。防御式编程帮助我们更容易发现错误,改正错误,当然,最好是一开始就不要引入错误,也就是可以利用一些方法,规则尽可能减少错误的产生。好了,下面说方法。

方法

首先,要抵御外来的侵略,也就是来自外部的错误的输入。第一步自然是要把错误检查出来,第二步决定怎么办。怎么办取决于程序的需求,是更看重健壮性还是更看重正确性。这两者通常是矛盾的。像消费类产品往往更看重健壮性,有结果总比关机好。所以可以在程序里尽量做点啥来让它能继续运行。比如超限的输入可以改到限制内,或者用前一个正确的输入,或者等后一个正确的输入;返回一个中性的值,或者返回前一个正确的值等等。而对安全性要求高的应用则更看重正确性,宁愿没有结果也不能有错误的结果。这个时候遇到错误可能就写一下log然后直接关机了。

防御式编程里常用的方法有断言(assertion),异常(exception),建立防护栏(barricade),还有一些debug的辅助手段等。

断言

断言用来检查那些应该永远也不会出现的情形。若是一个断言发生,就意味着一个应该永远不会发生的情形发生了,也就是发现了一个bug。断言是用来发现bug的非常有用的方法,只有发现了bug才能去修改,所以可以在可疑的地方都放一个。通常来说,一些先决条件(precondition)和后置条件(postcondition)都是要断言一下的。对于高要求的代码来说,这样还不算完。断言完了,修改好了,最好也要加上错误处理,因为我们不可能找到所有的错误。

说到错误处理,这是程序设计中不可或缺的一部分。我们要决定哪些错误是就地解决,哪些错误是要上报,上报到哪一级,这些级别要划分清楚,如同公司的管理一样,职责权限分明,搞不定没权限就要上报。还有一种方式是集中式错误处理,所有的错误都给到一个全局的错误处理模块,如同在公司里设立了一个专门处理错误的机构,当然,它的触手会伸到公司的每一个角落,所以,要权衡利弊。

异常

异常机制很多程序语言都提供了,也可以算是错误处理的一种方法,处理原则可以参考错误处理。还有些要注意的点比如不要在构造和析构函数里抛出异常;不要破坏抽象层次,把很底层的异常扔到上层;要注意引用的库的异常;不要有空的捕捉块等等。

防护栏

防护栏的功能如同防火墙,事实上它以前就叫防火墙,是后来防火墙这个词被广泛用于网络攻击后才改名的。防护栏的功能就是栏外的数据随便来,过了防护栏里面的数据就都是安全可靠的,如同安检,违禁物品带不过去的。这里重要的一点就是要确定哪些要放在栏外,哪些放在栏内。通常核心代码会放在栏内,而用户输入等会放在栏外。这个概念还可以用到类上,类的公有方法就是一道栏,私有方法被保护在栏内。有了防护栏之后,栏外的数据都需要错误处理,而栏内的只要断言就好了。

辅助手段

debug的一些辅助手段包括不要用发布版来限制开发版,开发版的程序要想办法尽可能多的去主动发现问题,当然,也要做一些准备方便在发布的时候移除这些辅助的代码,比如用预编译宏,用调试桩等。

代码留存

写了这么多防御式的代码后,最后遗留的一个问题就是发布的时候哪些代码可以留下,哪些要移除。几条指导性的方针是检查重要错误的留下,检查小错误的可以不要;导致数据丢失的不要,能让程序“优雅的”退出的留下;记录错误的log要留;用户会看到的错误信息要改的友好。所谓优雅的退出就是发现严重的错误后能记录错误信息,保留重要数据,安全的退出。

防御式编程不是万能药,防御的种种方法都会增加系统的复杂性,而且谁也不能保证防御的代码就不会有bug,所以哪些地方需要防御,做到什么程度都是设计者要考虑的问题。还记得吗,最好的防御是从一开始就不要引入错误。

同样,最后附上Checklist:

Checklist: Defensive Programming

General

  • Does the routine protect itself from bad input data? 
  • Have you used assertions to document assumptions, including preconditions and postconditions? 
  • Have assertions been used only to document conditions that should never occur? 
  • Does the architecture or high-level design specify a specific set of error handling techniques? 
  • Does the architecture or high-level design specify whether error handling should favor robustness or correctness? 
  • Have barricades been created to contain the damaging effect of errors and reduce the amount of code that has to be concerned about error processing? 
  • Have debugging aids been used in the code? 
  • Has information hiding been used to contain the effects of changes so that they won't affect code outside the routine or class that is changed? 
  • Have debugging aids been installed in such a way that they can be activated or deactivated without a great deal of fuss? 
  • Is the amount of defensive programming code appropriate--neither too much nor too little? 
  • Have you used offensive programming techniques to make errors difficult to overlook during development? 

 Exceptions

  • Has your project defined a standardized approach to exception handling? 
  • Have you considered alternatives to using an exception? 
  • Is the error handled locally rather than throwing a non-local exception if possible? 
  • Does the code avoid throwing exceptions in constructors and destructors? 
  • Are all exceptions at the appropriate levels of abstraction for the routines that throw them? 
  • Does each exception include all relevant exception background information? 
  • Is the code free of empty catch blocks? (Or if an empty catch block truly is appropriate, is it documented?) 

 Security Issues

  • Does the code that checks for bad input data check for attempted buffer overflows, SQL injection, html injection, integer overflows, and other malicious inputs? 
  • Are all error-return codes checked? 
  • Are all exceptions caught? 
  • Do error messages avoid providing information that would help an attacker break into the system?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值