1. 程式人生 > >業務代碼解構利器--SWAK

業務代碼解構利器--SWAK

技術分享 通過 劃分 解決沖突 art ali 處理 情況 掃描

摘要: 作者:閑魚技術-紫思 簡介 業務的不斷發展、商品類型的不斷增多、不斷添加的業務需求使得閑魚的代碼出現“bad smell”——平臺代碼和業務代碼耦合嚴重難以分離;業務和業務之間代碼交織缺少拆解。這也是行業中的通病。

作者:閑魚技術-紫思

簡介
業務的不斷發展、商品類型的不斷增多、不斷添加的業務需求使得閑魚的代碼出現“bad smell”——平臺代碼和業務代碼耦合嚴重難以分離;業務和業務之間代碼交織缺少拆解。這也是行業中的通病。為解決此類問題,閑魚自研了一套技術框架——SWAK。本文帶大家一起看看SWAK是怎麽解構閑魚代碼的。

SWAK是Swiss Army Knife的簡稱,眾所周知,瑞士×××是一款小巧靈活、適用於多種場景的工具。在閑魚服務端,SWAK框架也是這樣一種小巧靈活、適用於多種場景的技術框架, 它所要使用的場景都具有同一個特點——多實現間的規則化執行。本文將以一個例子開篇,來詳細介紹其中的概念。

多實現和規則化執行
熟悉閑魚的朋友們應該知道,在閑魚App裏面,商品有豐富的表現形式,不妨叫做類型A、類型B和類型C,各種類型也可以有各自的子類型。每種類型的業務邏輯存在一定的共性,但是也存在部分差異——如在分享頁面中,subtitle字段的展示邏輯就不盡相同:

這種單一的實現通常會被寫成如下的代碼:

if(A類型) {
if(A1類型) {
doSomething1();
}else if(A2類型) {
doSomething2();
}
} else if(B類型) {
doSomething3();
} else if(C類型) {
if(C1類型) {
doSomething4();
}else if(C2類型) {

doSomething5();
}
}
類似的代碼大家應該都寫過不少。邏輯簡單的時候寫成這樣無可厚非,但當邏輯開始變復雜的時候這種寫法會具有較多的壞處:

難以抽出公共的邏輯,代碼塊愈發臃腫。
有較多相同點少量異同點的新類型的實現很難復用原先的代碼。
各個類型的代碼實際上融合在一塊,更改代碼可能會影響到其他類型,提高上線風險和測試回歸成本。
對於新接手的開發人員來說,理解成本高,上手難度大,無形中降低開發效率。
按照面向對象的思想,獲取title的方式對於所有類型都是一致的,應該沈澱成平臺邏輯,而獲取subtitle就可以抽象成一個接口方法,而類型A、類型B和類型C的寶貝都具有各自的實現而已。對於 獲取subtitle這個接口方法來說,它有著多種實現。

那麽什麽是規則化執行呢?在上面的例子中,我們按照了商品的類型(type)進行了邏輯的分離,但通常情況下並非能分隔地如此徹底。舉一個例子,運營團隊的劃分可能也按照商品類型(type)做劃分,也有可能按照類目(category,如手機、3C數碼、服飾、圖書等)體系來做劃分,甚至還有可能按照地域進行劃分。那麽一個商品可能既會受到商品類型體系的約束,又會受到類目體系的約束,還會受到地域的約束。如果幾種約束不一致的話,就會產生沖突。比如subtitle字段,從類型A的視角上來看應該顯示價格,在圖書類目的視角下或許應該透出出版社——畢竟愛讀書的人大多更關註質量而出版社是衡量質量的一個重要標準。是展示價格,還是出版社?或者都展示?如果都展示的話先展示價格還是先展示出版社?如果一行不夠放下所有內容又怎麽辦?無論是上述的哪一種展示方式,背後都是“規則”(在設計模式裏,稱之為“策略”),代碼也無非是按照“規則”進行編寫而已。

以上的例子是多實現規則化執行的一個經典場景。類似地,如ABTest、雙寫等邏輯也是多實現規則化執行的應用場景。

基本思想
在上面的例子中,按照商品的類型或者按照商品的類目進行區分會產生沖突。其實無所謂類型或者類目,對於商品這個對象來說,無非是給其貼上了不同的標簽而已——如一個類型A的圖書類目寶貝被貼上“類型A”和“圖書”兩個標簽。“類型A”的獲取subtitle接口方法對應著一種實現,而“圖書”的獲取subtitle接口方法又對應著另一個實現。當一個對象被貼多個標簽的時候,多個標簽對應的實現就會產生沖突。

沖突的解決依賴於“規則”。“規則”最重要的兩個部分是——優先級(Priority)和歸約(Reduce)策略;執行的先後順序由優先級決定,而顯示第一個實現的結果、顯示第二個實現的結果還是兩個實現結果的拼接等都是歸約策略。“規則”還可以包含如“並行執行方式”和“異常處理方式”等其他組成部分。

如上,可以得出SWAK的基本思想:

