av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

轉(zhuǎn)轉(zhuǎn)游戲的賬號(hào)訂單流程重構(gòu)之路

1、背景

隨著需求的不斷迭代,項(xiàng)目代碼的復(fù)雜度也會(huì)越來(lái)越高,“屎山”也一天一天慢慢的堆積起來(lái),對(duì)于游戲業(yè)務(wù)的賬號(hào)訂單流程也是如此。游戲訂單類型由原來(lái)的倆種增加到了現(xiàn)在的七種,早就已經(jīng)到了需要重構(gòu)的地步。但是由于牽涉流程長(zhǎng)、影響范圍大、平時(shí)需求排期也比較緊張,所以便無(wú)法抽出大量的時(shí)間去進(jìn)行重構(gòu)。因?yàn)橐婚_始就設(shè)計(jì)的不夠規(guī)范、合理,所以之前整個(gè)賬號(hào)訂單流程存在以下主要問題:

在剛察等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),成都全網(wǎng)營(yíng)銷,成都外貿(mào)網(wǎng)站制作,剛察網(wǎng)站建設(shè)費(fèi)用合理。

1.1 核心代碼分布散亂

除了按照原子層、服務(wù)層劃分之外,還有一個(gè)服務(wù)用于接收訂單mq進(jìn)行大量的處理操作,訂單相關(guān)的接口分布于多個(gè)類甚至是一些名稱與訂單毫不相關(guān)的類當(dāng)中。

1.2 缺少設(shè)計(jì)模式

缺少設(shè)計(jì)模式,各種節(jié)點(diǎn)、不同訂單類型的邏輯基本都是通過(guò)各種if-else進(jìn)行處理,耦合度較高,可讀性、可擴(kuò)展性和可維護(hù)性都較差,甚至?xí)霈F(xiàn)修改一種訂單流程反而影響到了其它訂單流程的情況。

1.3 影響交付效率

代碼分布在多個(gè)服務(wù)當(dāng)中,開發(fā)一個(gè)相關(guān)需求時(shí)經(jīng)常需要拉4、5個(gè)項(xiàng)目分支。由于容易修改到了其它訂單模式的代碼,所以在測(cè)試的時(shí)候往往又需要回歸其它模式的訂單流程是否有受影響。這些都大大影響了開發(fā)測(cè)試以及最終交付的效率。

現(xiàn)在業(yè)務(wù)趨于穩(wěn)定,需求迭代也沒有這么快了,因此就有了重構(gòu)訂單流程的想法。最終的目的就是為了保證良好的可讀性、可維護(hù)性和可擴(kuò)展性。有了重構(gòu)想法的之后,產(chǎn)生了許多問題,主要如下:

  • 怎么進(jìn)行重構(gòu)呢,用什么設(shè)計(jì)模式?
  • 重構(gòu)后的測(cè)試上線怎么進(jìn)行呢?
  • 如果上線出現(xiàn)問題要怎么處理?

接下來(lái)就圍繞這幾個(gè)問題來(lái)敘述一下賬號(hào)訂單流程的重構(gòu)之路。

2、如何重構(gòu)

2.1 方案確定

先簡(jiǎn)單介紹一下游戲賬號(hào)交易的流程,最開始的時(shí)候有兩種交易方式,分別是客服發(fā)貨交易和自主發(fā)貨交易。兩者最大的區(qū)別是是否需要第三角色客服的介入,后來(lái)七種訂單交易模式都是在這兩種模式基礎(chǔ)上誕生的。

既然有七種訂單類型,這好辦啊??梢圆捎貌呗?模板模式啊,一個(gè)抽象模板+七個(gè)子類就可以啦。但是后來(lái)仔細(xì)一想,如果將所有的處理邏輯都放在父類和子類當(dāng)中,其實(shí)代碼整體也顯得十分臃腫。

