戲說移動江湖開發(fā)歷程
大主線
細說移動開發(fā)歷程
大技術
組件化開發(fā)
- 組件路由
- 組件配置動態(tài)加載
- 組件骨架架構
插件化開發(fā)
- 靜態(tài)插件化
- 動態(tài)插件化
細節(jié)雕琢
- 網絡層的優(yōu)化和架構
- 動態(tài)埋點的實現(xiàn)
- 技術層架構(MVP,MVVM等模式)
前言
你可能的收獲:
- 理解整個公司移動開發(fā)的基線和主線
- 學會移動開發(fā)組開發(fā)過程碰到問題和解決方案
- 學會移動開發(fā)過程各個技術的細枝末葉
- 希望能給讀者開發(fā)項目有點啟發(fā)和思索
正文
我理解的技術開發(fā)人員,除了業(yè)務和技術的熱愛,其同時也需具備獨立思考的能力。
在這個高速變換的二次元移動開發(fā)時代,很多產品和公司應付追趕日新月異之變化都是爭分奪秒攻城略地,伴隨而來的移動研發(fā)也是進隨著'敲鑼打鼓開天辟地'。
所以我們有必要分析和思索當下移動開發(fā)的周期,就個人理解則把移動開發(fā)生命周期分四大周期,這個四個周期同步伴隨著公司發(fā)展整個過程。
這個四個生命周期分別命名為:
- 1.成長期
- 2.混沌期
- 3.統(tǒng)一期
- 4.分化期
- 成長期一般在公司的第1~2年;
- 混沌期一般在公司的第2~3年;
統(tǒng)一和分化期在公司第3年以后;其中統(tǒng)一和分化期有可能多次迭代進行。
所謂的成長期,也就是傳說中的野蠻發(fā)展,此時公司主導方向快速迭代跟進市場,作為研發(fā)里程以及人員數(shù)目這塊都是從無到有的過程,其宗旨也是開發(fā)追趕產品實現(xiàn)快速上線過程。
此時開發(fā)技術選型都是以個人因素為走向,因此前期項目選型和架構都是個人技術喜愛占主導,自己熟悉的技術和框架才是最快最有效的,可以快速追趕上線進度。
譬如喜歡rxjava,喜歡mvp模式很快就會在這個項目就起主導方案和技術架構.甚至有些開發(fā)同仁直接從網上所謂架構好的現(xiàn)成項目開干懟。
此時段公司的唯一宗旨就是首戰(zhàn)市場產出產品,快速迭代占據(jù)每個開發(fā)人員的腦海中,細節(jié)等一切可以忽略,要啥自行車。
接下來,隨著公司業(yè)績第一槍打響,同時融資也下來了,開始招兵買馬大干一場,人員補給上來,開始出現(xiàn)混亂和磨合期,新來人員覺得老代碼就是一坨翔,各種心底鄙視和不爽;
老員工覺得新員工桀驁不馴啥都不懂喜歡裝逼。但是公司補給人員的目的是更加快速迭代項目,公司還動不動搞個什么敏捷開發(fā)鬼模式實現(xiàn)1~2周迭代一個版本(就喜歡搞事)。
需求繼續(xù)開展代碼還得迭代而新老開發(fā)人員依葫蘆畫瓢編寫代碼,慢慢的(可以N個),慢慢的過段時間發(fā)現(xiàn)代碼充斥各種耦合,不規(guī)范代碼,文件包混亂,業(yè)務各種穿插,
一句話混亂的一鍋粥,各種線上bug突突的冒出來;線上bug一統(tǒng)計,fuck指標超過5-10%,開始全組上下靜心反思,產生出版本重構迭代統(tǒng)一思想。
項目重構功能改善等統(tǒng)一口號就出現(xiàn)了,此時一般分兩波人馬,一撥人馬繼續(xù)業(yè)務迭代而另外一波人馬進行項目重構;此事的核心就是減少線上bug數(shù)的量級,
完成公司要求線上bug不能超過3%的指標,這個時候重構重點基于線上bug進行維度分析,通過問題按多少進行劃分,差不多這個時候的問題如下:
- Bug的可視化實時監(jiān)控和統(tǒng)計;
- 引用內存未釋放導致crash的bug;
- 內存泄漏導致crash的bug;
- 進入市場機型問題引起的bug;
- 網絡訪問慢的反饋;
- 奇葩未知的bug;
- 。。。
- 問題1的思考,引入第三方系統(tǒng),例如bugly等
- 問題2的思考,引入Eventbus解決回調地獄問題和回調引起泄漏未釋放問題;
- 問題3的思考,引進LeakCanary內存泄漏檢測,和prof分析大法根據(jù)各個問題進行突破;
- 問題4的思考,無解,能解決一個是一個,主要公司機型跟不上,可以通過網上機型提供商進行問題測試,貴不說而且感覺沒啥用;
- 問題5的思考,略;
關于公司指定的線上bug指標,是否完成也是需要多版本迭代現(xiàn)網運行后才能統(tǒng)計;既然是現(xiàn)網bug就有輕重之分,如果重大bug一般立即發(fā)布新版本更新,輕微的bug放到下一個版本迭代修復,那有沒有現(xiàn)網bug熱修復方案,肯定有的,成熟的有tinker等第三方庫;
雖然以上問題加班加點的搞完后,但是隨著公司業(yè)務的發(fā)展和市場的強大推廣,多個業(yè)務線如雨后春筍一般立項開干,看著當前項目架構模式(如圖一)
長嘆一聲,埋在心頭的那個一個極大隱患和不安慢慢露出來,項目中依舊充斥代碼各種耦合和混亂,加上‘混亂代碼加上新代碼依舊還是混亂代碼’定理一直壓著頭頂上,這項目框架肯定無法跟上公司新業(yè)務線的發(fā)展和規(guī)劃;有壓力就有動力,深思熟慮后不知覺分層分模塊架構慢慢浮現(xiàn)出來,每個業(yè)務線都是一個Module模塊,接下來每來一個業(yè)務線就按照這模塊模樣復制粘貼一份接著開懟業(yè)務。一般這種情況需要持續(xù)到三個業(yè)務線后基本就會出現(xiàn)模塊間混亂調用,資源文件各種重復且代碼到處飛,加上權限控制不到從而每個人都有權限編寫基礎庫從而使各個業(yè)務公共代碼下沉到基礎庫導致龐大臃腫,多模塊混合編譯速度極度慢等不良問題一大堆冒出來,回過頭看看項目現(xiàn)狀,我去,又來了,忙不完的事??纯磮D二如果你把自己當處女座,你肯定會發(fā)狂,要么炒老板魷魚要么靜下心思考分析。
分析后得出以下幾個急需解決的問題,
- 模塊間的調用進行解耦合實現(xiàn)模塊熱拔式方案
- 是時候加上代碼權限管理
- 模塊打包AAR實現(xiàn)模塊間引入
- 解決編譯速度慢問題
- 自動化打包問題
- 。。。。
問題1的思考,既然實現(xiàn)解耦合同時實現(xiàn)熱拔式方案,說白點就是當前模塊開關關閉,被其他引用的模塊無法感知到這個模塊被關閉,即其他模塊引用的代碼必須不能硬編碼此模塊的方法和引用類等等,方案就是組件路由,調用方通過字符串path查詢模塊的服務和功能。
問題2的思考,代碼權限管理一般通過git或者svn去實現(xiàn)。
問題3的思考,可以通過gradle腳本實現(xiàn)模塊打包上傳私服。
問題4的思考,gradle本身問題加上模塊多導致編譯速度慢,根據(jù)業(yè)務線的獨立性那我們可以通過編寫業(yè)務模塊時給此模塊實現(xiàn)App模式,減少其他不必要的代碼編譯和運行。實現(xiàn)方案大體如下:
在模塊gradle編譯腳本通過標識符來區(qū)分是模塊還是可獨立運行的App
- sourceSets {
- main {
- jniLibs.srcDirs = ['libs']
- if ("true".equals(FINANCE_IS_APPLICATION)) {
- manifest.srcFile 'src/main/diff/appmodule/AndroidManifest.xml'
- java.srcDirs = ['src/main/java', 'src/main/diff/appmodule/java']
- res.srcDirs = ['src/main/res', 'src/main/diff/appmodule/res']
- assets.srcDirs = ['src/main/assets', 'src/main/diff/appmodule/assets']
- } else {
- manifest.srcFile 'src/main/diff/libmodule/AndroidManifest.xml'
- java.srcDirs = ['src/main/java', 'src/main/diff/libmodule/java']
- res.srcDirs = ['src/main/res', 'src/main/diff/libmodule/res']
- assets.srcDirs = ['src/main/assets', 'src/main/diff/libmodule/assets']
- }
- } }
這樣我們需要單獨運行此模塊,在gradle.properies把FINANCE_IS_APPLICATION為true然后編譯就可以實現(xiàn)業(yè)務代碼編寫和運行。有人問,如果我需要實現(xiàn)主App里面的新業(yè)務,那你可以關閉其他無關的模塊實現(xiàn)快速編譯提高開發(fā)效率。
問題5的思考,隨著項目的增大和多渠道的打包,此時需要進行考慮項目周邊的業(yè)務服務,例如提供給測試人員的打包測試,正式版的發(fā)布等等自動化產出問題。
一般自動化服務可以通過搭建jenkins服務,或者配合python腳本實現(xiàn)自動化打包功能,其
腳本的功能因公司而異。
所以此時迫切需要一個熟悉gradle,python等腳本的同志(gradle本身是grovvy語言)。保證新業(yè)務的開發(fā)的情況下整個過程的重構和完善至少需要半年時間(大公司除外)。
慢慢發(fā)現(xiàn),組件化架構無聲無息的出現(xiàn)了,是不是很神奇。
回過頭發(fā)現(xiàn)組件化架構已經進行了一小部分,信心十足,繼續(xù)干,此時必須祭出毛爺爺?shù)募t本子,大聲的朗讀出來,我愛編程,皮膚好好!!
我們發(fā)現(xiàn)已經做了業(yè)務模塊化代碼分離和模塊間路由互調通信以及gradle組件化腳本;
你的成長是建立在公司的成長上,隨著公司業(yè)務發(fā)展龐大,種種緣由業(yè)務伴隨著也會出現(xiàn)分支獨立,需要某些子業(yè)務線獨立出App提供專業(yè)的服務和體驗;需要撒播種子開花結果,原先的子模塊可能變成獨立App,所以發(fā)現(xiàn)目前的架構是沒法實現(xiàn),對,走過來,請在菩提樹下思考;其根本緣由就是組件化不完全導致的。其中最大問題就是主項目模塊涉及到大量的以前最早的業(yè)務代碼和功能,現(xiàn)在最迫切問題是需要把主項目的業(yè)務剝離變成一個業(yè)務子模塊加一個純粹的項目骨架,其中項目骨架必須上升一級變成新的主項目模塊,此主項目模塊包含項目公共業(yè)務。說白點,把項目骨架套在其他子模塊就是一個獨立的App可以運行;
作為對比,圖四為原架構圖,圖五為主項目模塊上升一級為項目骨架的架構圖
其中主項目骨架必須包含的功能有:
- 項目升級降級功能;
- 第三方庫的引用和初始化工作;
- 實現(xiàn)子模塊加載和引入以及初始化工作;
- 周邊服務或插件的引入和初始化工作;例如Tinker和bugly等
- 。。。

