安居客 Android App 走向平臺化

首發於微信公衆號:BaronTalk前端

安居客 Android App 距離上次的模塊化/組件化重構已經兩年多了,重構以後很好的支撐了兩年多以來的業務發展。但這個世界老是在向前走的,沒有任何一種架構可以一勞永逸的解決全部問題,外部環境的不斷變化相應的也要求項目架構作出改變,以此來應對環境變化所帶來的挑戰。java

本文分享的就是咱們安居客 App 團隊此次向平臺化轉型的背景、轉型過程當中所面臨的問題、挑戰、咱們的解決方案以及我我的在這個過程當中的收穫和感悟。git

一. 背景

自 18 年以來的市場環境你們都知道,各大公司都在縮減開支、提高組織效率,但願用更少的投入帶來更多的產出,以此來應對經濟下行帶的不肯定性。在這個大背景下,集團在 18 年末作出了一系列人效提高、業務整合的動做。github

拿房產業務舉例:58 App 裏的房產業務以前是由北京的房產團隊開發的,而整個安居客 App 是由我所在的上海安居客團隊開發的。在此次調整以後,北京的房產團隊做爲一條垂直業務線來負責 58 App 和安居客 App 中的租房業務的開發,安居客團隊則繼續負責整個安居客 App(包含新房、二手房、內容、IM 等業務)的開發,同時還要開發 58 App 中二手房、新房、房產大內容等業務。小程序

這樣一次調整給咱們帶來了三大挑戰:後端

  1. 在人力不變,工做量翻倍的狀況下,咱們要如何保證業務的迭代速度不受影響?
  2. 由以往的「單兵做戰」變成了跨團隊跨地域協做開發,咱們要如何做爲一個平臺方來和業務方協做開發?
  3. 對於 58 App 而言咱們是業務方,對於北京房產團隊而言咱們是平臺方,咱們要如何同時處理好雙重角色?

面對這些挑戰咱們須要轉變開發思惟、改進項目架構。微信

**一次項目重構和架構升級,不僅是要解決當下的問題,更要爲將來一到兩年的業務發展提供支持。**爲了解決這一系列的問題,咱們聯合 58 無線團隊、58 房產團隊、前端、後端多個團隊的同窗一塊兒發起了「木星計劃」,也開啓了咱們的平臺化轉型之路。網絡

二. 問題、挑戰及解決方案

當公司的業務調整政策下來之後,團隊面臨的最急迫的一個選擇是繼續在 58 App 上維護老的房產代碼,迭代新功能;仍是將安居客現有業務搬遷到 58 App 實現一套代碼在兩個 App 裏運行呢?架構

  • 前者咱們須要分一半的人力去開發 58 App,這必然致使團隊的需求消化量減半,業務迭代速度受影響。好處是暫時不用作任何技術上的改造。app

  • 後者須要咱們協調 58 無線、58 房產、先後端等多個團隊一塊兒對 App 作一次「大手術」,同時還須要說服產品團隊容忍改造期間業務迭代速度的放緩。好處是可以一次性將安居客上的房產業務搬遷到 58 App 上,後續咱們只需針對房產業務作一次開發就能跑在兩個 App 上,用一份人力作了兩份的活,開發效率翻倍。

爲長遠計,咱們最終選擇了後者。但是要作到一套代碼雙端運行並不容易,58 App 和安居客 App 隸屬於北京、上海兩個不一樣的團隊開發,你們底層庫不同,技術方案不同,開發模式也不同,要達到咱們的目的必然要費一番功夫。接下來我從總體到局部逐步介紹咱們在平臺化演進過程當中的設計思路、遇到的問題和解決方案

2.1 總體設計

所謂平臺化,就是安居客 App 要做爲一個平臺來對平臺上承載的各類垂直業務提供服務,每一個服務都須要對上層提供標準化的接口來支撐平臺上各種垂直業務的功能。

安居客App平臺
這一次的項目重構除了要轉型平臺型 App 支持其餘業務的接入和將來業務的發展,還有更重要一點是要作到一套代碼在 58 和安居客雙平臺運行。

