论坛首页 综合技术论坛

关于用异常控制程序流程的看法

浏览 22470 次
精华帖 (3) :: 良好帖 (0) :: 新手帖 (5) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-08-03  
关键看几点:
1.是否code意义已经足够,不需要附带其他内容
2.是否当前函数就知道如何处理,不需要长跳转,即无需抛出,无需知道谁可能会处理
3.是否有强制处理或者强制终结的需要
0 请登录后投票
   发表时间:2011-08-05  
看看Exception的语义:异常,什么叫异常。即不是正常情况。
比如刚才的AddUser(user),如果实现者,应该检查有无重复用户,有则抛出UserExistException。
处理异常基本原则:
1、低级异常转成高级异常
2、如果你不知道如何处理,就不要处理

千万不要用返回值中某个枚举值作为异常的标志,现在基本所有高级语言都有异常机制,就是因为返回值是正常处理结果,无法返回意外信息。

parseInt(Str str),出现异常情况,定义返回0是异常,那不是乱套了。出现异常,意味出现意外情况,程序无法继续执行,一般抛出或转成统一高级异常抛出,由最外层处理提示用户或调用者
0 请登录后投票
   发表时间:2011-08-06  
bloodwolf_china:
哥,你完全没理解我说的内容,还是你根本没仔细看过。
第一,关于操作数据表时,遇到重复记录怎么处理我已经提过,以增加用户为例,以已存在用户名注册应视为正常的业务逻辑进行处理,而数据库连接断开,不能建立连接,等应视为异常。
也许我们对非正常状况的理解不一致。不过作为增加用户这样的用例,出现了重复注册这种情况你应该是知道该怎么处理的,在这种情况下你为什么要抛出异常?只用某个枚举或字符串作为返回值来说明你的处理结果不是更好?
第二如果是java,jdk有把字符串转换成数字的api,试图把非数字字符串转化成数字这种操作本身就会抛出异常,你再用一个状态值说明就是蛋疼。这种情况属于非正常状况,理应用异常处理。
不过这种非正常情况你自己也应该知道该怎么处理,你理应处理。或许你觉的在当前方法处理并不合适,那就该抛出转换时转换方法本身抛出的异常。
如果自己实现这样的转换逻辑,自然也要抛出异常处理,毕竟返回值被用来作为转换结果了,自然只能用异常处理试图转换非数字字符串的这种情况。
0 请登录后投票
   发表时间:2011-08-06  
ppgunjack 写道
关键看几点:
1.是否code意义已经足够,不需要附带其他内容
2.是否当前函数就知道如何处理,不需要长跳转,即无需抛出,无需知道谁可能会处理
3.是否有强制处理或者强制终结的需要


ppgunjack同学,我觉的我们说的内容越来越相近了。
不过个人觉的在有些情况下即使用code意义已经足够也不应该使用code,而是应该判断对于当前业务来说这是正常的业务逻辑还是程序不能处理的非正常状况。
2.当前程序能处理的就不需要抛出,那就可视为正常的业务逻辑
3.总有些时候会出现程序不能处理的非正常状况,而有时候直接抛出也不合适。比如jdk的Runnable.run()不能抛出检查异常,关闭流时会抛出检查异常,而关闭时io操作已经结束这时就需要强制结束,我们只能捕获而不处理它。在run方法内只能捕获并尽量处理,或包装成运行时异常再抛出。

这几种情况并不能一概而论,还是得具体情况具体分析。
不过有时候究竟该抛出还是处理也是不太好选择的时候。

另外下面以java为例说明一些可能出现的情况。
现在的软件都采用分层设计,不同层的代码可能由不同的人实现。
还是以添加用户为例,如果action和service层为例。
假如规范要求action只是调用service方法并根据service的处理结果向表示层返回不同的值或说明
如果service采用异常来表示用户己存在,密码过短等,用户名过长等状况,在action层还需要捕获各种异常并逐一处理,然后向表示层返回不同的结果。
如果service采用状态值表示不同的结果,action就简单的多了可以直接把从service返回的值用为响应表示层的值。

