自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

微信 Android 模塊化架構(gòu)重構(gòu)實(shí)踐(下)

開發(fā) 開發(fā)工具
“大前端”是個熱門的方向。我們結(jié)合自身情況,考慮到遷移已有代碼不是一件容易事,讓團(tuán)隊(duì)徹底切換編程工具短期不現(xiàn)實(shí)。這種“遠(yuǎn)水解不了近渴”的感覺,也只能暫且作罷。

上篇:http://zhuanlan.51cto.com/art/201708/547499.htm

取舍和選擇

對于架構(gòu)重構(gòu),我們也曾放眼行業(yè)內(nèi)已經(jīng)發(fā)布過的各種方案,希望從中找到一些解決思路。

我們參考了很多業(yè)界開放和發(fā)表的架構(gòu)設(shè)計(jì)??偟膩碚f,目前Android端App整體架設(shè)計(jì)上,除了聚焦在“大前端”之外,基本上都在“插件化/應(yīng)用沙盒”上面下功夫??梢詤⒖既鏰tlas、small、DroidPlugin、DynamicApk等等方案,不難發(fā)現(xiàn)讓模塊最終具備動態(tài)性是它們最核心的能力。

“大前端”是個熱門的方向。我們結(jié)合自身情況,考慮到遷移已有代碼不是一件容易事,讓團(tuán)隊(duì)徹底切換編程工具短期不現(xiàn)實(shí)。這種“遠(yuǎn)水解不了近渴”的感覺,也只能暫且作罷。

我們把目光投向了“插件化/應(yīng)用沙盒”。沙盒的好處是它具備很強(qiáng)的隔離性,有些方案可以徹底隔離代碼和資源,邊界限制性極強(qiáng),效果很好。此外,多數(shù)方案也都具備動態(tài)更新能力、補(bǔ)丁能力,動態(tài)性基本成為標(biāo)配。所以這時我們在考慮需不需要走上這樣的路。

一切從自身情況出發(fā)。在微信的角度看,我們最關(guān)心的問題是如何能約束住代碼邊界,如何防止架構(gòu)劣化,如何提高開發(fā)效率。這樣的情況下,重新審視了具備動態(tài)性的插件化和沙盒方案。先從動態(tài)性上考慮,回看業(yè)內(nèi)的使用經(jīng)驗(yàn),目前的動態(tài)性通常有兩個主要的用途:1)作為熱補(bǔ)丁使用;2)業(yè)務(wù)并行發(fā)布需求強(qiáng)烈,例如運(yùn)營需求,作為快速發(fā)布的手段。對于第二點(diǎn),就目前的微信團(tuán)隊(duì)來說是較少遇到的弱需求。相較之下,工具類和電商類應(yīng)用常有符合的使用場景。而對于***點(diǎn),我們則期望在實(shí)現(xiàn)模塊化上,目標(biāo)相對純粹一些,專心解決代碼自身問題,之后再通過tinker在開發(fā)階段之外實(shí)現(xiàn)熱補(bǔ)丁上的動態(tài)性需要。

再來看隔離性。需要說明的是,這里的隔離型主要來自于沙盒架構(gòu)效果。對于非獨(dú)立插件化工程(需要編譯依賴其他插件)除了動態(tài)性,它的作用和普通module在代碼隔離上沒有區(qū)別,不做討論。

我們心里很期盼代碼與代碼之間那種干凈清爽的分割效果,但事與愿違。

圖20 - 模塊依賴示意圖

圖20 - 模塊依賴示意圖

從上面這張模塊依賴示意圖看到,微信業(yè)務(wù)模塊之間數(shù)據(jù)關(guān)系相當(dāng)復(fù)雜,模塊間相互訪問數(shù)據(jù)、共享某些功能的行為如此普遍。而實(shí)際情況比示意圖更麻煩。

面對微信業(yè)務(wù)數(shù)據(jù)相互間頻繁的調(diào)用,沙盒隔離容易導(dǎo)致代碼復(fù)用困難和相互調(diào)用麻煩,想在微信上實(shí)現(xiàn),目前困難極大。重構(gòu)難度不談,單是隔離的收益就很有可能無法彌補(bǔ)開發(fā)效率上的損失。