要作到這一點,在現有的業務體系和代碼體量下雖然工做量巨大,但大的思路確是很清晰簡單的:

  • 底層庫能統一的儘可能統一;
  • 短期內沒法統一的庫以及平臺特性經過中間層屏蔽平臺差別。

安居客 App 架構調整

針對安居客 App ,咱們須要調整架構,引入一個平臺中間層並針對平臺中間層接口作安居客 App 側的實現,並將垂直業務中本來調用平臺接口的地方改成調用中間層接口。同時將以前的業務組件層細分爲「平臺級組件」和「業務級組件」,全部垂直業務再也不依賴平臺級組件,只依賴平臺中間層業務級組件,並明確業務代碼遷移的邊界。

安居客App架構變化
#### 58 App 架構調整

同時 58 無線團隊的同窗也改進了他們的架構,和咱們同樣引入了平臺中間層及中間層在 58 App 上的實現,保證安居客業務遷移進來後能正常編譯運行。

58App架構變化
上面這兩張架構圖呈現了兩個 App 架構調整的大方向,具體作了哪些、遇到了哪些問題我在下面的小節裏一一介紹。

2.2 平臺中間層屏蔽底層差別

計算機領域的任何問題均可以添加一箇中間層來解決。58 App 和安居客 App 做爲兩個不一樣的平臺,對業務層提供的能力是不同的,接口、方法名都是不同的。同一塊業務代碼要跑在兩個不一樣的平臺,必然要引入一箇中間層來抹平差別、屏蔽底層細節,同時對外提供統一的接口供業務層調用。

所以 58 無線團隊、58 房產團隊和咱們安居客團隊三方協商,共同制定了一套平臺中間層 API,而後兩個平臺再針對平臺中間層 API 作具體實現。

平臺中間層設計及示例

爲了便於後期管理、劃清代碼邊界,咱們將平臺中間層服務進一步細化,根據平臺差別性將中間層劃分爲平臺公共服務、安居客平臺特有服務、58 平臺特有服務等。以 Java Package 做爲區分,劃分到不一樣的包結構下。一旦後期某一特有服務變成了公共服務,則將其往平臺公共服務遷移。

平臺中間層服務劃分

在實現上,平臺中間層會提供一系列 Service 接口供垂直業務調用,同時提供一個 PlatFormServiceRegistry 類用來註冊和獲取服務。

public class PlatFormServiceRegistry {

    ...

    /** * 註冊服務 */
    private void registService(Class serviceInterface, Class<? extends IService> serviceImpl) {
        if (serviceInterface != null && serviceImpl != null ) {
            classMap.put(serviceInterface.getName(), serviceImpl);
        }
    }


    /** * 獲取服務 */
    private <T> T getService(Class<? extends T> service) {
        
				···
          
        IService instance = serviceImplMap.get(service.getName());
        if (null == instance) {
            try {
                Class<? extends IService> serviceClass = classMap.get(service.getName());
                if (serviceClass != null) {
                    instance = serviceClass.getConstructor().newInstance();
                    serviceImplMap.put(service.getName(), instance);
                }
            } catch (Exception e) {
                Log.d(TAG, e.toString());
            }
        }
        return (T) instance;
    }
}
複製代碼

在使用方式上,平臺方首先要註冊服務

//註冊平臺服務
PlatFormServiceRegistry.registeAppInfoService(AjkAppInfoServiceImpl.class);
複製代碼

業務方在使用服務的時候獲取到對應的 Service 就能夠調用相關方法了。

//使用平臺服務
IAppInfoService appInfoService = PlatFormServiceRegistry.getAppInfoService();
appInfoService.getAppName(context);
複製代碼

2.3 統一 HybridSDK 解決雙平臺 H5 交互問題

安居客 App 因爲歷史緣由,Android 和 iOS 在與 H5 的交互協議上有不少不同(雖而後期統一過 JSBridge 協議,但不少歷史遺留協議仍舊是不一致的),58 App 上的 Native 和 JS 交互協議更是和安居客不一致。爲了解決這些問題咱們須要 Android 和 iOS、58 和 安居客有一個統一的 Native 與 JS 的交互協議;同時爲了兼容歷史協議,讓業務平穩過渡,咱們還須要設計一套過渡方案。

