Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588821
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:50:36

这两天把Hopper Island的例子又翻出来看了看,然后与最近正在学习的Duwamish进行了比较,然后总结了一下Duwamish中对异常和错误进行处理的方式。



1. Duwamish的DataAccess层,它利用存储过程读取/写入数据,因此在这一层的Class中的Create/Update/Delete Method都用true/false作为操作成功与否的返回结果。而对于Read Method,就换作返回一个强类型的DataSet(没对应结果时,这个DataSet.DataTable.Rows.Count为0)。在这一层,没有异常或更多的错误信息向上层返回。

2. 而在Business层,CUD操作还是以true/false作为返回结果,与DataAccess层唯一区别的是:在有DataSet作为传入参数的Method中,通过Row.RowError与SetColumnError(),提供了稍微丰富一点的错误信息。

3.  在UI层,如果Business层的操作结果是false,则通过提取DataSet.DataTable.DataRow中的RowError与ColumnError,向用户反馈错误信息(比如用户已经存在、无效的Email地址等)。

这是我自己对该示例的一个剖析:


之前我类似的多层结构设计多参考Hopper Island News范例,与之不同的是,Duwamish中很少见到try-catch的使用,throw也很少。通过学习,我决定在以后的设计中采用这样的方式:

1. DataAccess层自己处理与数据库平台之间交互时发生的异常,因为这层的操作大多是原子级的,返回true/false已经足够了。这一层的编码努力向原子级靠拢。同时在Read Method的编码上,我们更喜欢返回DataSet/null,而不是有数据的DataSet/空行的DataSet。if (ds == null)比if (ds.DataTable.Rows.Count == 0)少打很多字,呵呵。

2. Business层根据DataAccess层的结果true/false,抛出异常给UI层处理。这一层相当于DataAccess层中方法的Shell,只是加入了更多的业务规则的检测。因为业务规则的存在,决定了UI层的很多要求可能因不符合规则而被拒绝,所以这一层会有大量的throw Exception。

3. 在UI层,利用try-catch获取和处理Business层的异常,向用户提供反馈信息。

我这样的设计合理吗?我还在矛盾之中,因为我这样的设计似乎让Business层与UI层在业务逻辑上交叉了,把Business层的一部分工作交给了UI层,Business层有向DataAccess层退化的趋势。而且我这样的设计,需要Business层的实现者向UI层实现者提供一个异常反馈表。

多层结构的系统中利用强类型的DataSet传递数据,这似乎已经成为风尚。但对于如何在多层结构的系统中合理的分配各层对异常与错误处理的责任,甚至确定每一个具体的Method的返回类型,明确各层的接口,我一直掌握不好。希望大家能给出一些建议,并指正我文中的错漏。


posted on 2007-03-18 00:52 Abbey的小匣子 阅读(1660)   

 re: 如何合理设计多层架构系统中的异常和错误处理 2007-03-19 11:05

照我的感觉

如果要使用异常
业务无关的函数可以发起异常,但业务层不要catch,逻辑层也不要,交给最上面的一层去catch,然后反馈给用户

如果不使用异常,貌似在 C#,Java中不是很有意义,因为本身库函数就会有异常,总是要catch,也不在乎多catch一个自己的异常

用C/C++可以不用异常, 无值返回的函数返回一个整数  表示成功, 其他值为错误码,有值返回的函数返回相应的值. 每层都检查上层的调用是否成功.
不过如果能习惯,还是用异常比较好,真的能省很多代码,不过我也不是很习惯,而且C++的异常用起来也不是那么舒服.

"我们更喜欢返回DataSet/null"
这个不是个好习惯 DataSet跟null意义上没有联系,他们是语言层面上的,例如 Dataset F(), 可以描述 F返回一个数据集,数据集可以是空的,但描述F返回一个空指针就容易引起混淆.事实上,总是返回一个Dataset意味着调用者更方便. 例如
Dataset d = F();
foreach( row in d.rows)
{
}
不用检查d是否为空,或者他有多少个,它也不会引发我们不想看到的异常->空引用
返回null是C/C++的做法,如果不是C/C++,就按照语言本身的习惯去做.

 re: 如何合理设计多层架构系统中的异常和错误处理 2007-03-20 22:57

“返回null是C/C++的做法,如果不是C/C++,就按照语言本身的习惯去做.”——谢谢指出我的问题,C++一直就这样过来的,呵呵。

“业务无关的函数可以发起异常,但业务层不要catch,逻辑层也不要,交给最上面的一层去catch,然后反馈给用户”——我现在也是这样做的,业务层向UI层抛出异常,本身不catch。UI层的实现可以是WinForm,也可以是Web

对于DataAccess层,因为Duwamish是用存储过程实现的,因此这部分没有try/catch的设计。所以我才考虑当自己用DataAdapter等实现这层时,也用类似的方法,自己处理数据库扔出的异常和错误。

 re: 如何合理设计多层架构系统中的异常和错误处理 2007-03-30 09:48

做尽可能多你能作的工作,不做你不该做的工作。

不论是哪一层都应该遵循这个规则,这样不论是哪一层对外都是完备的。(细节上,我倒觉得你返回null不如原设计)

没做过J2EE这方面的,你的设计是合理的。UI是需要知道Business的异常定义的,就像使用java和c#一样,异常也是他们间的通信交互协议的一部分(协议并不只是接口函数)。—— 显然,能做好工作的前提下,协议越少使用越方便,实现越简单。


--------------------next---------------------

阅读(455) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~