從開發(fā)模式上看也是一樣。微信Android團(tuán)隊(duì)目前每個迭代大概三四十人參與,內(nèi)部溝通成本不算高到不可接受。通常開發(fā)同學(xué)可能要同時開發(fā)和修改幾個模塊并保證他們相互模塊獨(dú)立,同時又可能有頻繁的模塊間通信。這種時候,模塊調(diào)用方不方便顯得很重要。

此外還需要考慮的問題,從幾個成熟方案中都能看到hook Android框架、修改aapt、替換或包裝android gradle plugin、代理組件等等設(shè)計(jì)。這些方案的復(fù)雜度和兼容性代價,不能忽視。使用和維護(hù)它們需要仔細(xì)權(quán)衡。

所以思前想后我們?nèi)赃x擇了重走最開始的模塊化之路。一切問題的根本還是在那個說的很多年的代碼邊界、解耦和內(nèi)聚上。只要有了清晰獨(dú)立的代碼模塊,才有將來其他變化的可能性。

代碼之外,架構(gòu)之內(nèi)

模塊負(fù)責(zé)人制度

有這樣一句話,“不被監(jiān)管的權(quán)利一定會發(fā)生腐敗” 。如果放到軟件開發(fā)的行當(dāng)來說,就是“不被監(jiān)管的代碼也一定會發(fā)生劣化”。所以代碼應(yīng)該要接受“監(jiān)管”。

為了能長期有效的保持代碼質(zhì)量,我們開始執(zhí)行新的代碼審查機(jī)制——模塊負(fù)責(zé)人制度。

代碼審查的好處毋庸置疑。在這之前,微信由于業(yè)務(wù)發(fā)展快速,同學(xué)們經(jīng)常會變換需求的開發(fā)方向。面對著業(yè)務(wù)模塊數(shù)量比人多的情況,開發(fā)同學(xué)經(jīng)常一個人需要開發(fā)多個模塊。也因此許多模塊被無數(shù)人維護(hù)過,基礎(chǔ)的支撐工程更是如此。這種類似游擊戰(zhàn)的方式,開發(fā)效率很高,支撐了微信快速的研發(fā)節(jié)奏,但也導(dǎo)致了“無主代碼”特別多。大家缺少對代碼的“歸屬感”,也降低了改進(jìn)優(yōu)化模塊的欲望。

另外在這之前,代碼審查是由leader對申請回流主干的Merge Request進(jìn)行review,這導(dǎo)致效率較低且容易遺漏問題。合理的代碼審查更應(yīng)該是全員性質(zhì)的。

模塊負(fù)責(zé)人制度嘗試改變這些現(xiàn)狀。通過大家認(rèn)領(lǐng)模塊,對模塊的代碼和設(shè)計(jì)負(fù)責(zé),對模塊對外提供的接口服務(wù)負(fù)責(zé),對其他人修改自己模塊的行為進(jìn)行監(jiān)督。這些情況明顯提高開發(fā)同學(xué)的代碼所有感,改變大家修改優(yōu)化和修改代碼的動機(jī)。

推動模塊負(fù)責(zé)人制度,漸進(jìn)式的推動了大范圍的代碼審查,這樣的方式很適合像微信這樣沒有從一開始執(zhí)行全員性質(zhì)Code Review的項(xiàng)目。目前模塊負(fù)責(zé)人機(jī)制運(yùn)轉(zhuǎn)順利,代碼審查率和模塊認(rèn)領(lǐng)率都在提高。

重構(gòu)與開發(fā)者心態(tài)的關(guān)系

在一個長期沒有改進(jìn)的框架下,開發(fā)者的習(xí)慣可能會逐步變成跟隨式、保守式的開發(fā)。這大概可以被描述成“只要別人這樣做,我也這樣做,哪怕這么樣的設(shè)計(jì)不好,但也不會錯”。隨著心態(tài)逐漸普遍,另一種情形出現(xiàn):經(jīng)常能聽到有同學(xué)吐槽一些代碼,卻更少看到代碼在被改進(jìn)。這說明一些沉積的問題不是沒有被大家發(fā)現(xiàn),只是沒有人愿意去修改。這種情況下代碼和框架會隨著時間變得越來越差,有些問題逐漸變成“陳年舊病”。 面對這個問題首先要說,這不是開發(fā)者合格與否的問題,實(shí)際上有想法的開發(fā)人員有很多,但想將每個想法轉(zhuǎn)換成代碼并讓大家接受,并不是一件很容易的事。尤其在一個大框架下,嘗試改變的代價很大。如果他的主要任務(wù)不在改進(jìn)某些模塊上,那么很多想法***都無法變成現(xiàn)實(shí)。這也是為什么保守和跟隨的習(xí)慣會逐漸變的普遍。

