论坛首页 Java企业应用论坛

嵌套异常处理逻辑的问题!

浏览 15679 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-09-23  
老庄得说法。
我回去改一改阿!
这里确实应该是设计出了问题。
0 请登录后投票
   发表时间:2004-09-23  
gigix 写道
firebody 写道
to gigix
既然你处理不了这个异常,就让它抛出去,让它导致事务回滚,不就回到业务没有开始的状态了吗?
什么是开始得状态?
比如说:我的交易已经发到银行,银行也处理了我的交易。
那么,我更改流水表也可能抛出异常吧。但是交易流程实际上已经不能回滚了,因为银行方已经做了交易。
这个异常不处理得话,等于客户损失了一笔钱哦。


两阶段提交是干什么用的呢?

这里没有两段提交的说法。
0 请登录后投票
   发表时间:2004-09-23  
firebody 写道
这里没有两段提交的说法。


用不用两阶段提交,只是一个基础设施的问题,你应该可以声明性地配置它。你唯一需要了解的就是,如果一切操作成功,就提交事务;如果操作有异常抛出,就回滚,系统将回到业务开始前的状态。我看你的业务并不涉及长事务,实现这样的声明性事务并没有技术上的困难吧。
0 请登录后投票
   发表时间:2004-09-23  
谢谢老庄提供的Command的思路,想想以前跟他争论接口的问题,现在看看我的水平,我都很惭愧啦。
下面是我们再MSN上交谈部分:(贴出来,只是想给好的思路而已,我就很笨,没想到这个。)
引用
可以讨论一下我的问题吗?我是firebody
庄表伟 说:
呵呵,这下总算挂上钩了
宇翔 说:
我想了一下你提供的思路。感觉对我的交易处理的逻辑帮助不是很大,因为交易逻辑处理是多阶段的,每一个阶段都可能抛出异常,而每一个异常的处理都是不同的。如果抽取接口的话,工作量和设计思路没什么突破。只不过重构把原本long method代码缩小而已罢了。
庄表伟 说:
我的思路是这样的,每个处理,无论是处理一个事务,还是处理一个异常,都可以抽象成一个Commnad模式。然后任何处理,都可能抛出异常,这个异常又需要某个特定的处理。
庄表伟 说:
你在定义的时候,只需要定义每个处理,以及这个处理可能抛出的异常种类
宇翔 说:
哦,我懂了,你的意思是说精确定义异常种类,根据异常种类,hook command的执行
庄表伟 说:
然后在具体的事务开始时,只要将这个初始的事务传递给那个递归函数,就可以了。
庄表伟 说:
原来你是层层嵌套的关系,现在就铺平了,变成一个一个的“一对多”关系。
宇翔 说:
我懂了,555!好想拥抱你一下!老大。谢谢
庄表伟 说:

庄表伟 说:
什么时候到上海来的时候,请我吃饭吧。
宇翔 说:
好的,请你吃大闸蟹
0 请登录后投票
   发表时间:2004-09-23  
gigix 写道
firebody 写道
这里没有两段提交的说法。


用不用两阶段提交,只是一个基础设施的问题,你应该可以声明性地配置它。你唯一需要了解的就是,如果一切操作成功,就提交事务;如果操作有异常抛出,就回滚,系统将回到业务开始前的状态。我看你的业务并不涉及长事务,实现这样的声明性事务并没有技术上的困难吧。

谢谢您的帮助。
其实我的系统,并不直接参与交易,只是一个中转接口而已。事务以及交易的进行并不由得我来控制,我所负责的仅仅是监控报文的转发以及本地发起冲正的逻辑判断而已,那么由我来回滚事务也不是我的责任,就像您所说的一样,流水表并不是很重要,我所关注的是我负责多方转发通讯(多阶段逻辑)的完整逻辑以及中间错误引起的待冲正。
0 请登录后投票
   发表时间:2004-09-24  
我有些想法,不知道可行不。

之所以原本干净的代码现在显得很杂乱、臃肿,有个原因就是你的代码承担了两个角色的任务:处理业务和处理异常。如果把这两个角色分离开来,也许代码就会清爽许多。分开以后的形式可能是下面这样的:
try {
    // 事务对象监视业务对象的执行
    Transaction.monitor(Business);;
}catch(Exception); {
   // 异常管理器负责处理异常,如果发现异常不能处理,则回滚事务
    if( !ExceptionManager.handle(Exception); ); {
        Transaction.rollback();;
    }
}

这里,异常处理器 ExceptionManager 需要注意一些问题:
1。处理异常的时候又发生异常;
   对这个问题,我觉得异常处理器最多处理自己的异常,不能再生成一个异常管理器,然后把自己的异常再传递下去。因为异常管理器本身的处理操作和重新抛出操作会形成一个比较简单的单一线索的异常处理链,如果还要把自己的异常传递给其他异常处理器会导致复杂的处理过程,而太复杂了会增加不稳定性,不值得。
