这两天把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)