保守的氣氛需要被打破。當(dāng)開啟一次重構(gòu)之后,你會發(fā)現(xiàn)團(tuán)隊(duì)中會有很多積極的聲音響應(yīng),他們會把積壓的想法和意見拋出來。一次問題的解決,可能會為另一個問題的解決帶來機(jī)會,其他開發(fā)同學(xué)的一些想法也許就能更容易落地。所以不定期的推動一些模塊的重構(gòu),將一些對代碼的不滿釋放出來,是一種不錯的激活。

此外在重構(gòu)之后,還要考慮引導(dǎo)開發(fā)的代碼組織方式切換,多用模板、正確的代碼實(shí)例等,讓他們可以放心參考。

模塊劃分經(jīng)驗(yàn)談

維持代碼邊界

代碼的邊界就像一堵墻,架構(gòu)的劣化都是從這堵墻的瓦解開始的。從以往的經(jīng)驗(yàn)來看,編譯上的隔離是***的約束手段,單純的約定或準(zhǔn)則并不能永遠(yuǎn)的保持下去。 所以在任何情況下都盡可能不要放開編譯上的約束。接著,將接口和實(shí)現(xiàn)分離,其他工程只依賴接口而不依賴實(shí)現(xiàn),這樣的邊界效果更好。當(dāng)然破壞無處不在,例如遇到某個緊急需求要某模塊新增若干接口,就可能出現(xiàn)跳過接口直接依賴實(shí)現(xiàn)工程進(jìn)行開發(fā)的情況。這時可以考慮通過代碼的審查進(jìn)行監(jiān)督,也可以通過開發(fā)簡單的編譯腳本,檢查是否有不當(dāng)依賴產(chǎn)生。

劃定模塊邊界的細(xì)節(jié)問題

當(dāng)對代碼進(jìn)行解耦時,即便大體上的模塊職責(zé)劃分已經(jīng)清晰,但因?yàn)槟K間的各種業(yè)務(wù)關(guān)系,細(xì)節(jié)上仍會遇到糾纏不清的情況。事實(shí)上,因?yàn)樾枨蠹肮δ艿牟煌]有哪一種模塊劃分的規(guī)則是完全適用于每個應(yīng)用的。隨著業(yè)務(wù)的發(fā)展和變化,模塊邊界出現(xiàn)不合適的情況完全符合預(yù)期。

那么如何讓模塊劃分更讓大家覺得合理,或者說當(dāng)遇到一個兩難選擇時,按照什么樣的方式大家會更好理解?我們建議的方法其實(shí)也很簡單:試著對代碼“講一個符合邏輯的故事”,哪個故事講得通,你就可以將之作為拆分的選擇。因?yàn)榇a解耦從來不是問題,糾結(jié)的只是解耦行為能不能讓人理解。例如一些模塊間通信用的數(shù)據(jù)結(jié)構(gòu)究竟屬于那個模塊的問題就可以用這種方式仲裁。在糾結(jié)的時候,能自圓其說的方案往往就足夠了。我們要盡力避免的,應(yīng)該是隨意拼湊和單純?yōu)榱祟愋徒怦疃怦畹那闆r。

模塊的一般組織方式

設(shè)計(jì)一個模塊,我們有一個一般性的組織方式,可以將模塊分成三個工程:implementation工程、api工程、library工程。

implementation工程提供邏輯的實(shí)現(xiàn)。api工程提供對外的接口和數(shù)據(jù)結(jié)構(gòu)。library工程,則提供該模塊的一些工具類。

