业务应该这么写--异常处理

     最近在帮同事调试代码,解决Bug的时候,搞了半天发现竟然是因为try{} catch{ return false} 而引起的。所以好好“教训”了这位同事一番。先大概总结:1、我觉得要写try catch的话呢,就必须认认真真的把try写好,还要把catch也写好(很多同事就是把try认认真真的写了,而catch呢就很随意)。2、我一般认为是异常信息要对解决这个异常有帮助,通过堆栈信息能够定位到具体的出错的地方。3、异常和日志一般是标配。欢迎大家留言讨论。

  (一) 编码过程中,常见的案例

    先看看下面几个常见的例子。

    一般来说,我们都是这么写代码的,在数据库访问层,查数据出错了,我们都是做如下处理,请看下面代码。

    public static UserEntity GetUserInfo(string userName){
       UserEntity userEntity = null;
       try{
        //数据库连接
        //准备SQL,
        //返回数据
        //这里报异常了
        userEntity.Id.ToString();
      }
      catch (Exception ex){
//在这里把异常抛出去
throw ex; } return userEntity; }

    当我们调用上端这段代码的时候,从堆栈信息里面的行数是throw ex的行数,明明是userEntity.Id.ToString();报错了,堆栈信息却定位到了throw ex 这里,说明这里存在一个堆栈信息的覆盖问题,这样呢,会导致我们对错误的定位也不够明确了,还是要一行行调试才知道问题出在哪里,堆栈信息处于无用的状态。

     

    (二) 异常处理的正确姿势

        1、一般来说上端必须有,能保证程序不会因为异常死掉(那些全局钩子(MVC 里面ExceptionFilter,Winform的全局捕捉等等也要有) 

        2、不要到处写try catch。不过有些时候,也要写,比如按照事务进行更新,删除操作等等,有可能失败要进行回滚的话要有。

        3、还有就是我们底层的框架,比如写日志等等,这里必须要把try-catch 给写上。因为写日志这些操作是不应该影响业务流程的。

        4、如果因为知识水平的限制,而不断用try catch,那就应该去提升自己。

        5、关于try catch损失性能问题,损失不了多少性能,首先要保证业务系统够稳才是硬道理。

    (三)解决刚刚开始那个问题的做法

        做法一:在调用层面写try catch.并且做好日志记录,(也就是刚刚说的,在上端写try catch);

        做法二:定义一个通用的返回类型;

public class ServiceResult {

    /// <summary>
    /// 状态码(1,代表正常,0、代表出异常)
    /// </summary>
    public int StatusCode { get; set; }

    /// <summary>
    /// 异常信息
    /// </summary>
    public string ErrorMsg { get; set; }
  }

  public class ServiceResult<T> : ServiceResult {
    public T Data { get; set; }
  }

    (四)对于异常的一个总结

        1、正常业务流程不应该用异常来处理,尽量使用Tester-Doer模式;

        2、异常和日志是标配(你可以定义一些自己搞的异常,但是日志里面一定要记录;

        3、尽量在上端记录异常(假如有一个BLL,既可能被winform调用,也可能被控制台调用)

posted @ 2018-05-02 16:53  GDOUJKZZ  阅读(263)  评论(0编辑  收藏  举报