函数设计之美--函数需要返回错误码吗(一)?-阿里云开发者社区

开发者社区> zhuweisky> 正文

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

简介: 很久以前我就考虑这样一个问题:有这样一个函数,它的功能是从一个整数集合中返回最大的那个数,如何设计这个函数的签名了?当时没有得出令自己满意的答案,所以就搁浅了。今天重新思考,终于有所悟!现在把我思索的整个过程展现于此。
+关注继续查看

很久以前我就考虑这样一个问题:有这样一个函数,它的功能是从一个整数集合中返回最大的那个数,如何设计这个函数的签名了?当时没有得出令自己满意的答案,所以就搁浅了。今天重新思考,终于有所悟!现在把我思索的整个过程展现于此。
最直观的函数签名设计如下:

int GetMaxElement(ArrayList eleList) ;

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

bool GetMaxElement(ArrayList eleList ,out int result) ;

        我问了很多程序员,几乎都是这样处理的。我觉得这样设计函数很别扭,我喜欢直观简单的解决方案,无疑我最喜欢第一种签名形式,它很好的反应的函数的意图。而第二种了,它的设计不够好,除了不够直观外,还有什么更重要的缺陷?今天我知道了答案。
        首先,我们想想看,当eleList为null或者其中元素个数为0时,GetMaxElement知道怎么处理这件事吗?当然,不知道!因为在此函数中所有相关的上下文已经丢失了,那么谁知道处理的方法了?对,是调用GetMaxElement的调用方。调用方在调用GetMaxElement之前就应该检查eleList 是否满足条件。那么,这个条件是在哪里定义的了,目前的解决方案是在GetMaxElement函数说明文档中。

调用方这么做:

ArrayList eleList = 

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


int max = GetMaxElement(eleList) ;

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

ArrayList eleList = 

int max = 0 ;
bool succeed = GetMaxElement(eleList , out max) ;

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

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

到这里,我总结了一个设计原则:
       不要让错误传播,在错误出现的发源地(萌芽期)就解决它!错误越是传播到最后,关于处理它的上下文就丢失得越多,对于错误的蔓延就越是爱莫能助!

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

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

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

[PreCondition(eleList != null)]
[PreCondition(eleList.Count 
> 0)]
int GetMaxElement(ArrayList eleList) ;

对于实现Dbc.net有什么好的建议,欢迎和我讨论。我已经在博客园申请了Dbc.net的专栏http://www.cnblogs.com/DbcNet,欢迎你的加入!

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
函数设计之美--函数需要返回错误码吗(一)?
很久以前我就考虑这样一个问题:有这样一个函数,它的功能是从一个整数集合中返回最大的那个数,如何设计这个函数的签名了?当时没有得出令自己满意的答案,所以就搁浅了。今天重新思考,终于有所悟!现在把我思索的整个过程展现于此。
613 0
嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误
  嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误 2015-05-27 14:19 184人阅读 评论(0) 收藏 举报  分类:   嵌入式(928)  一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的。
926 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
8920 0
find_if 仿函数错误:cannot convert 'this' pointer from 'const CActTaskData' to 'CActTaskData &'
今天编写find_if的仿函数时编译报错,cannot convert 'this' pointer from 'const CActTaskData' to 'CActTaskData &'。        struct act_task_finder { public: act_task_finder(const OBJID objId) : m_ObjId
788 0
创建、修改门店接口常见错误返回
1、Q:创建店铺场景下营业执照主体信息不一致        A:营业执照的名称和支付宝实名认证名称不一样,确保一致,需要上传授权涵。  2、Q:支付接口如果store_id和alipay_store_id都传了,支付宝会验证这两个参数的合法性吗?        A:均会进行检测两者是否匹配。
427 0
OpenJPA错误之一 This configuration disallows runtime optimization
参照http://blog.csdn.net/rcom10002/article/details/6568809,一运行就报错Exception in thread "main" org.
1083 0
+关注
zhuweisky
从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
300
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《Nacos架构&原理》
立即下载
《看见新力量:二》电子书
立即下载
云上自动化运维(CloudOps)白皮书
立即下载