為了想出更好的解決方案,于是對(duì)原有代碼和業(yè)務(wù)流程進(jìn)行了深入的梳理和總結(jié),主要有以下幾點(diǎn):

  1. 所有訂單流程都是在客服發(fā)貨和自主發(fā)貨基礎(chǔ)上衍生出來(lái)的。
  2. 所有訂單流程都包含下單、支付、上傳賬密、發(fā)貨、確認(rèn)收貨等節(jié)點(diǎn)。
  3. 在這些節(jié)點(diǎn)里不同訂單類型大多會(huì)有各自一些特定操作,但是這些操作其實(shí)并不屬于訂單的主流程。

通過(guò)以上分析,是不是可以將下單到確認(rèn)收貨作為一層,將不同訂單類型的特定處理實(shí)現(xiàn)作為一層呢?這樣不就將訂單流程中各種特殊處理從訂單主流程剝離開了嗎,因此最終決定采用三層接口+策略模板的設(shè)計(jì)方案。

2.2 三層接口+策略模板模式

接口設(shè)計(jì)如下:

  • 第一層接口

包含前端用戶進(jìn)行交互、處理mq消息以及給其它服務(wù)調(diào)用的接口。

  • 第二層接口

訂單核心主流程能力接口。將下單、支付到確認(rèn)收貨等“不變”的基礎(chǔ)能力提供給頂層接口調(diào)用,這層接口有自主發(fā)貨流程和客服發(fā)貨流程兩個(gè)實(shí)現(xiàn)類。

public interface IGameAccountOrderDealProcess {
    /**
     * 處理下單未支付訂單
     */
    int handlePlaceOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 處理支付成功訂單
     */
    int handlePaySuccessOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 處理已發(fā)貨訂單
     */
    int handleDeliverOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 處理支付前取消訂單
     */
    int handleCancelBeforePayOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 處理支付后取消訂單
     */
    int handleCancelAfterPayOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 處理交易成功訂單
     */
    int handleConfirmReceiptOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 賬號(hào)交易窗數(shù)據(jù)
     */
     T getOrderTradeData(String logStr, Long orderId, Integer device, Long uid);
    /**
     * 上傳賬密
     */
    ZZOpenScfBaseResult uploadAccountAndPwd(GameAccountSelfTrade.AccountPwdArg arg, long uid, String logStr, ServiceHeaderEntity header) throws Exception;
    /**
     * 發(fā)貨
     * @param orderContext
     */
    boolean deliverOrder(GameAccountOrderContext orderContext) throws Exception;
    /**
     * 訂單確認(rèn)收貨
     */
    ZZOpenScfBaseResult confirmReceiptOrder(GameAccountOrderContext orderContext, Long uid, boolean needCheckRisk) throws Exception;
}
  • 第三層接口

各種訂單類型的特殊處理,每一種訂單模式都對(duì)應(yīng)一個(gè)實(shí)現(xiàn)類。

public interface ITradeSelfHandler {
    GameAccountTradeFlow.GameAccountTradeType getOrderTrade();
    /*------------處理mq消息相關(guān)---------------*/
    /**
     *1.插入表之前設(shè)置客服和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);
    /**
     * 確認(rèn)收貨處理
     */
    int handleAfterConfirmReceipt(GameAccountOrderContext orderContext) throws Exception;
    /*---------------------------------*/
    /**
     * 獲取提現(xiàn)時(shí)間
     */
    Date getWithDrawlTime();
    /**
     * 發(fā)送支付成功push
     */
    void orderAlreadyPayPushMsgNew(GameAccountOrderContext orderContext, Pair jumpUrl);
    /**
     * 獲取分帳賬戶、類別信息
     */
    List getOrderSplitModelList(GameAccountOrderContext orderContext, OrderMaxSettleInfo settleInfo);
    /**
     * 定制各自spiUi
     */
    void buildOrderSpiUiData(GameAccountOrderContext orderContext, GameOrderSpiConfig bConfig, GameOrderSpiConfig sConfig, SpiUiData spiUiData) throws Exception;
    /**
     * 確認(rèn)收貨后一些處理
     */
    void otherOperationAfterReceipt(GameAccountOrderContext orderContext, Long uid);
}

