戲說移動江湖開發歷程

codeGoogle發表於2018-05-30

大主線

細說移動開發歷程

大技術

元件化開發

1、元件路由

2、元件配置動態載入

3、元件骨架架構

外掛化開發

1、靜態外掛化

2、動態外掛化

細節雕琢

1、網路層的優化和架構*

2、動態埋點的實現*

3、技術層架構(MVP,MVVM等模式)

大天地

後續按照大技術塊各個技術點深入淺出的分享出來,請訂閱關注。

前言

本文閱讀需要8分鐘。

你可能的收穫:

* 理解整個公司移動開發的基線和主線

* 學會移動開發組開發過程碰到問題和解決方案

*  學會移動開發過程各個技術的細枝末葉

*  希望能給讀者開發專案有點啟發和思索

正文

我理解的技術開發人員,除了業務和技術的熱愛,其同時也需具備獨立思考的能力。~~

在這個高速變換的二次元移動開發時代,很多產品和公司應付追趕日新月異之變化都是爭分奪秒攻城略地,伴隨而來的移動研發也是進隨著'敲鑼打鼓開天闢地'。

所以我們有必要分析和思索當下移動開發的週期,就個人理解則把移動開發生命週期分四大週期,這個四個週期同步伴隨著公司發展整個過程。

這個四個生命週期分別命名為:

1.成長期

2.混沌期

3.統一期

4.分化期

成長期一般在公司的第1~2年;

混沌期一般在公司的第2~3年;

統一和分化期在公司第3年以後;其中統一和分化期有可能多次迭代進行。

所謂的成長期,也就是傳說中的野蠻發展,此時公司主導方向快速迭代跟進市場,作為研發里程以及人員數目這塊都是從無到有的過程,其宗旨也是開發追趕產品實現快速上線過程。

此時開發技術選型都是以個人因素為走向,因此前期專案選型和架構都是個人技術喜愛佔主導,自己熟悉的技術和框架才是最快最有效的,可以快速追趕上線進度。

譬如喜歡rxjava,喜歡mvp模式很快就會在這個專案就起主導方案和技術架構.甚至有些開發同仁直接從網上所謂架構好的現成專案開幹懟。

此時段公司的唯一宗旨就是首戰市場產出產品,快速迭代佔據每個開發人員的腦海中,細節等一切可以忽略,要啥自行車。

接下來,隨著公司業績第一槍打響,同時融資也下來了,開始招兵買馬大幹一場,人員補給上來,開始出現混亂和磨合期,新來人員覺得老程式碼就是一坨翔,各種心底鄙視和不爽;

老員工覺得新員工桀驁不馴啥都不懂喜歡裝逼。但是公司補給人員的目的是更加快速迭代專案,公司還動不動搞個什麼敏捷開發鬼模式實現1~2周迭代一個版本(就喜歡搞事)。

需求繼續開展程式碼還得迭代而新老開發人員依葫蘆畫瓢編寫程式碼,慢慢的(可以N個),慢慢的過段時間發現程式碼充斥各種耦合,不規範程式碼,檔案包混亂,業務各種穿插,

一句話混亂的一鍋粥,各種線上bug突突的冒出來;線上bug一統計,fuck指標超過5-10%,開始全組上下靜心反思,產生出版本重構迭代統一思想。

專案重構功能改善等統一口號就出現了,此時一般分兩波人馬,一撥人馬繼續業務迭代而另外一波人馬進行專案重構;此事的核心就是減少線上bug數的量級,

完成公司要求線上bug不能超過3%的指標,這個時候重構重點基於線上bug進行維度分析,通過問題按多少進行劃分,差不多這個時候的問題如下:

1、Bug的視覺化實時監控和統計;

2、引用記憶體未釋放導致crash的bug;

3、記憶體洩漏導致crash的bug;

4、進入市場機型問題引起的bug;

5、網路訪問慢的反饋;

6、奇葩未知的bug;

問題1的思考,引入第三方系統,例如bugly等

問題2的思考,引入Eventbus解決回撥地獄問題和回撥引起洩漏未釋放問題;

問題3的思考,引進LeakCanary記憶體洩漏檢測,和prof分析大法根據各個問題進行突破;

問題4的思考,無解,能解決一個是一個,主要公司機型跟不上,可以通過網上機型提供商進行問題測試,貴不說而且感覺沒啥用;

