日期:2014-05-20  浏览次数:20766 次

项目开发中异常的处理
现在带领一个很小的开发团队工作。4个开发人员。测试人员不定。项目周期一般在1,2个月左右一个。项目不大。在开发过程中由于几个开发人员的擅长的方向不同。则分成了前后台的开发分配方式。往往是2个人员开发前台。1个开发人员开发业务逻辑层。一个开发人员开发数据底层。由于没有统一的异常处理机制。则导致了现在很混乱的情况。
  以一个简单的数据保存为例子:后台开发人员将保存方法的异常自己捕获,并返回给上层简单的true或flase。而前台开发人员发现自己页面录入信息没有正常保存后。不知道问题出在了什么地方。闷着头去跟代码。折腾了半天发现是后台开发人员里面有一个方法写错了。浪费了大量的时间和精力。前台人员开始抱怨后台人员不应该try住这个错误,害的他查了半天。而后台开发人员则认为我公布给你接口,不应该将我内部实现的细节公布给你,异常也当然不会直接的丢给你。返回给你是否成功就可以了。这个问题一方面应该是开发人员本身没有做好自己的方法级别的单元测试。也有人提出在开发阶段打开所有的异常或错误。在调试完成后再try住,但觉的这样做好像也是不对的。请问各位有经验的人员。对于开发调试阶段,面对这种小规模的团队开发。对于各个开发人员分开开发前后台的模式。各自方法中发生的异常应该怎么处理会比较合适呢?

------解决方案--------------------
引用楼主 ocochi 的帖子:
后台开发人员将保存方法的异常自己捕获,并返回给上层简单的true或flase…

------解决方案--------------------
引用楼主 ocochi 的帖子:
现在带领一个很小的开发团队工作。4个开发人员。测试人员不定。项目周期一般在1,2个月左右一个。项目不大。在开发过程中由于几个开发人员的擅长的方向不同。则分成了前后台的开发分配方式。往往是2个人员开发前台。1个开发人员开发业务逻辑层。一个开发人员开发数据底层。由于没有统一的异常处理机制。则导致了现在很混乱的情况。
以一个简单的数据保存为例子:后台开发人员将保存方法的异常自己捕获,并返回给上层简单的true或flase。而前台开发人员发现自己页面录入信息没有正常保存后。不知道问题出在了什么地方。闷着头去跟代码。折腾了半天发现是后台开发人员里面有一个方法写错了。浪费了大量的时间和精力。前台人员开始抱怨后台人员不应该try住这个错误,害的他查了半天。而后台开发人员则认为我公布给你接口,不应该将我内部实现的细节公布给你,异常也当然不会直接的丢给你。返回给你是否成功就可以了。这个问题一方面应该是开发人员本身没有做好自己的方法级别的单元测试。也有人提出在开发阶段打开所有的异常或错误。在调试完成后再try住,但觉的这样做好像也是不对的。请问各位有经验的人员。对于开发调试阶段,面对这种小规模的团队开发。对于各个开发人员分开开发前后台的模式。各自方法中发生的异常应该怎么处理会比较合适呢?

------解决方案--------------------
2。表示层:catch ApplicationException, 并 alert(appEx.Message) 给用户; 
业务层:对数据进行必要滴业务规则检查,发现违规及时 throw new ApplicationException("出错啦!"); 
数据层:执行 DB 操作,不应出现任何 catch 语句!。。。。。这里我想深问一下,对于DB 操作,不应出现任何 catch 语句。这个是为什么呢?还有对于数据进行的必要检查,这个大部分情况下不都是可以在UI交给业务层之前就通过一些方法完成的吗?为什么数据规则检查要放在了业务层呢?



从DDD的角度看,DB访问是数据持久化操作范畴,属于基础结构层面,它不回去理会任何业务逻辑上的错误,比如某个人的年龄是负数。它的作用是持久化(Persistent)或者物质化(Materialization),因此,它不是不会出错,也不是不能使用try..catch,但是你必须明白,基础结构层出现的错误都应该是技术上的,而不是业务上的,比如数据库连接错误、超时、数据表不存在等等这些让普通用户无法理解的错误。
业务逻辑上的错误是普通用户能够理解的错误,比如年龄填成了负数,这个时候就需要在业务层作出判断,并及时通知用户。数据库的确能够通过完整性约束来判断,比如在创建数据表的时候指定某个字段的取值范围,当数据超出这个范围就出错,但这样做已经把业务逻辑引入到基础结构层面了。

------解决方案--------------------
探讨
. 该错误只是记 log, 还是需要通知用户?
要看具体情况的,一般来讲,log是始终会记的,因为是异常,因此记录下log会方便今后的排错。目前记log一般都用类似log4net这样的框架,所以,是否该记log将会由用户自己决定,因为他可以更改log记录的配置信息。

2. 若要通知用户, 由谁来通知? catch 到异常的地方? caller? 抑或 caller's caller?
通知用户请到最上层,也就是UI层去通知,下层只要往上层throw就ok了。记得throw的时候把message写详细一点。

------解决方案--------------------
返回值+异常 共存的方式

返回值的方式是不推荐的。原始的api的确是通过返回值+message的形式报告函数调用的正确与否,但在.NET里引入了异常,为什么?因为返回值除了能代表正确/错误,或者更多地,代表错误类型以外,别的什么都代表不了。别的还有什么?还有:错误类型、什么地方发生的错误?由什么引起的错误?

异常能够承载这些信息。比如A中捕捉了异常,但仍然可能需要继续执行下去,但也可能不去处理而直接向上抛,在这种情况下,A会通过异常的类型来处理。比如:
C# code

foreach (element in elements)
{
    try
    {
      // ...
    }
    catch (IOException)
    {
      // 如果是IOException,则继续
       continue;
    }
    catch (Exception)
    {
      // 如果是其它Exception,则向上抛
      throw;
    }
}