2.3 具體實(shí)現(xiàn)

  • 核心代碼收攏到一個(gè)服務(wù),相關(guān)接口進(jìn)行聚合

原先在客服后臺(tái)、定時(shí)任務(wù)、mq集群都有一些訂單的操作,但是這些代碼基本都是重復(fù)的,所以此次重構(gòu)在訂單核心服務(wù)中新增相應(yīng)的訂單操作功能,統(tǒng)一由其它服務(wù)進(jìn)行RPC調(diào)用。

將訂單相關(guān)的接口、工具類集中到同一個(gè)包下,方便定位。

  • 整體類圖及設(shè)計(jì)原則
  1. 命名規(guī)范:類名、變量名、方法名盡量見名知義。
  2. 單一職責(zé):各個(gè)模塊各司其職,避免與其它模塊過(guò)度耦合。
  3. 準(zhǔn)備訂單上下文,清除RPC重復(fù)調(diào)用問題。
//上下文實(shí)體
public class GameAccountOrderContext {
    private String logStr;
    private Long orderId;
    private Integer mqStatus;
    private Order order;
    private GameAccountOrderResultEntity accountOrderEntity;
    private AccountOrderStatusEnum orderStatus;
    private Boolean hasInsuranceService;//訂單是否有保險(xiǎn)
    private GameAccountTradeFlow.GameAccountTradeType tradeType;
    private GameAccountProductData accountProductData;
    private ZZProduct product;
    private ZZProductExt productExt;
    private Map extValueMap;
    private AccountHelpSaleClue helpSaleClue;//幫賣線索
    private DistributionShareInfoDTO distributionShareInfo;//分銷信息
    private ITradeSelfHandler tradeSelfHandler;
    private Integer serviceUiStatus;//對(duì)應(yīng)訂單spi狀態(tài)
}
//上下文準(zhǔn)備
GameAccountOrderContext orderContext = orderContextBuilder.buildAccountOrderContext(order, zzProduct, logStr);

3、上線保障

訂單流程不管對(duì)于什么業(yè)務(wù),基本都是最重要的一個(gè)環(huán)節(jié),為了避免產(chǎn)生重大問題,需要做到以下兩點(diǎn):

  1. 嚴(yán)格保證線下測(cè)試的準(zhǔn)確性。
  2. 出現(xiàn)線上問題,影響范圍要盡可能小。

3.1 流程測(cè)試

根據(jù)賬號(hào)訂單流程的特點(diǎn),在測(cè)試的時(shí)候遵循以下原則:

  • 訂單流程正常跑通
  • 訂單分帳正確
  • 訂單保險(xiǎn)正常
  • 各個(gè)節(jié)點(diǎn)與原來(lái)保持一致
  • 相關(guān)push、私信正常發(fā)送
  • 統(tǒng)計(jì)日志正常打印

對(duì)于每一種訂單流程,同時(shí)進(jìn)行新、老流程訂單的測(cè)試。逐一對(duì)比新、老流程的買家側(cè)和賣家側(cè)各個(gè)流程節(jié)點(diǎn)的頁(yè)面、按鈕、跳轉(zhuǎn)、push、私信等是否保持一致。

3.2 灰度策略

為了避免產(chǎn)生重大問題,上線后必須采取灰度策略,不然出了問題就可能就是事故了。本次采用的灰度策略是上線后按訂單類型、訂單量進(jìn)行灰度,同時(shí)將灰度訂單落表記錄,配置如下:

[
  {
    "orderType": 6,//訂單類型
    "dayNum": 50,//每日灰度量
    "isTotalGray": true//是否全量
  }
]
 /**
  * 判斷訂單是否走新交易流程
  */
