成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 服務器端內(nèi)部業(yè)務處理失敗消息傳遞方式

MangoGoing / 1334人閱讀

摘要:綜合以上問題得出以下結論業(yè)務處理失敗消息要以的方式向上傳遞給調(diào)用者業(yè)務處理失敗消息以參數(shù)的方式傳遞不是很適合,并且不能以的方式返回再次思考,最終從里面想到了一點思路幸好是出身。

  

我需要拍磚 和 看見你們的意見,為團隊少挖坑

場景:創(chuàng)建訂單 實際流程:
  

終端調(diào)用(PC端、移動端APP、微信端、Web端)-->控制器 或 接口-->實際的業(yè)務處理-->控制器 或 接口-->終端做出相應處理(控制器可能是渲染對應頁面; 接口返回 JSON數(shù)據(jù))

業(yè)務處理類動作:

檢查用戶是否登陸

驗證商品 ID、購買數(shù)量等參數(shù)

檢查該商品是否處于上架中

檢查該商品是否可以購買

各種檢查...

創(chuàng)建訂單

記錄 Log

返回訂單創(chuàng)建結果給調(diào)用者

創(chuàng)建失敗:...

創(chuàng)建成功:[return true|return Order info]

游戲規(guī)則

前后端數(shù)據(jù)格式約定為 JSON格式如下:

{
    code: "00000",      // 狀態(tài)碼
    msg: "操作成功!",   // 提示信息
    data: {}            // 數(shù)據(jù)
}
  

注:"00000":業(yè)務成功狀態(tài)碼;非"00000"都為業(yè)務失敗。
為了防止服務器端狀態(tài)碼泛濫成災,code可以為"",這時 msg 里面則是相應的錯誤信息,只為給用戶提示。

導火線

項目開發(fā)完畢,測試人員去測試,提如下Bug:

  

如果用戶未登錄,進個人中心,提示用戶未登錄,然后會去登陸view;而在下單頁,提示用戶未登錄,卻沒有去登陸view。

然后前端童鞋開始去修復該問題,查出如下問題:

個人中心服務器接口返回的數(shù)據(jù)格式:

{
    code: "00008",
    msg: "用戶未登錄,請登錄",
    data: [ ]
}

下單頁服務器接口返回的數(shù)據(jù)格式:

{
    code: "",
    msg: "用戶未登錄,請登錄!",
    data: [ ]
}

然后前端童鞋對服務器端童鞋講,這里你應該返回給我code: "00008",我這邊一看 code便知是用戶未登錄,就可以做出相應的操作,這里你只返回提示信息,我這邊不好做更加細膩的操作。

然后,后端童鞋開始嘗試給該地方添加上 code。
開始著手修改代碼:
首先找到接口方法里面發(fā)現(xiàn)如下 demo:

php$order = kernel::single("sysapi_ecoupon_order")->create($params, $msg);
if (!$order) {
    return array("code" => "", "data" => array(), "msg" => $msg);
}
return array("code" => "00000", "data" => $order);

改方法返回array(); 在外部統(tǒng)一入口、出口處再返回 JSON出去。

sysapi_ecoupon_order

phppublic function createNew($params, & $msg)
{
    // 獲取用戶信息
    $member_info = app::get("b2c")->model("members")->get_current_member();

    if (empty($member_info)) {
        $msg = app::get("ecoupon")->_("用戶未登錄,請登錄!");
        return false;
    }
    // 繼續(xù)下面的業(yè)務處理
}

接口調(diào)用的kernel::single("sysapi_ecoupon_order")->create($params, $msg);這里面做實際的業(yè)務處理,錯誤信息是通過 $msg 向上傳遞出去,外部沒辦法通過 $msg 獲知對應的 code。然后給前端童鞋講這種情況沒辦法返回 code給你。

前端就只能通過判斷 msg的方式來修復該問題
然后寫了如下 demo:

javascriptif("用戶未登錄,請登錄!" == data.msg) {
    // 用戶未登錄,去登錄
    // ...
}

然后提交,測試,通過,上線,N天后

有人跑過來講:下單頁 與 個人中心的提示有點不同,貌似多了個 "!"。(舉例而已,更多的可能是提示不友好、錯別字等情況)

然后后端同學修改為 $msg = app::get("ecoupon")->_("用戶未登錄,請登錄"); 提交,測試不通過,前端同學再修改為if("用戶未登錄,請登錄" == data.msg),提交,測試通過

// 如此反反復復

終究有一天:產(chǎn)品、測試,前端、后端混戰(zhàn)了一場。N人,卒.....

重新正視問題

最終前后端得出結論:要想對用戶實現(xiàn)更加友好的體驗,前后端數(shù)據(jù)必須有個標識具有唯一性,不變性。而現(xiàn)在用的 msg卻不具備,還是得用 code。并且這里前后端極度耦合msg。

后端童鞋回來繼續(xù)修改代碼,開始著手給這里添加上相應的 code。
開始思考該怎么添加 code,現(xiàn)在的問題是 create( ) 方法可能是其他童鞋開發(fā),內(nèi)部返回的提示信息,我這邊是調(diào)用者,不能確定方法內(nèi)部到底會返回什么提示信息,無解。

忽然,有一天想到,我在調(diào)用該方法之前檢查下用戶有沒有登錄就OK了,然后開始寫如下實現(xiàn):

public function create($params)
{
    $member = app::get("b2c")->model("members")->get_current_member();

    // 登錄驗證
    if (empty($member)) {
        return array("code" => "00008");
    }

    $msg = "";

    $order = kernel::single("sysapi_ecoupon_order")->create($params, $msg);
    if (!$order) {
        return array("code" => "", "data" => array(), "msg" => $msg);
    }
    return array("code" => "00000", "data" => $order);
}

呵呵,好機智的少年。
然后告訴前端,這里可以返回 code了,前端愉快的刪掉原來那坨判斷 msg的代碼,而在 ajax請求的地方統(tǒng)一判斷 code就能預知用戶未登錄,做出相應的操作。

經(jīng)測試,上線。一切又回到了美好時光。

隨著時光的流逝,業(yè)務的增加,后端童靴發(fā)現(xiàn)Order類里面如下 demo:

phppublic function create($params)
{
    $member = app::get("b2c")->model("members")->get_current_member();

    // 登錄驗證
    if (empty($member)) {
        return array("code" => "00008");
    }

    // 實際業(yè)務處理....    
}

public function getOrderList($params)
{
    $member = app::get("b2c")->model("members")->get_current_member();

    // 登錄驗證
    if (empty($member)) {
        return array("code" => "00008");
    }

    // 實際業(yè)務處理....    
}

public function getOrderDetail($params)
{
    $member = app::get("b2c")->model("members")->get_current_member();

    // 登錄驗證
    if (empty($member)) {
        return array("code" => "00008");
    }

    // 實際業(yè)務處理....    
}

// ...

這都是什么玩意............ 然后開始封裝,稍微好了點

又過了一段時間,有人過來說創(chuàng)建訂單還需要優(yōu)化體驗,
點擊創(chuàng)建訂單提示如下:

超過最大購買量——給出提示,繼續(xù)留在創(chuàng)建訂單頁

該商品已賣光或已下架——引導用戶去商品列表頁

這時,前端童鞋告訴后端童鞋,商品下架的時候,你也應該返回一個狀態(tài)碼。

后端童鞋開始打算添加 code,發(fā)現(xiàn)如下 demo

phpkernel::single("sysapi_ecoupon_order")->create($params, $msg);

這里的提示信息是 $msg 返回的,用戶登錄外部可以提前檢測,這里的商品能否購買要實現(xiàn)添加 code也需要提前檢測,將來要是需要添加類是功能豈不是...... 每需要一個精確的 code返回出去,這里就需要添加檢測,這里代碼將會變得無法直視。
況且這里本該在業(yè)務里面檢測,一切不那么友好起來了。

再次思考,代碼寫的不爽了,一定是哪里不對

問題所在

開始懷疑 public function create($params, & $msg) { } 這里不應該是通過 & $msg 來作為 調(diào)用者與 被調(diào)用者之間的 錯誤信息通信約定,一切的問題都出在了這里。錯誤消息向上傳播的約定不合適

如果這里約定的是 code作為錯誤向上傳播一切的問題即將不復存在。在調(diào)用業(yè)務方法之前的檢測代碼就都可以去掉了,代碼簡約,一切又美好起來。

接下來繼續(xù)思考,使用 code作為業(yè)務處理失敗消息傳遞問題又來了

現(xiàn)在已有的業(yè)務代碼都是如此定義public function create($params, & $msg),怎樣更加友好的替換成 code

如果使用 code,code只能服務器端 與 前端約定的一個具有唯一性的標識(code 比 msg 對國際化的實現(xiàn)更加容易)但是并不能直接展示給用戶,那么就需要定義每個 code 的代表的意義 與 對應的提示信息。那么問題來了,code 應該已怎樣規(guī)范來定義所代表的含義

再來看如下常用的兩種方法定義:

public function create($params, & $msg)

public function create($goodsId, $num, & $msg)

第一種方式,參數(shù)通過一個 $params數(shù)組傳遞過來,方法內(nèi)部在把錯誤提示放到 $msg中。

好處:$params是個數(shù)組,里面參數(shù)可以任意添加