在未實現協議統一的狀況下,一個 H5 頁面要上 58 App 和安居客 App 兩個平臺,須要支持兩套協議,再加上安居客以前 Android、iOS 協議的不一致,一個 H5 頁面最多可能須要支持 4~5 套協議。

爲了實現協議的最終統一,而且讓業務平穩過渡,咱們引入了一套過渡方案。在保留兩個平臺現有協議和 JSBridge SDK 的狀況下,58 無線團隊的同窗設計並開發了一個全新的 HybridSDK,過渡階段三套協議並存,來不及調整的舊業務使用舊協議,新開發及本次要調整的業務使用新協議。

而後隨着業務的迭代,不斷廢棄兩個平臺的自有協議,最終走向統一。

中間層設計

2.4 統一路由協議、API 動態下發路由解決頁面交互問題

現有 App 內的頁面跳轉要麼是 intent 跳轉,要麼是寫死的路由跳轉。在此次的平臺化改造過程當中,咱們從 58 App 上也學到了不少東西,其中動態路由下發就是咱們學習並引入到安居客 App 中的。

簡單的說就是 App 給各個頁面定義好路由協議,App 在調用 API 的時候返回結果中會包含當前頁面跳轉到下一頁面的路由協議,這就是所謂的動態路由下發。這樣作會帶來三個好處:

  1. 能夠作到完善的降級策略,好比當線上的房源詳情頁出現了大面積的 Crash,API 能夠返回一個 H5 頁面的路由協議,臨時用 H5 的房源詳情頁替代;同時 App 上線 HotFix,等 HotFix 覆蓋率達到必定程度後 API 再改回下發Native 路由,跳回 Native 頁面;
  2. 能夠支持新功能的效果驗證,利用 H5 和 Native 自由切換這一特性,能夠在不發版的狀況下驗證新功能的數據效果。好比要上線驗證某個改動或者某個新功能的效果,以前須要 App 發版,如今只須要作一版 H5 頁面,API 直接路由到這個 H5,若是驗證下來效果好則能夠開發對應的 Native 頁面,很差則能夠再嘗試其餘方案;
  3. 能夠支持平臺化改造過程當中的灰度上線,這一點放到下一小節詳細說明。

2.5 灰度策略保證上線後的穩定性

咱們此次的平臺化改造,不管對安居客 App 仍是 58 App 來講都是一次「大手術」,術後可否保證線上的穩定性、業務數據不受影響是很是重要的。就拿把安居客業務遷移到 58 App 這件事來講,若是一股腦的用安居客遷移過去的房產業務代碼替代 58 App 內的房產業務代碼,就算咱們在技術上作到了絕對的穩定,也難保業務數據不會受影響。

好在得益於上面提到的動態路由下發方案,咱們能夠作到在少許城市、少許用戶上作灰度,讓這部分人先試用安居客遷移過去的業務,其它用戶繼續使用老的房產業務,數據效果好再逐步加量,直到徹底替代。這樣就能最大限度的下降影響,保證上線後的穩定性。

2.6 業務平移帶來的包大小問題

雖然在上一次的模塊化/組件化改造過程當中咱們對各項垂直業務作了拆分、解耦,可是各業務仍是有不少重疊的業務,因而咱們將這些業務下沉到 CommonBusiness 組件中,同時這個 CommonBusiness 組件裏還包含了一些 App 平臺級別的基礎功能,所以這個 CommonBusiness 組件成了個大而全的東西。

在此次的架構調整中,咱們爲了實現業務的快速平移,將 CommonBusiness 和新房、二手房等幾條垂直業務線的代碼一股腦的遷移進了 58 App,這就直接致使了 58 App 體積的快速膨脹。因而在後期,咱們將 CommonBusiness 按能力拆分紅了多個獨立的組件,而且分爲了「平臺級組件」和「業務級組件」。平臺級組件屬於安居客平臺特有,不隨業務遷移;業務級組件屬於多個垂直業務公用的組件,隨業務代碼一塊兒遷移到 58 App。這一點在前面的架構圖中有體現。

2.7 持續演進

前面介紹中間層的時候提到,還有一部分底層庫暫時沒法統一,現階段是經過引入中間層來解決的。但從長遠來看,整個集團無線體系下,依賴的底層庫仍是要走向統一。就拿分享組件來講,現階段安居客和 58 都是使用本身的 ShareSDK,而後中間層定義了一套分享接口,兩個 App 分別調用本身的 ShareSDK 來實現接口知足業務的分享需求。爲了進一步下降開發成本,避免重複造輪子,後期雙方還須要統一使用同一個 ShareSDK,拋棄中間層。最終整個集團體系下全部的 App 的架構應該以下面這張圖所示:

中間層設計
統一的平臺層,不一樣的宿主搭配上不一樣的垂直業務,就是不一樣的 App。這一點還須要咱們持續迭代才能作到。

三. 收穫和感悟

整個木星計劃下來,我的有不少的收穫和感悟。說實話,此次的技術改造在技術上並無太大的難度,更談不上有什麼「黑科技」。改造能順利落地,更多的對於全局的把控、資源的協調溝通以及各個兄弟團隊的積極配合。因此這裏拋開技術不談,談談個人幾點收穫:規範化、流程化和全局視角。

3.1 規範化、流程化

安居客 Android App 團隊在技術上過往基本都屬於小團隊做戰,不多有跨團隊、跨地域協同開發的經驗,也缺乏和集團其它團隊的交流,所以規範和流程一直是咱們團隊所欠缺的。

在以前的小團隊開發模式下,就這麼一畝三分地,想怎麼玩都行,怎麼方便怎麼來。可是這種方式一旦涉及到跨地域跨團隊的協做時就會遇到瓶頸。

好比北京租房團隊的需求開發完要集成進安居客,按照咱們單純的想法,定個時間點提交代碼給咱們就 OK 了,但實際狀況是這種方式根本行不通。業務方何時開發完、測試完、何時交付給咱們?業務集成的交付標準是什麼?平臺方測試和業務方測試如何配合、如何交接?業務代碼是以源碼方式集成仍是 aar 方式集成等等這些都是問題,須要有一套標準化、流程化的規範來約束各方的行爲,這樣才能保證項目順利上線。

像上面這樣的例子還有不少,我這裏就不一一列舉了。

3.2 全局視角

正所謂**「不謀全局者,不足謀一域」**,本次平臺化改造過程當中個人另一個重大收穫是讓我意識到要以全局視角去看到問題。

前面提到咱們在規範和流程上有不少欠缺,不少問題單從自身沒法解決,這促使我跳出本身的圈子來思考問題。咱們作 App 開發的同窗每每容易把視角侷限於本身負責的一個頁面、一個功能模塊、一個業務,能站在整個 App 的角度看待問題的已經寥寥無幾了,更別提跳出 App 的視角來看待問題。

但缺乏全局視角,不少事情就不能很好的完成。舉個例子,假設你接到了一個優化頁面響應速度的任務,若是你單從 App 的角度入手你會發現能作的頗有限,當你一通操做把 App 的優化點作完了卻發現中臺部門提供的 SDK 方法耗時兩秒,API 返回數據耗時三秒,真的是一頓操做猛如虎,一看結果二百五

上面提到的這個例子還只是最多見、最基礎的一點。真正的全局視角是要求咱們跳出 App 的限制,去思考整個研發流程的痛點、跨團隊協做上還有哪些優化空間等等,這樣才能真正提高咱們的開發效率、產品性能和用戶體驗。就拿我業餘時間裏一直在作的 APM 項目來講,若是隻從 App 的角度來看,要實現對線上性能數據的採集會涉及到 Gradle Plugin、字節碼、ASM、數據的採集、存儲、上報、跨進程通信等等,每一項都不簡單,每一項須要有必定的技術深度才能作好一個 APM 組件。那麼是否是每一項都作好了,實現了一個優秀的 APM 組件就能解決線上性能問題、提高用戶體驗呢?顯然不是!