這個時候組件化大體已經完整成型,現(xiàn)在唯一需要做的就是通過gradle腳本去做粘合器,腳本配合jenkins動態(tài)實現(xiàn)模塊間和主項目骨架的組合;
上面說的組件化成型是主體骨架完整了,但是需要根據(jù)自己的公司業(yè)務繼續(xù)進一步解耦和分離,一般如:
- 全局配置文件的分離,實現(xiàn)配置文件根據(jù)子模塊業(yè)務走,例如網絡地址的配置和網絡請求地址的分離;
- 業(yè)務配置文件的分離,配合服務端一起實現(xiàn)模塊化分離;
- 各個子模塊的公共業(yè)務動態(tài)加載塊;
- 耦合代碼的分離和重構;
- 。。。
此過程應該做到了項目模塊以及代碼的各種解耦和分離,看起來非常清爽和干凈。不知覺又開始唱起了:我愛編程,皮膚好好!!
突然有一天你聽到有人說插件化,你心里暗暗一笑,我們項目早就實現(xiàn)了熱拔式插件化;
一討論發(fā)現(xiàn)原來不是你想的插件化,他們說的插件化是把業(yè)務模塊動態(tài)存放到網上,需要的時候加載進來;
哇咔咔,原來插件化分兩種,一直靜態(tài)插件化和動態(tài)插件化;
不知覺的發(fā)現(xiàn)我們已經實現(xiàn)了靜態(tài)插件化功能,細水長流說的就是這個,哦,應該是水到渠成;
動態(tài)插件化的前提必須是項目已經具備成型的組件化后才能實現(xiàn)動態(tài)插件化功能。
目前已經可以獨立出各個子模塊打包成AAR、JAR、APK;接下來就是需要在主項目骨架上添加一項動態(tài)插件化功能;完美
現(xiàn)在動態(tài)插件化市面上有很多成熟的方案,因為這個不像組件化過程,組件化其實本身和業(yè)務和項目有很大關聯(lián),需要根據(jù)自己的業(yè)務以及已有的業(yè)務框架進行加工和架構實現(xiàn);而
動態(tài)插件化實現(xiàn)機制和業(yè)務體系和自身架構無關系,可以大膽的引入第三方成熟的插件;例如美團公司,阿里公司的動態(tài)插件化。
其實,回味下整個過程,發(fā)現(xiàn)這些都是一步步的走下去的,不可能一步到位,這才人生;
有人問是不是接下來高枕無憂,哈哈,too x too native, 這才是萬里長征前幾步而已,接下來需要細節(jié)上和技術上進一步雕琢,周邊服務的完善和安全等配套實施都需要等你去實現(xiàn);路遙茫茫。。。
細節(jié)上雕琢隨便列舉幾個:
- 例如上面提到的bug中出現(xiàn)網絡性能慢,這個就可以深入挖掘各個實現(xiàn),例如騰訊就這個小點實現(xiàn)了Mars開源框架;
- 業(yè)務UI框架的封裝(減少重復開發(fā)以及性能問題);
- 性能監(jiān)控;
- 配置管理中心;
- 動態(tài)埋點;
- 各個業(yè)務核心點的優(yōu)化;
- 編寫的組件化的重構和優(yōu)化;
- 技術層架構(MVP,MVVM等模式)
- 分布式架構;
- 。。。。
最終你會發(fā)現(xiàn),很多功能只有在你組件化結束后或者插件化結束后再去實施會達到事半功倍效果,實現(xiàn)集中優(yōu)化改動分布最小化,極大減少改動的風險和bug風險;
以上過程其實是一個分久必合合久必分的過程。當項目走向做到極致的時候還是沒法應付龐大用戶群和業(yè)務群,請轉行養(yǎng)豬。。。
插件化路由實現(xiàn),源碼詳見,覺得好請點擊star:
https://github.com/wenzhonghu/MyRouter