分析對象所具有的標簽。
分離出不可變的邏輯和可變的邏輯。可變的邏輯抽象成接口。
可變的邏輯根據標簽的不同有多種實現。每種實現是獨立的,即每種實現是互相隔離的。
當對象同時具有多個標簽時,使用優先級和歸約策略來解決沖突問題。
值得一提的是,SWAK的基本思想借鑒自阿裏巴巴中臺的TMF架構,關於TMF的細節可以參考《盡在雙11--阿裏巴巴技術演進與超越》一書的《基於TMF框架的交易平臺架構》章節。

相應地,使用SWAK框架將帶來如下的好處:

代碼邏輯清晰,可變和不可變一目了然。
代碼復用度變高。
可變邏輯按照標簽進行隔離,單個標簽的實現不會影響到其他標簽的實現,降低開發和測試成本。無論是按照“類型”分還是按照類目分,對應的開發和測試同學只需要關註對應的邏輯即可。
新接手的開發人員能夠快速理解,輕松上手。
實現原理
相較於運行期才進行根據標簽去掃描並加載實現類的方式,SWAK框架更傾向於在靜態期就能分析出具有某幾個標簽的對象在不同的實現方法下會有著怎樣的執行邏輯。一方面通過緩存可以明顯降低響應時間,另一方面也便於在開發期間發現和排查問題。整體的實現原理可以分成兩個部分:註冊 和 執行。基本流程如下:

技術分享圖片

在註冊過程中,SWAK框架將會掃描文件(多實現接口、歸約策略、沖突優先級采用了Java註解或者XML文件進行了配置,下面的代碼示例中介紹多實現接口和其實現類是如何配置的),掃描出的結果都註冊到了本地緩存中,而在執行過程中SWAK框架會從本地緩存中直接查找其所需的沖突優先級配置和歸約策略等,這樣有助於減少響應時間。另外,使用統一的本地緩存有助於進行“可視化的展現”——開發人員可以直觀地看到並分析出程序的執行流程;產品經理也可以直觀地看到哪些功能點可以方便擴展,哪些地方的優先級需要更新等等,甚至有助於需求的估時和排期。使用統一的本地緩存也為“可視化的配置”提供了可能性,結合阿裏內部的Diamond或者Switch框架(輕量級的開關和動態配置項管理框架),可以無需更新代碼,僅需推送配置就可以更新沖突優先級,為開發和測試提供了極大的便利。

/**

  • 此處用一個簡單的demo演示下基本的配置,實際的業務要遠比demo復雜
    */
    @SwakInterface(desc="獲取subtitle") // 使用註解聲明這是一個多實現接口
    public interface SubtitleFetcher {@SwakMethod
    br/>@SwakMethod
    }

@SwakTag(tags = {"tagA"}) // 使用SwakTag綁定tagA的實現@Component
br/>@Component
br/>@Override
return "我是TagA";
}
}

@Component
@SwakTag(tags = {"tagB"}) // 使用SwakTag綁定tagB的實現
public class TagBSubtitleFetcher implements SubtitleFetcher {@Override
br/>@Override
return "我是TagB";
}
}
閑魚服務端應用基本都基於Spring框架。為了便於在服務端應用上使用SWAK框架,在設計之初,我們就要求SWAK需要100%地兼容Spring框架。最終的實現版本做到了這一點,無論是業務的bean還是SWAK框架自身引入的bean,都完全由Spring容器托管。框架還使用了cglib代理了上圖裏執行過程中的一系列流程,完全由框架執行,對開發同學是完全透明、無感知的,使用起來如普通的單實現的接口一般,如下代碼塊所示。

@Autowired
private SubtitleFetcher subtitleFetcher;

//省略大段代碼.......

String subtitle = subtitleFetcher.fetchSubtile();
//省略大段代碼.......
在閑魚的應用情況
目前,SWAK框架在閑魚已經在商品發布和編輯的部分流程上得以應用,我們正在積極將SWAK框架擴展到到更多的流程上。下圖是基於SWAK框架的商品域核心功能的改造計劃。經過基於SWAK的升級改造,閑魚商品域核心功能按照業務隔離,各業務開發同學僅需關系其對應業務的開發即可,其通用邏輯和業務隔離由基於SWAK框架的一層和二層充分保證。代碼質量和開發效率將獲得顯著提升。

技術分享圖片

總結
閑魚自研的SWAK這一多實現規則化執行框架,可以很好地解決平臺代碼和業務代碼耦合嚴重難以分離、業務和業務之間代碼交織缺少拆解的問題。並且SWAK 100%兼容Spring,使用方便,快速上手。名副其實地,SWAK框架就像瑞士×××一樣可以適用於多種場景,小巧方便。當然,SWAK仍在不斷進化,特性和功能仍在不斷豐富。類似地,在閑魚還有很多有意思的、創造性的嘗試。如果對此感興趣,歡迎加入我們。簡歷投遞:**[email protected]
br/>簡歷投遞:**[email protected]

原文鏈接

本文為雲棲社區原創內容,未經允許不得轉載。

業務代碼解構利器--SWAK