問題5的思考,略;

關於公司指定的線上bug指標,是否完成也是需要多版本迭代現網執行後才能統計;既然是現網bug就有輕重之分,如果重大bug一般立即釋出新版本更新,輕微的bug放到下一個版本迭代修復,那有沒有現網bug熱修復方案,肯定有的,成熟的有tinker等第三方庫;

雖然以上問題加班加點的搞完後,但是隨著公司業務的發展和市場的強大推廣,多個業務線如雨後春筍一般立項開幹,看著當前專案架構模式(如圖一)

初期架構

圖(一)

長嘆一聲,埋在心頭的那個一個極大隱患和不安慢慢露出來,專案中依舊充斥程式碼各種耦合和混亂,加上‘混亂程式碼加上新程式碼依舊還是混亂程式碼’定理一直壓著頭頂上,這專案框架肯定無法跟上公司新業務線的發展和規劃;有壓力就有動力,深思熟慮後不知覺分層分模組架構慢慢浮現出來,每個業務線都是一個Module模組,接下來每來一個業務線就按照這模組模樣複製貼上一份接著開懟業務。一般這種情況需要持續到三個業務線後基本就會出現模組間混亂呼叫,資原始檔各種重複且程式碼到處飛,加上許可權控制不到從而每個人都有許可權編寫基礎庫從而使各個業務公共程式碼下沉到基礎庫導致龐大臃腫,多模組混合編譯速度極度慢等不良問題一大堆冒出來,回過頭看看專案現狀,我去,又來了,忙不完的事。看看圖二(偷圖,侵圖刪)如果你把自己當處女座,你肯定會發狂,要麼炒老闆魷魚要麼靜下心思考分析。

圖(二)

分析後得出以下幾個急需解決的問題,

1. 模組間的呼叫進行解耦合實現模組熱拔式方案

2. 是時候加上程式碼許可權管理

3. 模組打包AAR實現模組間引入

4. 解決編譯速度慢問題

5. 自動化打包問題

問題1的思考,既然實現解耦合同時實現熱拔式方案,說白點就是當前模組開關關閉,被其他引用的模組無法感知到這個模組被關閉,即其他模組引用的程式碼必須不能硬編碼此模組的方法和引用類等等,方案就是元件路由,呼叫方通過字串path查詢模組的服務和功能。

問題2的思考,程式碼許可權管理一般通過git或者svn去實現。

問題3的思考,可以通過gradle指令碼實現模組打包上傳私服。

問題4的思考,gradle本身問題加上模組多導致編譯速度慢,根據業務線的獨立性那我們可以通過編寫業務模組時給此模組實現App模式,減少其他不必要的程式碼編譯和執行。實現方案大體如下:

在模組gradle編譯指令碼通過識別符號來區分是模組還是可獨立執行的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然後編譯就可以實現業務程式碼編寫和執行。有人問,如果我需要實現主App裡面的新業務,那你可以關閉其他無關的模組實現快速編譯提高開發效率。

問題5的思考,隨著專案的增大和多渠道的打包,此時需要進行考慮專案周邊的業務服務,例如提供給測試人員的打包測試,正式版的釋出等等自動化產出問題。

一般自動化服務可以通過搭建jenkins服務,或者配合python指令碼實現自動化打包功能,其

指令碼的功能因公司而異。

戲說移動江湖開發歷程

#####  圖(三)

所以此時迫切需要一個熟悉gradle,python等指令碼的同志(gradle本身是grovvy語言)。保證新業務的開發的情況下整個過程的重構和完善至少需要半年時間(大公司除外)。

慢慢發現,元件化架構無聲無息的出現了,是不是很神奇。

回過頭髮現元件化架構已經進行了一小部分,信心十足,繼續幹,此時必須祭出毛爺爺的紅本子,大聲的朗讀出來,我愛程式設計,皮膚好好!!

我們發現已經做了業務模組化程式碼分離和模組間路由互調通訊以及gradle元件化指令碼;

你的成長是建立在公司的成長上,隨著公司業務發展龐大,種種緣由業務伴隨著也會出現分支獨立,需要某些子業務線獨立出App提供專業的服務和體驗;需要撒播種子開花結果,原先的子模組可能變成獨立App,所以發現目前的架構是沒法實現,對,走過來,請在菩提樹下思考;其根本緣由就是元件化不完全導致的。其中最大問題就是主專案模組涉及到大量的以前最早的業務程式碼和功能,現在最迫切問題是需要把主專案的業務剝離變成一個業務子模組加一個純粹的專案骨架,其中專案骨架必須上升一級變成新的主專案模組,此主專案模組包含專案公共業務。說白點,把專案骨架套在其他子模組就是一個獨立的App可以執行;