当然还会有更复杂的业务逻辑。
假如果上层接收了下层的返回值后还要做其它处理,比如业务层操作数据库时,数据库发生异常,这个异常就需要抛出,然后在控制层捕获并做处理,这种时候不同正常业务状态或结果和非正常的下层不能处理的状况可能都需要在控制层处理。这种时候如果一律使用状态码或一律使用异常恐怕不太合适。
当然你把用户己存在,用户名过长,密码错误当作一种非正常状况或者把数据库连接错误,文件未找到,字符串转换日期或转换数字出错等等当作正常业务逻辑处理那是你的理解。
这完全取决于各人在设计时的理解不同。
不过我个人还是倾向于把自己能处理的都自己处理了然后给上层调用者交待处理结果,不能处理的才抛出告诉上层自己无能为力。这么做就像你处理领导交给你的任务,在自己能力范围和责任范围内的一定要处理,然后给领导报告一个结果,因为这是正常的处理方式和业务流程;对于自己做不了的或者有僭越的就抛出异常,因为超出了自己能够受理的范围这就是非正常业务状况。
0 请登录后投票
   发表时间:2011-08-07  
楼主比较初级,没理解到异常的意义
0 请登录后投票
   发表时间:2011-08-08  
第二个说我初级。
好吧。你们高级。
你们就说一句初级,别的什么也不说能有什么说服力?
还是你们不屑于说?
我没理解异常的意义,那劳驾请你们把自己对异常的理解说出来吧,肯请不吝赐教。
也让咱进步一下。
啥都不说冒个泡就闪了,我还说你们装*
0 请登录后投票
   发表时间:2011-08-09  
出现上面一大串的讨论,或是LZ没解释清楚应用的场景,或是在座的回答不相应
LZ所说的正常情况应是属于业务处理的一部分,即是需要处理的逻辑
LZ所说的使用code即是上述处理的一部分?
LZ所说的非正常情况正是大家所熟悉的那一些异常,比如类型转换异常等等
0 请登录后投票
   发表时间:2011-08-10  
异常,程序执行出乎了偶们的意料,我们用异常来通知这个意外
这是非正常状态(当然也是一种状态),所以,楼主所说,
引用
至少直到目前为止我还没在开发过程中发现非用异常做流程控制不可的理由。

确实,理论上来讲就是可以。

楼主在后面的讨论回帖也说了
引用
有同学说异常能包含更丰富的信息,这倒是不假,抛出异常能更有效更快速的定位问题和对非正常情况做出简单明了的说明。不过我始终认为异常就是用来指示程序运行的非正常情况的,而不是用来参与程序运行的正常流程的。
比如说登录用户不存在,密码错误,新注册用户名已被注册等是程序运行时的正常业务情况,不应该用异常处理。网络连接断开,数据库连接断了,违反数据约束了,本来应该存在的文件却没找到,本来应该存在的引用却是null,传递了错误的参数类型或错误的参数数量,这是非正常情况应该用异常。不知诸位注意过没有,在jdk里面状态码和异常是都有定义的,难道大家平时只注意到异常,没意识到jdk里面还定义了状态码和标识码?

我是很同意lz这段话的。

个人以为,lz更想表达的是对异常的滥用的反对,是吗?
其实吧,焦点就在于,“你”认为,什么状态是正常的,什么是不正常?
lz显然是认为,我们能考虑到的,就是允许的。比如用户注册时可能产生重名冲突,我们会检查啊,发现重名告诉你一声,你改了不就结了吗。所以这不是一个异常状态,我们能处理。
另外的兄弟伙些,重名啊,那不允许啊,这不违反数据库约束了吗,异常,异常。
其实,我想大家伙都看出来了,我第二个情况表达的不自然,我是比较赞同第一种说法的,但是,我赞同第二种实现。