從另一個角度看,implementation工程實(shí)際上是和應(yīng)用的狀態(tài)、生命周期相關(guān)的,它的執(zhí)行依賴于各種應(yīng)用狀態(tài)。而library工程則不關(guān)心這些狀態(tài)。因此也可以看做library提供某種功能,implementation則是如何運(yùn)用這種功能。例如,我們實(shí)現(xiàn)一個表情模塊,library工程提供表情的資源、表情的渲染和播放能力,api工程提供了使用表情的服務(wù)接口,implementation工程則提供了api的實(shí)現(xiàn),及何時開始加載表情資源、緩存管理、以及其他表情功能例如商店等等。

當(dāng)然,這是一個指導(dǎo)性的建議,很多時候library工程和api工程之間沒有明顯邊界也很正常。但強(qiáng)烈建議至少要有implementation工程和api工程。

分析依賴關(guān)系的工具

解耦代碼時,快速分析代碼的依賴關(guān)系能很好的提升工作效率。Android Studio提供了一個不錯的工具。

圖21 - Analyze dependency工具

文件、資源以及工程,都可以進(jìn)行依賴分析。有了分析結(jié)果,接下來一步一步把代碼分離就簡單多了。

***

重構(gòu)整體架構(gòu)不是一件容易事,通常也不太可能讓整個團(tuán)隊(duì)停下來只做重構(gòu)。所以一直以來微信的重構(gòu)都是隨著版本迭代進(jìn)行“拆分”-> “灰度” -> “回流”的循環(huán)節(jié)奏。

“設(shè)計(jì)系統(tǒng)的組織,其產(chǎn)生的設(shè)計(jì)和架構(gòu)等價于組織間的溝通結(jié)構(gòu)”。對于微信幾年間走過的路程,時至今日團(tuán)隊(duì)內(nèi)的溝通形式還可以做到較多的直接溝通。這些情況決定了微信如今的技術(shù)選擇。所以在方案選擇上我們就更愿意尋求相對簡單合適的方式解決問題——用純粹的模塊化保持后續(xù)架構(gòu)的靈活性和健壯性,重新強(qiáng)調(diào)依賴、強(qiáng)調(diào)應(yīng)用狀態(tài)和生命周期、強(qiáng)化代碼的邊界。

除了代碼上的設(shè)計(jì),代碼之外我們也做了些努力。我們認(rèn)同代碼審查的意義,也開始推行模塊負(fù)責(zé)人的審查機(jī)制。此外我們還打算強(qiáng)化文檔的使用,當(dāng)然這個還在規(guī)劃中。

原文鏈接:https://www.qcloud.com/community/article/794491,作者:carlguo

【本文是51CTO專欄作者“騰訊云技術(shù)社區(qū)”的原創(chuàng)稿件,轉(zhuǎn)載請通過51CTO聯(lián)系原作者獲取授權(quán)】

 

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 騰訊云
相關(guān)推薦

2017-08-08 16:07:57

Android 模塊化架構(gòu)

2017-05-18 11:43:41

Android模塊化軟件

2015-07-02 13:21:44

模塊化數(shù)據(jù)中心

2013-08-20 16:45:22

重構(gòu)Web App模塊化

2010-05-28 10:31:28

模塊化IT

2016-12-14 14:50:26

CSS預(yù)處理語言模塊化實(shí)踐

2010-02-03 09:01:01

Java動態(tài)模塊化

2019-08-28 16:18:39

JavaScriptJS前端

2021-10-11 09:51:37

模塊化UPS架構(gòu)

2017-02-13 18:46:38

Android模塊化組件化

2016-11-08 20:31:19

同方服務(wù)器模塊化

2023-06-28 08:12:49

Python代碼重構(gòu)

2022-01-10 08:43:25

CanonicalSnap應(yīng)用Linux

2017-06-09 12:58:20

微信小程序架構(gòu)分析

2021-12-24 07:10:36

架構(gòu)分層模塊化

2017-07-11 11:02:03

APP模塊化架構(gòu)

2013-08-20 15:31:18

前端模塊化

2017-05-18 10:23:55

模塊化開發(fā)RequireJsJavascript

2020-09-17 10:30:21

前端模塊化組件

2015-10-10 11:29:45

Java模塊化系統(tǒng)初探
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號