若是你站在更高的角度來看,一個單純的 APM 組件並無辦法解決任何性能問題。咱們須要從前期開發階段的開發規範和實現方案、QA 驗收標準、上線後的性能數據採集、數據上報後的聚合、分析和報警、性能問題的處理流程和規範等各個維度來協同處理,全方位的系統的思考每個點,從更高的角度入手才能真正解決線上性能問題。

登高望遠

如今咱們把視角再往上拔高一個層次,站在整個技術團隊的角度來看移動開發。

安居客 App 是市面上一類比較典型的互聯網應用,它包含了基本的業務呈現、即時通信、視頻播放、直播等面向用戶的功能模塊,也包含了數據採集、日誌記錄、網絡通信等用戶看不見的功能模塊,同時還需持續交付平臺、測試平臺等等平臺的支持。

早期,即便在同一家公司這些內容各個 App 都是獨立的,各自本身作一套;

後來慢慢發現這種各自爲戰的模式效率過低,重複造輪子的現象太嚴重,因而有了平臺化的概念。即時通信是一個平臺、視頻直播是一個平臺、日誌系統又是一個平臺,持續交付、測試均是單獨的平臺。各個平臺爲各類 App 提供不同的服務,各個 App 單獨對接各個平臺就能夠了,避免了重複造輪子。

這種平臺化方案也有它本身的問題,經過前面的描述你會發現,基本上來一個新業務就要開發一個新系統,造成一個新平臺,這樣也會給 App 的接入帶來困擾,同時不一樣的平臺天然會有不一樣的團隊,這之間的溝通協做成本是巨大的。因而更進一步把各類分散的平臺統一成一個更大的平臺,統一對各類 App 提供服務。

這就是整個 App 研發體系從蠻荒時代到平臺化,再從平臺到中臺的完整進化史。

這裏說的平臺化和文章標題裏的平臺化不是同一個概念,這裏的平臺化是指一套系統做爲一個平臺爲各類 App、Web、小程序等前臺應用提供服務;而文章標題裏的平臺化是指安居客 App 做爲一個平臺來支持各種房產業務。

那麼如今咱們再來看研發團隊的組織結構,就徹底不同了。請看下圖:

中間層設計

當咱們能站在這樣一個角度看團隊的組織結構、研發流程的時候,不少事就更容易理解了。好比中臺部門推出了一套日誌系統,各個前端團隊要不要替換掉自研的埋點庫,使用中臺部門的服務,個人見解是固然要。讓專業的團隊作專業的事,中臺爲各個前端業務團隊賦能,不管是質量上仍是效率上都會有極大的提高。同時這樣也便於對各業務線的用戶數據、行爲作統一的聚合、分析、報警等等,而後進一步反哺業務。

這也是爲何以前集團 TEG 團隊推出 WMDA(58集團埋點系統)後,咱們要頂住巨大壓力在安居客內部推廣的緣由。

寫在最後

平臺化改造能順利完成並不是咱們一個團隊的功勞,這得益於先後端、產品、測試、58 無線、58 房產等多個團隊積極的配合,就好比前面介紹的不少技術方案都是 58 無線團隊的同窗提出並開發的,所以要在這裏說一聲感謝,咱們從兄弟部門學到了不少。

此次平臺化改造的過程當中涉及了太多的內容,其中每個點都能拿出來單獨寫一篇文章,因爲篇幅限制並不能在文中一一詳述。咱們團隊在平臺化方面的實踐上還缺少足夠的經驗,我的能力也有限,未能將細節很好的一一呈現。若是你們發現文章中的錯誤或者實現方案上的不完美,歡迎在評論區留言交流指正。


若是你喜歡個人文章,就關注下個人公衆號 BaronTalk知乎專欄 或者在 GitHub 上添個 Star 吧!

相關文章
相關標籤/搜索