在业务分析角度,我赞同lz的说法,程序实现成面,咋怎么高效,简洁,怎么来吧。
(lz的团队能自己实现出和数据库媲美的数据维护,那就那么做吧,搞不定的,老老实实靠数据库通知)

所以,我觉得这个不用讨论了吧?一万个人有一万个说法。


=======================================分割一下========================================
下面的就稍微有点离题了

仔细看完楼主的主贴,和后面的讨论回帖,我发现,
从是否异常控制程序流程这个主题,细化出了两个问题:
1.大数据量的前提下,讨论某些字段的约束必要性,lz的态度是,约束索引要谨慎,引用下lz的主帖
引用
我参与过的所有项目,除了long型主键其它字段一律都不添加任何约束。

我认为这取决于项目特点,如果是数据最重要,那么,我建议,数据库约束还是老老实实做,如果数据不是那么重要,或者如果项目组有能力自己做,那就自己应用来维护数据。
(lz举了个朋友自写c++文件操作系统的例子,我也没意见,知道这样做能带来啥,并且接受,那就没问题)
所以这个问题,我转化一下:
不用(少用,尽量少用)数据库约束,改为程序维护数据,给你们带来了什么?丢掉了什么?
引用下lz的回帖
引用
针对如何维护数据一致性的问题再多说一些。在维护数据一致方面,自己尝试实现确实会增加编程难度和程序复杂性,但是降低了数据库压力,数据库只管增删改查就好了,不需要再为数据一致性做出判断,这样会提高数据库执行效率,也会优化数据表的难度。在极端考虑效率的情况下,可以往这方面考虑,尤其在互联网应用。

不推荐自己解决是因为编程难度和代码复杂性,对开发人员的编程功底有很高的要求。所以在数据库压力不大,开发人员水平普遍不够高的情况下,把更多数据一致性工作交给数据库去做,毕竟数据库有成熟的解决方案。

还有我发这篇帖是为了讨论异常控制程序流程的不是为了讨论数据一致性该如何操作的的。侧重点并不在于此。
我整理下,过几天再发一篇有关数据一致性的帖。

lz的项目应该是做过程序维护数据一致性哈,期待lz的新贴。就可以回答偶的问题了

2.那个userDao的add例子,下面是lz的建议
if(!userDao.exist(user)){  
   return userDao.save(user);  
}else{  
   return USER_EXISTED;  
}  
public static final int USER_EXISTED=-1; 

这个其实吧,有点像第一个问题转换后问题的答案之一:
我们改为程序维护数据,就可以这样做了,保证不会重名。

同样,我还是转化下问题:
这样做,楼主你们的项目得到了啥,又失去了啥。(或者就是为了贯彻那个我们考虑到了,能够处理,那就不是异常,这个理念?)
0 请登录后投票
   发表时间:2011-08-11  
kx29126390 写道
httpclient_bd 写道
完全难以接受。

效率根本不是理由,那些需要pool的东西稍稍优化一下, 就够上万次的throw了。

楼主你忽略了接口定义本身的明确的自解释性了。API设计语义很重要,并且Exception机制本身还有继承关系和checked\unchecked区分, 这些不是用error code以及带mask的errorcode能描述和实现的很好的。 枚举, 你会让维护人员生不如死的。

同意你的看法。

+1
0 请登录后投票
   发表时间:2011-08-11  
kaipingk 写道
楼主比较初级,没理解到异常的意义

虽然我也不完全赞同LZ的观点
但是我觉得既然你觉得LZ初级,请发表一下你们的高见或把相关文章URL贴上来
否则没有资本就不要装X
我个人觉得楼主的帖子很有讨论意义
这种帖子不存在对与错的问题
是讨论好与更好的处理问题的方法
我反正是好久没有在JAVAEYE里看到这种不错的帖子了
顶LZ
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics