摘要:綜合以上問題得出以下結論業(yè)務處理失敗消息要以的方式向上傳遞給調(diào)用者業(yè)務處理失敗消息以參數(shù)的方式傳遞不是很適合,并且不能以的方式返回再次思考,最終從里面想到了一點思路幸好是出身。
場景:創(chuàng)建訂單 實際流程:我需要拍磚 和 看見你們的意見,為團隊少挖坑
業(yè)務處理類動作:終端調(diào)用(PC端、移動端APP、微信端、Web端)-->控制器 或 接口-->實際的業(yè)務處理-->控制器 或 接口-->終端做出相應處理(控制器可能是渲染對應頁面; 接口返回 JSON數(shù)據(jù))
檢查用戶是否登陸
驗證商品 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
摘要:是騰訊云內(nèi)部自研基于的高可靠強一致可擴展分布式消息隊列,在騰訊內(nèi)部包括微信手機業(yè)務紅包騰訊話費充值廣告訂單等都有廣泛使用。目前已上線騰訊云對外開放,本文對核心技術原理進行分享介紹。 ? 極牛技術實踐分享活動 極牛技術實踐分享系列活動是極牛聯(lián)合頂級VC、技術專家,為企業(yè)、技術人提供的一種系統(tǒng)的線上技術分享活動。 每期不同的技術主題,和行業(yè)專家深度探討,專注解決技術實踐難點,推動技術創(chuàng)新,...
摘要:為了幫助用戶更好地完成消費決策閉環(huán),馬蜂窩上線了大交通業(yè)務?,F(xiàn)在,用戶在馬蜂窩也可以完成購買機票火車票等操作。第二階段架構轉(zhuǎn)變及服務化初探從年開始,整個大交通業(yè)務開始從架構向服務化演變。 交通方式是用戶旅行前要考慮的核心要素之一。為了幫助用戶更好地完成消費決策閉環(huán),馬蜂窩上線了大交通業(yè)務?,F(xiàn)在,用戶在馬蜂窩也可以完成購買機票、火車票等操作。 與大多數(shù)業(yè)務系統(tǒng)相同,我們一樣經(jīng)歷著從無到有...
閱讀 563·2021-11-25 09:44
閱讀 2651·2021-11-24 09:39
閱讀 2325·2021-11-22 15:29
閱讀 3536·2021-11-15 11:37
閱讀 3404·2021-09-24 10:36
閱讀 2530·2021-09-04 16:41
閱讀 1010·2021-09-03 10:28
閱讀 1877·2019-08-30 15:55