前言
最近事情比較多,2個月沒寫文章了。看筆者圣誕節還在寫技術文章,就知道程序猿的生活有多慘淡。
上幾篇單元測試的文章,筆者已經把大部分思路講給大家聽了,如果在開發中有新的思路和技巧,以后給大家分享。
接下來,想給大家講講App項目的組件化與業務拆分。
如果上Google搜“App模塊化”、“App組件化”,可以出現一堆文章教你“如何組件化”、“組件化用到什么技術”,筆者經常搞不清他們說的“組件”、"模塊"、“業務”到底怎么劃分,很多作者對這幾個概念都有不同的理解。這導致筆者當初在搜集這方面資料,非常尷尬,每看一篇文章都有地方跟之前的文章沖突,也不知道誰對誰錯。
本文會從業務的角度,給大家講講為什么要拆分App業務,如何拆分,以及優點等等。
為什么要組件化、模塊化
項目存在問題
- 代碼量大,耦合嚴重
- 編譯慢,效率低
- 業務開發分工不明確,開發人員要關心非業務的代碼
- 改代碼時,可能會影響其他業務,牽一發動全身
優點
- 架構更清晰,解耦
- 加快編譯速度
- 業務分工明確,開發人員僅專注與自己的業務
- 提高開發效率
- 組件、業務獨立更新版本,可回滾,持續集成
組件化與模塊化
組件、模塊,中文字面意思相近,在英文上都可以翻譯為"Module",加上Android Studio上,library被稱為"Module",這就不難解釋為什么我們談到“組件化”、“模塊化”,兩者之間的區別相當的模糊。
組件
App工程上所說的 組件,應該翻譯為“Component”,意思是組件、部件、元件。在電子電路中,電子元件是電子電路中的基本元素。在App工程上,組件是構成業務或者功能模塊的基本單位。原則上,組件與組件之間互不依賴。
例如,圖片上傳功能,應該叫“圖片上傳組件”,而不是“圖片上傳模塊”。因為圖片上傳從功能、業務上,已經不能往下拆了。圖片上傳可能使用七牛sdk,或者又拍云sdk。無論圖片上傳組件用七牛sdk,還是又拍云sdk,都不會影響這個組件的功能,因此組件具有可替換性;同時,圖片上傳組件可以被多個業務使用,因此組件具有可復用性。由于sdk只是技術細節,它跟業務并沒有關系。在業務架構圖上,也不會出現“xx sdk”,因此我們說圖片上傳組件不能拆分了。
同理,日志功能,叫“日志組件”,不叫“日志模塊”。
模塊
模塊翻譯為“Module”,字面意思。模塊由多個組件構成,它可以實現一個獨立的功能,甚至業務。
例如,大眾點評的美食功能,是一個業務,可以叫“美食模塊”,習慣上叫“美食業務”。它可以拆分更小的模塊:搜索、簽到、評論等。
兩者關系
從上面的闡述可以得出,一個工程,由多個模塊組成,每個模塊由多個組件構成。但很多時候,兩者界限還是相當模糊。例如“日志組件”稱為“日志模塊”,也沒有違和感。
- 組件從業務角度上不能繼續拆分,可替換,可復用;
- 模塊的定義比較籠統,可以是一個Business業務,可以是技術架構中一個業務,也可以是幾個組件構成的小功能。
無論是組件化還是模塊化,目標都是把臃腫的工程,拆分為更小的部分,解耦各種復雜的邏輯,便于代碼管理。
業務劃分
一個產品的業務,其實是在規劃產品功能,或者做產品原型時,已經定好了(如果連產品或者老板都沒這概念的話,我們還是算了);如果后端牛逼的話,他們也會做業務劃分,每個業務部署到獨立的容器、虛擬機、服務器。所以,我們做業務劃分時,可以咨詢后端,也可以咨詢產品經理。
例如,大眾點評,首頁已經展示了好多個業務:美食、電影、酒店、休閑娛樂、外賣、機票/火車票..... 這種多業務APP,通常會把業務盡量展示在首頁,這種APP大的業務很好劃分。美食、電影這類看起來完全不同的業務,筆者稱為Business業務。
但并不是這樣劃分就OK了,好像大眾點評這種超級APP,每個Business業務都能分成很多基礎業務。例如,美食業務,可以搜索商鋪、預約、使用優惠券、點評、簽到等;同時,電影業務也有搜索、優惠券、點評等。所以,搜索商鋪、優惠券、點評這種基礎業務,可以獨立出來,被多個Business業務使用。
組件與業務
上文提過,多個組件構成一個模塊,當模塊相當于業務時,就是說該業務由多個組件組合而成。
還是拿大眾點評做例子,點評基礎業務,發布點評需要上傳圖片、網絡提交、記錄本地日志等,那么需要調用上傳圖片組件、網絡組件、日志組件等。
不僅僅點評業務調用,所有業務都會調用這些組件。于是,業務架構如下:
Business業務 -> 基礎業務 -> 各種組件
業務與業務
情景
場景:在大眾點評訂了酒店,入住之后,打開該酒店詳情頁,大眾在“推薦列表”給你推薦若干大保健......
(不要問筆者大保健是什么,筆者什么都不知道)
情況1:
前端H(負責酒店業務H):后端D,麻煩給酒店業務單獨做個推薦大保健的api。
后端D(負責大保健業務D):大保健業務有api D
,你調用api D
吧前端在酒店業務Module,寫了調用
api D
,功能上線。=============================================================
過了一段時間,大保健業務做了調整,數據變動、改域名等。后端D:前端H,api調整了,麻煩調用
api D
改為調用api D1
。
前端H:現在好忙,我加班搞吧。于是前端H加班改代碼,還要做單元測試等一系列工作。
=============================================================
又過了一段時間,大保健業務再次數據變動。后端D:前端H,
api D1
改成api D2
。
前端H:怎么又改.....
本來前端H是做酒店業務的,為了大保健的推薦列表,不得不因為大保健業務調整,而加班加點。再延伸一下,如果酒店業務H還需要調用電影院列表、美食列表.....每個業務的改動,前端H就呵呵了。
情景2:
當然了,要前端不改動,后端保持原來api D
也可以的。只不過,會引發下面對話:
前端H:后端D,不過你一直提供
api D
給其他業務使用,當數據調整時,api D
做好兼容我們就不用改了。
后端D:你傻逼啊,兼容多麻煩,我們很忙的,你們不就改一點代碼嗎?我們還要#&^@&#$"@*#......
維護兼容/對外開放接口確實是一種解決方法,只不過會加重后端開發、運維的工作量,長期來看并不科學。
情景3:
如果在前端業務與業務在獨立的情況下,也可以相互調用,那就簡單多了:
前端H:前端D,麻煩寫一個接口,讓其他前端業務可以請求大保健推薦列表。
前端D(負責大保健業務D),沒問題,你調用D類getHealthCare()
,就會請求大保健推薦列表,并返回你要的數據了。=============================================================
過了段時間,大保健數據變動。前端D在前端大保健業務D做了api D
->api D1
改動,并對D類getHealthCare()
做了數據兼容,前端H不需要額外改代碼。
從上面3個情景看,情景3是最優的做法,前端H并不需要跟后端D對接,大保健業務D改動,后端D不需要通知前端H,只需要跟前端D對接即可。而前端的兼容工作,比后端兼容工作要簡單得多。
業務之間跳轉
業務之間跳轉,這個話題老生常談了。無論是Android、iOS,都是URL Scheme跳轉這種解決方案。原因是url不需要任何依賴,而且可傳遞參數。
業務數據交互
無論前端、后端,業務之間數據交互,都是很重要的環節,選用何種合適的方案,就考驗架構師的水平了。
未做業務拆分時,直接調用其他業務的代碼即可:
但業務拆分后,就不能直接調用代碼了。兩個業務相互獨立,代碼互不依賴,必須用某種協議(常用json)用數據。
如果其他業務需要獲取大保健數據,首先大保健業務要注冊大保健服務到服務中心,其他業務才可以通過協議調用這個服務。
如何注冊服務,Android和iOS都有不同的做法,而且方法不止一種。本文僅提供思路,技術細節,會在之后的文章闡述。
其實組件與組件之間,也存在相互調用的情況,可參考這種做法。
P.S.大眾點評沒有“大保健”業務,只有“足療按摩”業務。筆者為渲染氣氛虛擬一個大保健出來,希望大眾的朋友諒解。
小結
組件化、拆分業務后:
- 單一職責:開發人員專注于自己的業務
- 依賴倒置:上層業務依賴下層業務,業務依賴組件,業務之間、組件之間不相互依賴
- 接口隔離:業務之間調用數據,通過統一的協議與服務中心交互,不調用業務實際代碼
代碼質量與規范程度明顯提高,高內聚、低耦合。業務職責分明,單元測試也更好寫。如果業務拆分做得好,可以一個業務一個單獨工程編譯,不僅大幅提高編譯速度,而且業務代碼還可以回滾、版本發布等。
一切為了更清晰的架構、更干凈的代碼_。
關于作者
我是鍵盤男。
在廣州生活,在互聯網公司上班,猥瑣文藝碼農。喜歡科學、歷史,玩玩投資,偶爾獨自旅行。