缺點:該方法調(diào)用者在外部不能知道該方法需要什么參數(shù),必須來看該方法內(nèi)部實現(xiàn),做出對應的數(shù)組 key的轉(zhuǎn)換(如: user_id 轉(zhuǎn) userId)。方法調(diào)用者 與 方法實現(xiàn) 極度耦合。維護成本大、出Bug系數(shù)高

第二種方式,按基本類型分別傳遞單個參數(shù)

好處:方法調(diào)用者根據(jù)方法定義就能夠知道方法具體需要的參數(shù),調(diào)用方法時不需要作 key轉(zhuǎn)換,只需要傳遞對應的參數(shù)即可

缺點:參數(shù)數(shù)目過多時,慘不忍睹

這里有如下問題:

這里如何已一種更加容易維護,擴展的方式來處理(Java里面方法參數(shù)已對象的方式傳遞可以借鑒

這里的& $msg 真的合適嗎,如果是第二種方式定義的方法,以后擴展個 $phone 該如何處理?public function create($goodsId, $num, & $msg, $phone="")這樣么?怎么看怎么蛋疼

再來看不通過 & $msg傳遞錯誤信息之后的代碼

phppublic function create($goodsId, $num)
{
    if ( ? ) {
        // 返回狀態(tài)碼
        return "0001";
    }
    if ( ? ) {
        // 返回狀態(tài)碼
        return "0002";
    }
    // 創(chuàng)建訂單
    // ...
    // 返回訂單信息
    return $order;
}

看似實現(xiàn)了,但是方法調(diào)用者,怎么調(diào)用怎么蛋疼,一會返回狀態(tài)碼,一會返回訂單信息,完全兩種類型。

綜合以上問題:

得出以下結論:

業(yè)務處理失敗消息要以 code 的方式向上傳遞給調(diào)用者

業(yè)務處理失敗消息以參數(shù)的方式傳遞不是很適合,并且不能以 return的方式返回

再次思考,最終從 Java里面想到了一點思路(幸好是 Java出身。疑問:為何面試的時候 Java的工作經(jīng)驗都不算在 PHP工作經(jīng)驗里呢,并沒有因此而加分)

解決方案:

自定義一個異常類,包括 codo屬性 和 msg 屬性

凡是遇到業(yè)務不能正常處理的時候就創(chuàng)建一個異常對象,設置對應的 code 或者 msg屬性(為了減少 code泛濫,這里的 code 與 msg 可以2選一,如果前端需要做精準的處理,就設置 code,如果只是為了給用戶提示,就只返回 msg,則可以減少一個 code),然后拋出異常

方法調(diào)用者在外部統(tǒng)一捕捉該異常,如 接口的統(tǒng)一入口出口的方法內(nèi)部處理

  

因個人工作時間、項目經(jīng)歷不多、歸根結底經(jīng)驗不足?,F(xiàn)在將該方案寫下來,還望有經(jīng)驗的大神拍磚,以免給團隊挖坑,以上 $msg 就是 N久以前埋下的坑。

該文章發(fā)布在自己站點地址:http://www.webdevs.cn/article/91.html

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/20921.html

相關文章

  • 騰訊云分布式高可靠消息隊列CMQ架構最佳實踐

    摘要:是騰訊云內(nèi)部自研基于的高可靠強一致可擴展分布式消息隊列,在騰訊內(nèi)部包括微信手機業(yè)務紅包騰訊話費充值廣告訂單等都有廣泛使用。目前已上線騰訊云對外開放,本文對核心技術原理進行分享介紹。 ? 極牛技術實踐分享活動 極牛技術實踐分享系列活動是極牛聯(lián)合頂級VC、技術專家,為企業(yè)、技術人提供的一種系統(tǒng)的線上技術分享活動。 每期不同的技術主題,和行業(yè)專家深度探討,專注解決技術實踐難點,推動技術創(chuàng)新,...

    Ku_Andrew 評論0 收藏0
  • 馬蜂窩火車票系統(tǒng)服務化改造初探

    摘要:為了幫助用戶更好地完成消費決策閉環(huán),馬蜂窩上線了大交通業(yè)務?,F(xiàn)在,用戶在馬蜂窩也可以完成購買機票火車票等操作。第二階段架構轉(zhuǎn)變及服務化初探從年開始,整個大交通業(yè)務開始從架構向服務化演變。 交通方式是用戶旅行前要考慮的核心要素之一。為了幫助用戶更好地完成消費決策閉環(huán),馬蜂窩上線了大交通業(yè)務?,F(xiàn)在,用戶在馬蜂窩也可以完成購買機票、火車票等操作。 與大多數(shù)業(yè)務系統(tǒng)相同,我們一樣經(jīng)歷著從無到有...

    Raaabbit 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<