函数设计之美--函数需要返回错误码吗(一)?

博客围绕从整数集合返回最大数的函数签名设计展开。探讨了两种签名形式,指出第二种签名在处理空集合时会使调用方丢失错误根源。提出不要让错误传播,应在发源地解决的设计原则,还提及考虑在.NET平台实现契约设施Dbc.net。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很久以前我就考虑这样一个问题:有这样一个函数,它的功能是从一个整数集合中返回最大的那个数,如何设计这个函数的签名了?

当时没有得出令自己满意的答案,所以就搁浅了。今天重新思考,终于有所悟!现在把我思索的整个过程展现于此。

最直观的函数签名设计如下:

intGetMaxElement(ArrayListeleList);

乍看之下,很好,很直接的反应了意图。稍微深入一点就发现,如果eleList为null或者其中元素个数为0,GetMaxElement返回什么了?第一反应,修改签名为下面的形式:

boolGetMaxElement(ArrayListeleList,outintresult);

我问了很多程序员,几乎都是这样处理的。我觉得这样设计函数很别扭,我喜欢直观简单的解决方案,无疑我最喜欢第一种签名形式,它很好的反应的函数的意图。而第二种了,它的设计不够好,除了不够直观外,还有什么更重要的缺陷?今天我知道了答案。

首先,我们想想看,当eleList为null或者其中元素个数为0时,GetMaxElement知道怎么处理这件事吗?当然,不知道!因为在此函数中所有相关的上下文已经丢失了,那么谁知道处理的方法了?对,是调用GetMaxElement的调用方。调用方在调用GetMaxElement之前就应该检查eleList 是否满足条件。那么,这个条件是在哪里定义的了,目前的解决方案是在GetMaxElement函数说明文档中。

调用方这么做:

ArrayListeleList=

if((eleList==null)||(eleList.Count==0))
{
//处理错误
}


intmax=GetMaxElement(eleList);

由于调用方知道怎么处理eleList为空和个数为0的错误的上下文,所以它很容易解决这个问题。如果采用第二种签名,有何缺陷了?在第二种签名情况下,调用方通常这么做:

ArrayListeleList=

intmax=0;
boolsucceed=GetMaxElement(eleList,outmax);

if(!succeed)
{
//唉,我也不知道怎么处理了
}

到if(!succeed)语句时,调用方已经不知道GetMaxElement返回的错误是不是由eleList为空和个数为0引发的,错误的根源丢失了,所以调用方对返回的false真是爱莫能助、唯有叹息了!

到这里,我个设计原则:

不要让错误传播(出现),在错误出现的发源地(萌芽期)就解决它!错误越是传播到最后,关于处理它的上下文就丢失得越多,对于错误的蔓延就越是爱莫能助!

为GetMaxElement方法加上注释后是这个样子:

//调用此函数前请确保eleList不为null,且其中元素个数大于0
intGetMaxElement(ArrayListeleList);

这实际上是限制了一个前置条件,关于前置条件和后置条件的更多资料可参考“契约式设计”!将到这里,我考虑在.NET平台上实现一个契约设施Dbc.net,该设施将在运行时自动检测前置条件、后置条件等。很有可能像下面的样子:

[PreCondition(eleList!=null)]
[PreCondition(eleList.Count
>0)]
intGetMaxElement(ArrayListeleList);

晚了,就先到这里吧!对于实现Dbc.net有什么好的建议,欢迎和我讨论?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值