業務代碼解構利器--SWAK

做者:閒魚技術-紫思設計模式

簡介

業務的不斷髮展、商品類型的不斷增多、不斷添加的業務需求使得閒魚的代碼出現「bad smell」——平臺代碼和業務代碼耦合嚴重難以分離;業務和業務之間代碼交織缺乏拆解。這也是行業中的通病。爲解決此類問題,閒魚自研了一套技術框架——SWAK。本文帶你們一塊兒看看SWAK是怎麼解構閒魚代碼的。緩存

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

多實現和規則化執行

熟悉閒魚的朋友們應該知道,在閒魚App裏面,商品有豐富的表現形式,不妨叫作類型A、類型B和類型C,各類類型也能夠有各自的子類型。每種類型的業務邏輯存在必定的共性,可是也存在部分差別——如在分享頁面中,subtitle字段的展現邏輯就不盡相同:
圖片1框架

這種單一的實現一般會被寫成以下的代碼:ide

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的視角上來看應該顯示價格,在圖書類目的視角下或許應該透出出版社——畢竟愛讀書的人大多更關注質量而出版社是衡量質量的一個重要標準。是展現價格,仍是出版社?或者都展現?若是都展現的話先展現價格仍是先展現出版社?若是一行不夠放下全部內容又怎麼辦?不管是上述的哪種展現方式,背後都是「規則」(在設計模式裏,稱之爲「策略」),代碼也無非是按照「規則」進行編寫而已。fetch

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

基本思想

在上面的例子中,按照商品的類型或者按照商品的類目進行區分會產生衝突。其實無所謂類型或者類目,對於商品這個對象來講,無非是給其貼上了不一樣的標籤而已——如一個類型A的圖書類目寶貝被貼上「類型A」和「圖書」兩個標籤。「類型A」的獲取subtitle接口方法對應着一種實現,而「圖書」的獲取subtitle接口方法又對應着另外一個實現。當一個對象被貼多個標籤的時候,多個標籤對應的實現就會產生衝突。spa

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

如上,能夠得出SWAK的基本思想:

  • 分析對象所具備的標籤。
  • 分離出不可變的邏輯和可變的邏輯。可變的邏輯抽象成接口。
  • 可變的邏輯根據標籤的不一樣有多種實現。每種實現是獨立的,即每種實現是互相隔離的。
  • 當對象同時具備多個標籤時,使用優先級和歸約策略來解決衝突問題。

值得一提的是,SWAK的基本思想借鑑自阿里巴巴中臺的TMF架構,關於TMF的細節能夠參考《盡在雙11--阿里巴巴技術演進與超越》一書的《基於TMF框架的交易平臺架構》章節。

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

  • 代碼邏輯清晰,可變和不可變一目瞭然。
  • 代碼複用度變高。
  • 可變邏輯按照標籤進行隔離,單個標籤的實現不會影響到其餘標籤的實現,下降開發和測試成本。不管是按照「類型」分仍是按照類目分,對應的開發和測試同窗只須要關注對應的邏輯便可。
  • 新接手的開發人員可以快速理解,輕鬆上手。

實現原理

相較於運行期才進行根據標籤去掃描並加載實現類的方式,SWAK框架更傾向於在靜態期就能分析出具備某幾個標籤的對象在不一樣的實現方法下會有着怎樣的執行邏輯。一方面經過緩存能夠明顯下降響應時間,另外一方面也便於在開發期間發現和排查問題。總體的實現原理能夠分紅兩個部分:註冊和 執行。基本流程以下:

圖片2

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

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

@SwakTag(tags = {"tagA"}) // 使用SwakTag綁定tagA的實現
@Component
public class TagASubtitleFetcher implements SubtitleFetcher {
    @Override
    public String fetchSubtitle() {
        return "我是TagA";
    }
}

@Component
@SwakTag(tags = {"tagB"}) // 使用SwakTag綁定tagB的實現
public class TagBSubtitleFetcher implements SubtitleFetcher {
    @Override
    public String fetchSubtitle() {
        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框架的一層和二層充分保證。代碼質量和開發效率將得到顯著提高。

圖片3

總結

閒魚自研的SWAK這一多實現規則化執行框架,能夠很好地解決平臺代碼和業務代碼耦合嚴重難以分離、業務和業務之間代碼交織缺乏拆解的問題。而且SWAK 100%兼容Spring,使用方便,快速上手。名副其實地,SWAK框架就像瑞士軍刀同樣能夠適用於多種場景,小巧方便。固然,SWAK仍在不斷進化,特性和功能仍在不斷豐富。相似地,在閒魚還有不少有意思的、創造性的嘗試。若是對此感興趣,歡迎加入咱們。 簡歷投遞:**guicai.gxy@alibaba-inc.com

相關文章
相關標籤/搜索