作為對比,圖四為原架構圖,圖五為主專案模組上升一級為專案骨架的架構圖

其中主專案骨架必須包含的功能有:

1、專案升級降級功能;

2、第三方庫的引用和初始化工作;

3、實現子模組載入和引入以及初始化工作;

4、周邊服務或外掛的引入和初始化工作;例如Tinker和bugly等

戲說移動江湖開發歷程

圖(四)

元件化成型架構

圖(五)

這個時候元件化大體已經完整成型,現在唯一需要做的就是通過gradle指令碼去做粘合器,指令碼配合jenkins動態實現模組間和主專案骨架的組合;

上面說的元件化成型是主體骨架完整了,但是需要根據自己的公司業務繼續進一步解耦和分離,一般如:

1. 全域性配置檔案的分離,實現配置檔案根據子模組業務走,例如網路地址的配置和網路請求地址的分離;

2. 業務配置檔案的分離,配合服務端一起實現模組化分離;

3. 各個子模組的公共業務動態載入塊;

4. 耦合程式碼的分離和重構;

此過程應該做到了專案模組以及程式碼的各種解耦和分離,看起來非常清爽和乾淨。不知覺又開始唱起了:我愛程式設計,皮膚好好!!

突然有一天你聽到有人說外掛化,你心裡暗暗一笑,我們專案早就實現了熱拔式外掛化;

一討論發現原來不是你想的外掛化,他們說的外掛化是把業務模組動態存放到網上,需要的時候載入進來;

哇咔咔,原來外掛化分兩種,一直靜態外掛化和動態外掛化;

不知覺的發現我們已經實現了靜態外掛化功能,細水長流說的就是這個,哦,應該是水到渠成;

動態外掛化的前提必須是專案已經具備成型的元件化後才能實現動態外掛化功能。

目前已經可以獨立出各個子模組打包成AAR、JAR、APK;接下來就是需要在主專案骨架上新增一項動態外掛化功能;完美

現在動態外掛化市面上有很多成熟的方案,因為這個不像元件化過程,元件化其實本身和業務和專案有很大關聯,需要根據自己的業務以及已有的業務框架進行加工和架構實現;而

動態外掛化實現機制和業務體系和自身架構無關係,可以大膽的引入第三方成熟的外掛;例如美團公司,阿里公司的動態外掛化。

其實,回味下整個過程,發現這些都是一步步的走下去的,不可能一步到位,這才人生;

有人問是不是接下來高枕無憂,哈哈,too x too native, 這才是萬里長征前幾步而已,接下來需要細節上和技術上進一步雕琢,周邊服務的完善和安全等配套實施都需要等你去實現;路遙茫茫。。。

細節上雕琢隨便列舉幾個:

1、例如上面提到的bug中出現網路效能慢,這個就可以深入挖掘各個實現,例如騰訊就這個小點實現了Mars開源框架;

2、業務UI框架的封裝(減少重複開發以及效能問題);

3、效能監控;

4、配置管理中心;

5、動態埋點;

6、各個業務核心點的優化;

7、編寫的元件化的重構和優化;

8、技術層架構(MVP,MVVM等模式)

9、分散式架構;

最終你會發現,很多功能只有在你元件化結束後或者外掛化結束後再去實施會達到事半功倍效果,實現集中優化改動分佈最小化,極大減少改動的風險和bug風險;

以上過程其實是一個分久必合合久必分的過程。當專案走向做到極致的時候還是沒法應付龐大使用者群和業務群,請轉行養豬。。。

外掛化路由實現,原始碼詳見,覺得好請點選star:我的路由

連結:https://www.jianshu.com/p/df2a6717009d,轉載請註明來源

閱讀更多

react-native技術的優劣

學習React Native必看的幾個開源專案

開發了幾個小程式後,說說我對小程式的看法

NDK專案實戰—高仿360手機助手之解除安裝監聽

(Android)面試題級答案(精選版)

如果有什麼 問題,歡迎和我交流 微信公眾號:終端研發部

相關文章