|
1背景1.1核心代码分布散乱1.2缺少设计模式1.3影响交付效率2如何重构2.1方案确定2.2三层接口+策略模板模式2.3具体实现3上线保障3.1流程测试3.2灰度策略3.3异常机制4总结1背景随着需求的不断迭代,项目代码的复杂度也会越来越高,“屎山”也一天一天慢慢的堆积起来,对于游戏业务的账号订单流程也是如此。游戏订单类型由原来的俩种增加到了现在的七种,早就已经到了需要重构的地步。但是由于牵涉流程长、影响范围大、平时需求排期也比较紧张,所以便无法抽出大量的时间去进行重构。因为一开始就设计的不够规范、合理,所以之前整个账号订单流程存在以下主要问题:1.1核心代码分布散乱除了按照原子层、服务层划分之外,还有一个服务用于接收订单mq进行大量的处理操作,订单相关的接口分布于多个类甚至是一些名称与订单毫不相关的类当中。1.2缺少设计模式缺少设计模式,各种节点、不同订单类型的逻辑基本都是通过各种if-else进行处理,耦合度较高,可读性、可扩展性和可维护性都较差,甚至会出现修改一种订单流程反而影响到了其它订单流程的情况。1.3影响交付效率代码分布在多个服务当中,开发一个相关需求时经常需要拉4、5个项目分支。由于容易修改到了其它订单模式的代码,所以在测试的时候往往又需要回归其它模式的订单流程是否有受影响。这些都大大影响了开发测试以及最终交付的效率。现在业务趋于稳定,需求迭代也没有这么快了,因此就有了重构订单流程的想法。最终的目的就是为了保证良好的可读性、可维护性和可扩展性。有了重构想法的之后,产生了许多问题,主要如下:怎么进行重构呢,用什么设计模式?重构后的测试上线怎么进行呢?如果上线出现问题要怎么处理?接下来就围绕这几个问题来叙述一下账号订单流程的重构之路。2如何重构2.1方案确定先简单介绍一下游戏账号交易的流程,最开始的时候有两种交易方式,分别是客服发货交易和自主发货交易。两者最大的区别是是否需要第三角色客服的介入,后来七种订单交易模式都是在这两种模式基础上诞生的。既然有七种订单类型,这好办啊。可以采用策略+模板模式啊,一个抽象模板+七个子类就可以啦。但是后来仔细一想,如果将所有的处理逻辑都放在父类和子类当中,其实代码整体也显得十分臃肿。为了想出更好的解决方案,于是对原有代码和业务流程进行了深入的梳理和总结,主要有以下几点:所有订单流程都是在客服发货和自主发货基础上衍生出来的。所有订单流程都包含下单、支付、上传账密、发货、确认收货等节点。在这些节点里不同订单类型大多会有各自一些特定操作,但是这些操作其实并不属于订单的主流程。通过以上分析,是不是可以将下单到确认收货作为一层,将不同订单类型的特定处理实现作为一层呢?这样不就将订单流程中各种特殊处理从订单主流程剥离开了吗,因此最终决定采用三层接口+策略模板的设计方案。2.2三层接口+策略模板模式接口设计如下:第一层接口包含前端用户进行交互、处理mq消息以及给其它服务调用的接口。第二层接口订单核心主流程能力接口。将下单、支付到确认收货等“不变”的基础能力提供给顶层接口调用,这层接口有自主发货流程和客服发货流程两个实现类。public interface IGameAccountOrderDealProcess { /** * 处理下单未支付订单 */ int handlePlaceOrder(GameAccountOrderContext orderContext) throws Exception; /** * 处理支付成功订单 */ int handlePaySuccessOrder(GameAccountOrderContext orderContext) throws Exception; /** * 处理已发货订单 */ int handleDeliverOrder(GameAccountOrderContext orderContext) throws Exception; /** * 处理支付前取消订单 */ int handleCancelBeforePayOrder(GameAccountOrderContext orderContext) throws Exception; /** * 处理支付后取消订单 */ int handleCancelAfterPayOrder(GameAccountOrderContext orderContext) throws Exception; /** * 处理交易成功订单 */ int handleConfirmReceiptOrder(GameAccountOrderContext orderContext) throws Exception; /** * 账号交易窗数据 */ T getOrderTradeData(String logStr, Long orderId, Integer device, Long uid); /** * 上传账密 */ ZZOpenScfBaseResult uploadAccountAndPwd(GameAccountSelfTrade.AccountPwdArg arg, long uid, String logStr, ServiceHeaderEntity header) throws Exception; /** * 发货 * @param orderContext */ boolean deliverOrder(GameAccountOrderContext orderContext) throws Exception; /** * 订单确认收货 */ ZZOpenScfBaseResult confirmReceiptOrder(GameAccountOrderContext orderContext, Long uid, boolean needCheckRisk) throws Exception;}第三层接口各种订单类型的特殊处理,每一种订单模式都对应一个实现类。public interface ITradeSelfHandler { GameAccountTradeFlow.GameAccountTradeType getOrderTrade(); /*------------处理mq消息相关---------------*/ /** *1.插入表之前设置客服和extendInfo */ void fillExtraOrderInfoBeforeInsert(GameAccountOrderResultEntity orderEntity, GameAccountOrderContext orderContext); /** * 下单后处理 */ void handleAfterPlaceOrder(GameAccountOrderContext orderContext); /** * 支付前取消处理 */ void handleCancelBeforePay(GameAccountOrderContext orderContext); /** * 支付后取消处理 */ int handleCancelAfterPay(GameAccountOrderContext orderContext) throws Exception; /** * 支付后一些额外处理 */ int handleAfterPaySuccess(GameAccountOrderContext orderContext); /** * 确认收货处理 */ int handleAfterConfirmReceipt(GameAccountOrderContext orderContext) throws Exception; /*---------------------------------*/ /** * 获取提现时间 */ Date getWithDrawlTime(); /** * 发送支付成功push */ void orderAlreadyPayPushMsgNew(GameAccountOrderContext orderContext, air jumpUrl); /** * 获取分帐账户、类别信息 */ List
|
|