三文鱼海域

Fools learn nothing from wise men, but wise men learn much from fools.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
 

最近做项目时偶然翻到自己前不久写的一段代码,里面有一个给字符串加上换行符的函数,定义大致如下:

 

string StringInsertNewLine(string src, int length)

 

函数功能很简单:每隔i个字符就给s插入一个换行符。主要是用于在表格中显示备注等信息。里面有一个简单的输入参数检查:

 

string StringInsertNewLine(string src, int length)

{

if (length == 0)

{

throw new ArgumentException("length必须大于0");

}

 

if (src == null || src.Length < length)

{

return src;

}

... ...

}

 

对于src是否为null的检查,似乎已经是写程序的一种惯例了,但记得有同事对这种检查和处理方式提出了疑问,他认为这种检查没有什么必要:难道会有人傻到用下面的方式去调用它吗?

 

string s = StringInsertNewLine(null, 10)

抑或是

string s = StringInsertNewLine("Hello kitty", -10)

 

显然,直接用这种方式调用的可能性几乎为0(除非程序员根本没弄清楚这个函数是干什么的)。但是极有可能出现这样的调用情况


string s = StringInsertNewLine(GetString(), GetLength())


我们无法确定
GetString()这个函数是否会在某种情况下返回null(事实上极有可能),也不清楚GetLength()是否会返回一个负数。如果不对参数进行检查,在这种情况下可能导致程序崩溃。

 

这就是“防御式编程”的主题,要对传入参数的险恶性有充分的考虑。关于“防御式编程”的讨论可以参考《程序员修炼之道》和《Code Complete2》,另外还有不少书都重点强调了这一问题。即便如此,在写程序时还是难免偷懒。我们是不是在每个函数中都对参数的有效性作过严密的验证呢?我们是否也都抱过侥幸的心理,对于一些“不可能”的情况轻易放过?虽然我还没有足够的经历来证明这种“懒惰”可能导致的后果,但还应该尽量去避免这样的疏漏。

 

至于在检查出异常的情况下如何处理,这取决于程序的应用。且不谈“契约”之类的理论,就拿上面的例子来说,在srcnull的情况下应该返回null还是抛出异常?把这段代码放在不同的应用中会有不同的结论,如果src是绝对不允许为null的话,抛出异常是一种正确的选择;但在上面的例子中,StringInsertNewLine是用于备注等信息的处理,srcnull是一种常见的也是允许的情况,返回一个null应该没有什么问题。“何时应该抛出异常”也是一个很有争议的主题,在《.net 框架程序设计》中也基于.net平台的特性作了一些讨论。

posted on 2006-08-01 20:38  三文鱼  阅读(343)  评论(0编辑  收藏  举报