美文网首页架构师程序员架构设计与重构
利用自定义异常来重构代码

利用自定义异常来重构代码

作者: buguge | 来源:发表于2016-12-13 17:27 被阅读122次

    先贴出来代码

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        string jsonStr = "";
        var oReturnValue = new ReturnValue("9999", "无参数");
        if (context.Request.Form.AllKeys.Length > 0)
        {
            try
            {
                var oAlipayRefundApply = new RefundApplyDTO
                {
                    OrderNo = context.Request.Form["on"],
                    OrderAmount = context.Request.Form["oa"],
                    Remark = context.Request.Form["or"]
                };
                var dt = new DataTable();
                var listOrderNo = new List<string>();
                var dicMoney = new Dictionary<string, string>();
                var dicRemark = new Dictionary<string, string>();
                oReturnValue = new AlipayPaymentBLL.AlipayRefundRecord().BuilderArray(listOrderNo, dicMoney, dicRemark, oAlipayRefundApply);//解析传入参数信息
                if (oReturnValue.Code == "0000")
                {
                    oReturnValue = new AlipayPaymentBLL.AlipayRefundRecord().DoRefund(oAlipayRefundApply, dt, listOrderNo, dicMoney, dicRemark);
                    if (oReturnValue.Code == "0000")
                    {
                        oReturnValue = BuilderRequest(dt);
                    }
                }
            }
            catch (Exception ex)
            {
                CommonUtils.LogCommon.instance.writePay(this, "支付宝退款请求组建异常:" + ex);
                oReturnValue = new ReturnValue("9999", "请求发生异常");
            }
        }
    
        jsonStr = JsonConvert.SerializeObject(oReturnValue);
        context.Response.Write(jsonStr);
    }
    

    代码分析

    以上是一个一般处理程序(.ashx文件)的类文件里的主方法ProcessRequest的方法体。
    不考虑逻辑,仅从代码简洁的角度来看,如上代码段存在如下问题:

    • 变量/对象oReturnValue被重复赋值并使用
    • 层层判断嵌套
    • ReturnValue的构造器是两个string参数。我要说的是第一个参数code,在这段代码里,code取值只有0000和9999这两种值,分别代表成功和失败。这时,不如直接改为true/false更直观

    如下是ReturnValue类的定义:

    public class ReturnValue
    {
        /// <summary>
        /// 错误码
        /// </summary>
        private string _code;
    
        /// <summary>
        /// 错误信息
        /// </summary>
        private string _msg;
    
        public ReturnValue(string code, string msg)
        {
            _code = code;
            _msg = msg;
        }
    
        public string Code { get { return _code; } }
        public string MsgStr { get { return _msg; } }
    }
    

    代码重构

    从如下几个角度进行重构:

    • 封装处理方法,主方法里统一做try..catch的异常捕获处理
    • 引入自定义异常, 当判断失败时,返回自定义异常。这样可以去掉很多if的嵌套。
    • 修改接口返回值类型

    重构后的代码如下:

    HttpRequest _ctxRequest;
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        _ctxRequest = context.Request;
        ResponseModel oReturnValue = null;
        try
        {
            oReturnValue = ProcessRequestAndReturnFormHtml();
            CommonUtils.LogCommon.instance.writePay(this, "支付宝退款请求处理完成");
        }
        catch (Exception ex)
        {
            if (ex is ResponseErrorException)
            {
                oReturnValue = new ResponseModel(false, ex.Message);
                CommonUtils.LogCommon.instance.writePay(this, "支付宝退款请求处理失败:" + ex.Message);
            }
            else
            {
                CommonUtils.LogCommon.instance.writePay(this, "支付宝退款请求处理出现异常:" + ex.ToString());
                oReturnValue = new ResponseModel(false, "请求发生异常");
            }
        }
        string jsonStr = JsonConvert.SerializeObject(oReturnValue);
        context.Response.Write(jsonStr);
    }
    
    private ResponseModel ProcessRequestAndReturnFormHtml()
    {
        var oReturnValue = new ReturnValue("9999", "无参数");
        if (_ctxRequest.Form.AllKeys.Length > 0)
        {
            throw new ResponseErrorException("无参数");
        }
        var oAlipayRefundApply = new RefundApplyDTO
        {
            OrderNo = _ctxRequest.Form["on"],
            OrderAmount = _ctxRequest.Form["oa"],
            Remark = _ctxRequest.Form["or"]
        };
    
        var dt = new DataTable();
        var listOrderNo = new List<string>();
        var dicMoney = new Dictionary<string, string>();
        var dicRemark = new Dictionary<string, string>();
        var alipayPaymentBLL = new AlipayPaymentBLL.AlipayRefundRecord();
        alipayPaymentBLL.BuilderArray(listOrderNo, dicMoney, dicRemark, oAlipayRefundApply);//解析传入参数信息
        alipayPaymentBLL.DoRefund(oAlipayRefundApply, dt, listOrderNo, dicMoney, dicRemark);// 发起退款,并获得结果做相应处理
        string formHtml = BuildRequestFormHtml(dt);// 创建支付宝请求(Form表单)
        return new ResponseModel(true, formHtml);
    }
    

    可见,代码清晰了很多。主要的方式是引入了自定义异常ResponseErrorException,使得方法只管返回理想情况下应该返回的参数类型,而现实很骨感,所以,当不满足判断条件时,就通过抛出自定义异常的方式来实现,同时也没有破坏方法的结构。 另外,我将异常捕获统一放到了主方法ProcessRequest里,也使得代码结构清晰,少了那些if的判断,是不是很漂亮?

    同时,涉及到的改动还有相关的上下游的引用:

    1. 前端js在对响应的判断要由判断0000/9999改为true/false

    var url = "ExcuteRefund.ashx";
    $.ajax({
        url: url,
        type: "POST",
        dataType: "json",
        data: { "on": arr[0], "oa": arr[1], "or": arr[2] },
        success: function (result) {
            if (result !== "") {
                var jsonData = eval(result);
                if (jsonData.Code === "0000") {
                    $(".table_MidGl").html("");
                    $(".table_MidGl").append(jsonData.MsgStr);
                } else {
                    alert(jsonData.MsgStr);
                    window.location.reload();
                    return false;
                }
    

    2. 所引用的方法,AlipayRefundRecord.BuilderArray()、AlipayRefundRecord.DoRefund()和本类里的BuildRequestFormHtml(),如下是BuildRequestFormHtml()的改动

    private string BuildRequestFormHtml(DataTable dt)
    {
        ......
        var sortedDicPara = obll.GetRefundParameters(CommonModel.PayCenterConfig.PayPartner.PayPartnerEnums.AlipayApp, dt, ref sInputCharset, ref sLinkString, out sMsg);
        if (!sortedDicPara.Any())
        {
            throw new ResponseErrorException(sMsg);
        }
    
        //拼接url'?'后条件
        string payUrlValueStr = string.Format("{0}&sign={1}&sign_type={2}",
                                                sLinkString,
                                                sortedDicPara["sign"],
                                                sortedDicPara["sign_type"]
                                            );
    
        //发起退款URL
        string url = new CommonModel.PayCenterConfig.ServerURLConfig(CommonModel.PayCenterConfig.PayPartner.PayPartnerEnums.AlipayApp).REFUND_URL;
        CommonUtils.LogCommon.instance.writePay(this, "进入支付宝退款,发起消息: " + url + payUrlValueStr);
        string formHtml = WebCommon.BuildRequest(sortedDicPara, "post", "确认", url, sInputCharset);
        CommonUtils.LogCommon.instance.writePay(this, "进入支付宝退款,发起消息(form表单): " + formHtml);
        return formHtml;
    }

    相关文章

      网友评论

        本文标题:利用自定义异常来重构代码

        本文链接:https://www.haomeiwen.com/subject/bkjbmttx.html