• 关于审批成功或确认逆向操作下有多个相同动作的程序设计


    我们在开发过程中,一般都会遇到这样的需求吧。
    审批通过的时候要执行多个动作:

    1.更改A表的状态为“已审批”,我们记为操作A

    2.插入B表一条数据 ,我们记为操作B

    3.更改C表的多条数据的状态,我们记为操作C

    N多

    .......

    但是当N多天后,在业务发生需要逆向这个审批的时候,我们需要回滚这些操作。

    我们需要一个不漏的逆向刚刚审批做的操作。

    这个时候如果我们这样写:

    审批方法()
    
    {
    
    1.动作A
    
    2.动作B
    
    3.动作C
    
    ......
    
    }
    
    逆向方法()
    
    {
    
    1.逆向A
    
    2.逆向B
    
    3.逆向C
    
    ......
    
    }

    这样的话,如果后续业务再增加一个动作的时候,需要改动两处地方,万一漏掉一处(往往都是逆向处) ,并且测试都没测出来,那么问题就可大可小了。

    我们从程序设计上就可以避免这个问题的产生。

    我这边是生成付款清单*(情形类似)为例:

    1.先定义一个接口,包含两个方法:生成与删除

        public interface IPayToDealerOperate
        {
            /// <summary>
            /// 生成付款明细接口
            /// </summary>
            /// <param name="db"></param>
            /// <param name="dbQuery"></param>
            /// <param name="listWarranty"></param>
            /// <param name="currentId"></param>
            /// <returns></returns>
            List<ClmPayToDealer> GeneratePayDetail(CEPEntities db, CepOneViewEntities dbQuery, List<ClmWarranty> listWarranty, long currentId);
            /// <summary>
            /// 删除付款明细接口
            /// </summary>
            /// <param name="DbContext"></param>
            /// <param name="dbQuery"></param>
            /// <param name="payMasterId"></param>
            /// <param name="currentId"></param>
            /// <param name="payDetailId"></param>
            /// <returns></returns>
            string DeletePayDetail(CEPEntities DbContext, List<ClmPayToDealer> payItemAllList, ClmPayToDealer pDetail, long currentId);
        }

    2.为每个子动作分别创建类,并分别实现上面接口

        public class PayNormalDetailImpl : IPayToDealerOperate
        {
            /// <summary>
            /// 生成付款明细接口
            /// </summary>
            /// <param name="db"></param>
            /// <param name="dbQuery"></param>
            /// <param name="listWarranty"></param>
            /// <param name="currentId"></param>
            /// <returns></returns>
            public List<ClmPayToDealer> GeneratePayDetail(CEPEntities db, CepOneViewEntities dbQuery, List<ClmWarranty> listWarranty, long currentId)
            {
                 //内含正常保修单生成付款项操作,此动作非重点已省略
    
                return listPayToDealer;
            }
            /// <summary>
            /// 删除付款明细接口
            /// </summary>
            /// <param name="DbContext"></param>
            /// <param name="dbQuery"></param>
            /// <param name="payMasterId"></param>
            /// <param name="currentId"></param>
            /// <param name="payDetailId"></param>
            /// <returns></returns>
            public string DeletePayDetail(CEPEntities DbContext, List<ClmPayToDealer> payItemAllList, ClmPayToDealer pDetail, long currentId)
            {
                 //内含收货入库删除操作,此动作非重点已省略
    
                return string.Empty;
            }
        }
        public class PayPartReceiveInstockDetailImpl : IPayToDealerOperate
        {
            /// <summary>
            /// 生成付款明细接口
            /// </summary>
            /// <param name="db"></param>
            /// <param name="dbQuery"></param>
            /// <param name="listWarranty"></param>
            /// <param name="currentId"></param>
            /// <returns></returns>
            public List<ClmPayToDealer> GeneratePayDetail(CEPEntities db, CepOneViewEntities dbQuery, List<ClmWarranty> listWarranty, long currentId)
            {
                 //内含审计扣款生成付款项操作,此动作非重点已省略
    
                return listPayToDealer;
    
                
            }
            /// <summary>
            /// 删除付款明细接口
            /// </summary>
            /// <param name="DbContext"></param>
            /// <param name="dbQuery"></param>
            /// <param name="payMasterId"></param>
            /// <param name="currentId"></param>
            /// <param name="payDetailId"></param>
            /// <returns></returns>
            public string DeletePayDetail(CEPEntities DbContext, List<ClmPayToDealer> payItemAllList, ClmPayToDealer pDetail, long currentId)
            {
                //内含收货入库删除操作,此动作非重点已省略
    
                return string.Empty;
    
            }
        }
        public class PayAuditDebitImpl : IPayToDealerOperate
        {
            /// <summary>
            /// 生成付款明细接口
            /// </summary>
            /// <param name="db"></param>
            /// <param name="dbQuery"></param>
            /// <param name="listWarranty"></param>
            /// <param name="currentId"></param>
            /// <returns></returns>
            public List<ClmPayToDealer> GeneratePayDetail(CEPEntities db, CepOneViewEntities dbQuery, List<ClmWarranty> listWarranty, long currentId)
            {
                //内含审计扣款生成付款项操作,此动作非重点已省略
    
                return listPayToDealer;
            }
            /// <summary>
            /// 删除付款明细接口
            /// </summary>
            /// <param name="DbContext"></param>
            /// <param name="dbQuery"></param>
            /// <param name="payMasterId"></param>
            /// <param name="currentId"></param>
            /// <param name="payDetailId"></param>
            /// <returns></returns>
            public string DeletePayDetail(CEPEntities DbContext, List<ClmPayToDealer> payItemAllList, ClmPayToDealer pDetail, long currentId)
            {
                //内含审计删除操作,此动作非重点已省略
    
                return string.Empty;
    
            }
        }

    3.在调用处定义接口数组:

            /// <summary>
            /// 付款清单新增数据与删除数据,统一管理入口
            /// </summary>
            private IPayToDealerOperate[] _payDetailOperateArray = new IPayToDealerOperate[] {
                new PayNormalDetailImpl(),//正常付款清单
                new PayPartReceiveInstockDetailImpl(),//零件收货入库扣款
                new PayAuditDebitImpl()//保修审计扣款
            };

    4.在调用处循环数组执行相应动作。

    4.1 在生成付款单处执行生成动作。

                            foreach (var action in _payDetailOperateArray)
                            {
                                listPayTotalItem.AddRange(action.GeneratePayDetail(db, dbQuery, item.ToList(), currentId));
                            }

    4.2 在删除付款单时执行删除动作。

                   //循环处理_payDetailOperateArray中包含的还原扣款信息
                    foreach (var action in _payDetailOperateArray)
                    {
                        action.DeletePayDetail(DbContext, payItemAllList, pdForDel, currentId);
                    }

    至此,大功告成。如若后续业务需要增加扣款项,那么我只需新建一个类,这个类实现了最初定义的接口,那么我就必须去实现生成和退回操作,从而避免了漏操作的尴尬,同时也遵循着开闭原则。

    补充,如果我增加了一个业务,只需要在生成付款项的时候进行动作,删除的时候不要有动作,那么只要实现这个删除动作,直接返回即可。

  • 相关阅读:
    19c 新特性: Hint Usage Reports详解
    byte buddy学习笔记
    彻底告别“人工+Excel”低效模式,传统制造业实现“一站式”数据化管理
    有的人想在上班之余做兼职,并且不想投入太多钱
    2019你为什不选择创业?是因为什么原因?
    深入理解pandas读取excel,txt,csv文件等命令
    劳务派遣公司是怎么盈利的?
    为什么穷人大多不敢创业?
    30多岁了仍一事无成,除了去工厂上班还有哪些出路?
    MySQL Change Data Directory
  • 原文地址:https://www.cnblogs.com/zhanghai/p/9856073.html
Copyright © 2020-2023  润新知