2。处理异常所需的资源出现不足或故障;
   比如这里,处理异常的时候发现数据库本身出了问题,也就是处理异常所需的资源出了问题,不能正常处理业务异常。那么需要对异常处理资源有个预测,比如数据库保存错误报告不行,就写日志,写日志时判断文件系统空间够不够,如果不够,显然写日志也行不通。对于这种问题的处理,可以有个程序间歇性的探测文件系统的容量,如果达到预警值就用某种方式报告给相关的处理人员解决这个后顾之忧。
0 请登录后投票
   发表时间:2004-09-24  
youngS 写道
我有些想法,不知道可行不。

之所以原本干净的代码现在显得很杂乱、臃肿,有个原因就是你的代码承担了两个角色的任务:处理业务和处理异常。如果把这两个角色分离开来,也许代码就会清爽许多。分开以后的形式可能是下面这样的:
try {
    // 事务对象监视业务对象的执行
    Transaction.monitor(Business);;
}catch(Exception); {
   // 异常管理器负责处理异常,如果发现异常不能处理,则回滚事务
    if( !ExceptionManager.handle(Exception); ); {
        Transaction.rollback();;
    }
}

这里,异常处理器 ExceptionManager 需要注意一些问题:
1。处理异常的时候又发生异常;
   对这个问题,我觉得异常处理器最多处理自己的异常,不能再生成一个异常管理器,然后把自己的异常再传递下去。因为异常管理器本身的处理操作和重新抛出操作会形成一个比较简单的单一线索的异常处理链,如果还要把自己的异常传递给其他异常处理器会导致复杂的处理过程,而太复杂了会增加不稳定性,不值得。
2。处理异常所需的资源出现不足或故障;
   比如这里,处理异常的时候发现数据库本身出了问题,也就是处理异常所需的资源出了问题,不能正常处理业务异常。那么需要对异常处理资源有个预测,比如数据库保存错误报告不行,就写日志,写日志时判断文件系统空间够不够,如果不够,显然写日志也行不通。对于这种问题的处理,可以有个程序间歇性的探测文件系统的容量,如果达到预警值就
用某种方式报告给相关的处理人员解决这个后顾之忧。

你的想法还是很不错的。你的思考也很深入,真是个聪明家伙。哈哈

其实,我也要为我昨晚这个比较鲁莽的发贴而道歉,因为当时我自己也没有深入的思考,写了mock交易逻辑,发现一些异常处理带来的bad smell,就急急忙忙的赶着问别人。其实直到今天我重构我的代码过程中,我才整理出一个比较好的思路,这也得益于老庄的帮助。
在很多严格要求交易完整的应用中,异常的处理是作为业务逻辑的一部分的。因为异常的处理是业务实现的一部分,所以我们必须对异常的整个体系进行一个很精确的定义,以使得我们更构根据抛出的异常判断我们需要处理的业务逻辑,异常的抛出,表示业务逻辑必须按照这个异常所发生的情境进行处理。

而我们代码编写中,异常跟正常业务运作确实又有不同的,就像主干流与支流的区别一样。
对于我的应用,我主要整理了我的异常类体系,然后使用一个类似与Log4j的ErrorHandler来统一处理这些正常业务代码中抛出的所有异常,因为异常的定义很精确,精确到交易中的每一个情境,所以我的ErrorHandler能够准确从异常获得它所要执行的业务逻辑。这样的话,我就很好的分离了我的正常运作和异常处理,而又 不分离整体的业务逻辑。
具体的实现可以采用template method的方法,交易的子类只要扩展真正的正常运作的代码即可。 所有的异常处理都已经由ErrorHandler代理(或者template method代理)!

至于数据库操作的异常,其实数据库的异常在很多应用中意味着Fatal,这是需要立即停止应用的。当然,你要保证你的对于数据库的操作的逻辑没有出现逻辑错误。
数据库异常,我的思路还是它一旦发生,就停止服务。所以对于数据库的异常,我一般把它当作需要停止服务的事件。
0 请登录后投票
   发表时间:2006-02-08  
firebody的最终解决办法,竟然和robbin的异常、业务逻辑关系观念如出一车,呵呵。。。

异常,具体说是"exception",就是处理分支业务逻辑和运行期不可预测事件。:)
0 请登录后投票
   发表时间:2006-02-08  
:D
原来是多年前的老贴啊
受益良多
0 请登录后投票
   发表时间:2006-02-08  
ddandyy 写道
:D
原来是多年前的老贴啊
受益良多

温故而知新
不好么
每次看一些旧的好贴都有些新的领悟
0 请登录后投票
论坛首页 Java企业应用版

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