public boolean isNewOrderProcess(String logStr, GameAccountOrderContext orderContext) {
        Long orderId = orderContext.getOrderId();
        try {
            if (gameGrayTestService.isNewTradeProcessOrder(orderId)){
                return true;
            }
            GameAccountOrderResultEntity orderEntity = accountOrderManage.getGameAccountOrderEntity(orderId, logStr);
            GameAccountTradeFlow.GameAccountTradeType orderTradeType = orderContext.getTradeType();
            String orderRedisSet = String.format("account_order_gray_set_%s_%s", Objects.nonNull(orderEntity) ? orderEntity.getSelfType() : orderTradeType.getSelfType(), DateUtil.format(new Date(), "yyyy-MM-dd"));
            if (ZZGameRedisUtil.sismember(orderRedisSet, orderId.toString())){
                return true;
            }
            if (newAccountOrderTradeSwitch){
                return true;
            }
            Optional grayConfigOptional = grayConfigList.stream().filter(c->c.getOrderType() == orderTradeType.getSelfType()).findFirst();
            if (grayConfigOptional.isPresent()){
                OrderGrayConfig grayConfig = grayConfigOptional.get();
                if (Objects.nonNull(grayConfig.getIsTotalGray()) && grayConfig.getIsTotalGray()){
                    return true;
                }
                if (orderContext.getOrderStatus() != AccountOrderStatusEnum.place_order){//只處理新訂單
                    return false;
                }
                String dayNumKey = String.format(NEW_ORDER_PROCESS_GRAY_NUM, DateUtil.format(new Date(), "yyyy-MM-dd"), orderTradeType.getSelfType());
                if (NumberUtils.toInt(ZZGameRedisUtil.get(dayNumKey)) < grayConfig.getDayNum()){
                    int result = gameGrayTestService.insertNewTradeProcessOrder(orderId);
                    log.info("{} desc=insert_gray_order_data orderId={} result={}", logStr, orderId, result);
                    if (result > 0){
                        ZZGameRedisUtil.increAndGet(dayNumKey, 1);
                        ZZGameRedisUtil.expire(dayNumKey, 3600*24);
                        ZZGameRedisUtil.sadd(orderRedisSet, orderId.toString());
                        ZZGameRedisUtil.expire(orderRedisSet, 3600*24);
                    }
                    return result >= 0;
                }
                return false;
            }
        } catch (Exception e) {
            log.error("{} desc=isNewOrderProcess_error orderId={}", orderContext.getLogStr(), orderContext.getOrderId(), e);
        }
        return false;
}

3.3 異常機(jī)制

在一些重要的節(jié)點(diǎn)設(shè)置告警機(jī)制,比如上傳賬密、發(fā)貨、提現(xiàn)等節(jié)點(diǎn)出現(xiàn)異常時(shí)會(huì)發(fā)送企業(yè)微信告警通知,可以第一時(shí)間關(guān)閉灰度,查找問題。

不過(guò)對(duì)于分帳正確性保障這塊只是通過(guò)測(cè)試確保正確,這種最好是可以接入中臺(tái)的BCP(Business Check Platform)系統(tǒng)。它是一種標(biāo)準(zhǔn)化數(shù)據(jù)校對(duì)平臺(tái),支持標(biāo)準(zhǔn)化數(shù)據(jù)源接入,基于事件觸發(fā)規(guī)則執(zhí)行,進(jìn)行業(yè)務(wù)數(shù)據(jù)校對(duì),可以及時(shí)快速的發(fā)現(xiàn)業(yè)務(wù)異常數(shù)據(jù)并實(shí)時(shí)告警。

4 總結(jié)

在對(duì)訂單流程進(jìn)行重構(gòu)之后,新增或修改某種訂單模式,只需增改相應(yīng)的訂單類型處理類就可以了,也不用擔(dān)心本次修改會(huì)影響到其它的訂單模式,大大提高了開發(fā)效率。此外,重構(gòu)代碼可以幫助我們進(jìn)一步深入了解整個(gè)業(yè)務(wù)流程,發(fā)現(xiàn)代碼的壞味道,提升代碼結(jié)構(gòu)設(shè)計(jì)能力。


分享文章:轉(zhuǎn)轉(zhuǎn)游戲的賬號(hào)訂單流程重構(gòu)之路
當(dāng)前鏈接:http://uogjgqi.cn/article/cdspdgp.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流