餓了么移動APP的架構(gòu)演進(jìn)

0 引言

時代演進(jìn)国旷,技術(shù)也隨之發(fā)展匿级。到今天,APP已然成為絕大多數(shù)互聯(lián)網(wǎng)企業(yè)用來獲取用戶的核心渠道椭豫。與此同時贩耐,伴隨著業(yè)務(wù)量的增長弧腥,愈來愈大、愈來愈多的APP也在不斷地潮太、持續(xù)地挑戰(zhàn)著每一個移動端研發(fā)人員的知識深度管搪,而我們的移動端技術(shù)人員也在這個不斷接受挑戰(zhàn)的過程中,成就了今天的移動互聯(lián)網(wǎng)時代铡买。餓了么移動APP就是這樣一個挑戰(zhàn)更鲁,多用戶量、多業(yè)務(wù)量奇钞,在接受著更多更挑剔用戶的同時澡为,默默地、不斷地演進(jìn)著移動端的架構(gòu)蛇券。

1 MVC

我們常說缀壤,脫離業(yè)務(wù)談架構(gòu)就是純粹的刷流氓樊拓。餓了么移動APP的發(fā)展也是其業(yè)務(wù)發(fā)展的一面鏡子。

在餓了么業(yè)務(wù)發(fā)展的早期塘慕,移動APP經(jīng)歷從無到有的階段筋夏。為了快速上線搶占市場,傳統(tǒng)移動APP開發(fā)的MVC架構(gòu)成了“短平快”思路的首選:

圖1 MVC架構(gòu)

這種架構(gòu)以層次結(jié)構(gòu)簡單清晰图呢,代碼容易開發(fā)而被大多數(shù)人所接受条篷。

在MVC的體系架構(gòu)中,Controller層負(fù)責(zé)整個APP中主要邏輯功能的實現(xiàn)蛤织;Model層則負(fù)責(zé)數(shù)據(jù)結(jié)構(gòu)的描述以及數(shù)據(jù)持久化的功能赴叹;而View層作為展現(xiàn)層負(fù)責(zé)渲染整個APP的UI。分工清晰指蚜,簡潔明了乞巧;并且這種系統(tǒng)架構(gòu)在語言框架層就得到了Apple的支持,所以非常適用于APP的startup開發(fā)摊鸡。

然后绽媒,這種架構(gòu)在開發(fā)的后期會由于其超高耦和性,從而造就龐大Controller層免猾,而這也是一直被人所詬病是辕。最終的MVC都從Model-View-Controller走向了Massive-View-Controller 的終點。

2 Module Decoupled

“短平快”的MVC架構(gòu)幫助餓了么移動APP快速搶占了市場猎提。而隨著代碼量的不斷增加获三,臃腫的Controller層也在漸露頭角;而業(yè)務(wù)上锨苏,餓了么移動APP也從單一APP發(fā)展為多APP齊頭并進(jìn)的格局疙教。這時候,如果降低耦合蚓炬,復(fù)用已有模塊成了架構(gòu)的第一要務(wù)松逊。

架構(gòu)中,模塊復(fù)用的第一要求便是代碼的功能組件化肯夏。組件化意味著擁有獨立功能的代碼從系統(tǒng)中進(jìn)行抽象并剝離经宏,再以“插件”的形式插回原有系統(tǒng)中。這樣剝離出來的功能組件驯击,便可以供其他APP進(jìn)行使用烁兰,從而降低系統(tǒng)中模塊與模塊之間的耦和性;也同時提高了APP之間代碼的復(fù)用性徊都。

餓了么移動對于組件有兩種定義:公有組件和業(yè)務(wù)組件沪斟。公有組件指的是封裝得比較好的一些SDK,包括一些第三方組件和自己內(nèi)部使用的組件。如iOS中最著名的網(wǎng)絡(luò)SDK AFNetworking主之,Android下OKHttp择吊,都是這類組件的代表。而對于業(yè)務(wù)組件槽奕,則定義為包含了一系列業(yè)務(wù)功能的整體几睛,例如登錄業(yè)務(wù)組件,注冊業(yè)務(wù)組件粤攒,即為此類組件的典型代表所森。

對于公有組件,餓了么移動采取了版本化的管理方式夯接,而這在iOS和Android平臺上也早有比較成熟的解決方案焕济。例如,對于iOS平臺盔几,CocoaPods基本上成為了代碼組件化管理的標(biāo)配晴弃;在Android平臺上,Gradle也是非常成熟和穩(wěn)健的方案问欠。采用以上管理工具的另一個原因在于肝匆,對企業(yè)開發(fā)而言,代碼也是一種商業(yè)機(jī)密顺献。基于保密性的目的枯怖,支持內(nèi)網(wǎng)搭建私有服務(wù)器成為了必需注整。以上的管理工具都能夠很好地支持這些操作。

對于業(yè)務(wù)的組件化度硝,我們采取了業(yè)務(wù)模塊注冊機(jī)制的方式來達(dá)到解耦合的目的肿轨。每個業(yè)務(wù)模塊對外提供相應(yīng)的業(yè)務(wù)接口,同時在系統(tǒng)啟動的時候向Excalibur系統(tǒng)注冊自己模塊的Scheme(Excalibur是餓了么移動用來保存Scheme與模塊之間映射的系統(tǒng)蕊程,同時能根據(jù)Scheme進(jìn)行Class反射返回)椒袍。 當(dāng)其他業(yè)務(wù)模塊對該業(yè)務(wù)模塊有依賴時,從Excalibur系統(tǒng)中獲取相關(guān)實例藻茂,并調(diào)用相應(yīng)接口來實現(xiàn)調(diào)用驹暑,從而實現(xiàn)了業(yè)務(wù)模塊之間的解耦目的。

而在業(yè)務(wù)組件辨赐,即業(yè)務(wù)模塊的內(nèi)部优俘,則可以根據(jù)不同開發(fā)人員的偏好,來實現(xiàn)不同的代碼架構(gòu)掀序。如現(xiàn)在討論得比較火的MVVM, MVP等帆焕,都可以在模塊內(nèi)部進(jìn)行而不影響整體系統(tǒng)架構(gòu)。

這時候的架構(gòu)看起來更像是這樣:

圖2 EMC架構(gòu)

這種E(Excalibur)M(Modules)C(Common)架構(gòu)以高內(nèi)聚不恭、低耦合為主要的特點叶雹,以面向接口編程為出發(fā)點财饥,降低了模塊與模塊之間的聯(lián)系。

該架構(gòu)的另外一大好處則在于解決了不同系統(tǒng)版本的兼容性問題折晦。這里舉iOS平臺下的WebView作為例子來進(jìn)行說明佑力。Apple從iOS8系統(tǒng)開始提供了一套更好的Web支持框架——WebKit,但在iOS7系統(tǒng)下卻無法兼容筋遭,從而導(dǎo)致Crash打颤。使用此類架構(gòu),可以在iOS7系統(tǒng)下仍然注冊使用傳統(tǒng)的WebView來渲染網(wǎng)頁漓滔,而在iOS8及其以上系統(tǒng)注冊WebKit來作為渲染網(wǎng)頁的內(nèi)核编饺。即避免了Apple嚴(yán)格的審核機(jī)制,又達(dá)到了動態(tài)加載的目的响驴。

3 Hybrid

移動APP的開發(fā)有兩種不同的路線透且,Native APP和Web APP。這兩種路線的區(qū)別類似于PC時代開發(fā)應(yīng)用程序時的C/S架構(gòu)和 B/S架構(gòu)豁鲤。

以上我們談到的都屬于典型的Native APP秽誊,即所有的程序都由本地組件渲染完成。這類APP優(yōu)點是顯而易見的琳骡,渲染速度快锅论、用戶體驗好;缺點同時也十分突出:出現(xiàn)了錯誤一定要等待下一次用戶進(jìn)行APP更新才能夠修復(fù)楣号。

Web APP的優(yōu)點恰好就是Native APP的缺點所在最易,其頁面全部采用H5撰寫并存放在服務(wù)器端。每次進(jìn)行頁面渲染時都從服務(wù)器請求最新的頁面炫狱。一旦頁面有錯誤服務(wù)器端進(jìn)行更新便能立刻解決藻懒。不過其弊端也容易窺見:每次頁面都需要請求服務(wù)器,造成渲染時等待時間過長视译,從而導(dǎo)致的用戶體驗不夠完美嬉荆,并且性能上較Native APP慢了1-2個數(shù)量級;與此同時還會導(dǎo)致更多的用戶流量消耗酷含。另一個缺點則在于鄙早,Web APP在移動端上調(diào)用本地的硬件設(shè)備存在一定的不便。不過這些弊端也都有相應(yīng)的解決方案第美,如PhoneGap將網(wǎng)頁提前打包在本地以減少網(wǎng)絡(luò)的請求時間蝶锋;同時也提供一系列的插件來訪問本地的硬件設(shè)備。然而什往,盡管如此扳缕,其渲染速度上還是會稍微存在一定的差距。

Hybrid APP則是綜合了二者優(yōu)缺點的解決方案。餓了么移動對于此二類APP的觀點在于躯舔,純粹展示性的模塊會更適合使用Web頁面來達(dá)到渲染的目的驴剔;而更多的數(shù)據(jù)操作性、動畫渲染性的模塊則更適合采用Native的方式粥庄。

基于之前的EMC架構(gòu)丧失,我們將部分模塊重新進(jìn)行了架構(gòu):

圖3 Hybrid-EMC架構(gòu)

Hybrid-EMC架構(gòu)中,Web作為一個子模塊惜互,注冊加入到整個系統(tǒng)中布讹,從而實現(xiàn)讓業(yè)務(wù)上需要快速迭代的模塊達(dá)到實時更新的效果。

4 React-Native & Hot Patch

經(jīng)過這些年的業(yè)務(wù)發(fā)展训堆,Hybrid提供的展示界面更新方案也逐漸地?zé)o法滿足APP更新迭代的需要描验。因此越來越多的動態(tài)部署的方案被提了出來,比如iOS下的JSPatch, waxPatch坑鱼,Android下的Dexpose,AndFix, ClassLoader膘流,都是比較成熟Hot Patch動態(tài)部署解決方案。這些方案的思路都是通過下載遠(yuǎn)程服務(wù)器的代碼來動態(tài)更新本地的代碼行為鲁沥。

React-Native則屬于另一種動態(tài)部署的方案呼股,其核心原理在于通過JavaScript來調(diào)用本地組件進(jìn)行界面的渲染。

而餓了么移動APP發(fā)展到今天画恰,各個APP綜合用戶量已經(jīng)過億彭谁。因此一個非常小的Bug所帶來的問題都可能會直接影響到幾萬人的使用。為了保證APP的穩(wěn)定性和健壯性阐枣,Hot Patch方案也就成了當(dāng)下最有待解決的問題马靠。

根據(jù)80%的用戶訪問20%頁面這一80/20原則,保證這20%訪問最頻繁的頁面的穩(wěn)定性就是保證了80%的APP的穩(wěn)定性蔼两。因此,餓了么移動對于部分訪問最頻繁的模塊進(jìn)行了React-Native備份逞度。當(dāng)這部分頁面出現(xiàn)問題時额划,APP可以通過服務(wù)器的配置,自動切換成React-Native的備份頁面档泽;而與此同時開發(fā)人員開發(fā)一個小而精的Hot Patch來修復(fù)出現(xiàn)的問題俊戳。當(dāng)Hot Patch完成修補后,再切換回Native APP的原生功能馆匿。

這時候的架構(gòu)看起來會像是這樣:

圖4 HotPatch-EMC架構(gòu)

HotPatch-EMC的架構(gòu)主要目標(biāo)在于解決移動APP的穩(wěn)定性問題抑胎。通過RN與Native的主備,可以減少系統(tǒng)APP出錯帶來的失誤成本渐北。

5 結(jié)語

我們都知道阿逃,對于軟件工程來說,這世上沒有銀彈。對于架構(gòu)而言其實也非常的適用恃锉。業(yè)務(wù)的不斷更新搀菩,帶來了餓了么移動APP架構(gòu)的不斷演進(jìn)。

架構(gòu)沒有真正的好壞之分破托,只要適用于自己的業(yè)務(wù)肪跋,就是好的架構(gòu)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末土砂,一起剝皮案震驚了整個濱河市州既,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萝映,老刑警劉巖吴叶,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锌俱,居然都是意外死亡晤郑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門贸宏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來造寝,“玉大人,你說我怎么就攤上這事吭练〗肓” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵鲫咽,是天一觀的道長签赃。 經(jīng)常有香客問我,道長分尸,這世上最難降的妖魔是什么锦聊? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮箩绍,結(jié)果婚禮上孔庭,老公的妹妹穿的比我還像新娘。我一直安慰自己材蛛,他們只是感情好圆到,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卑吭,像睡著了一般芽淡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豆赏,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天挣菲,我揣著相機(jī)與錄音富稻,去河邊找鬼。 笑死己单,一個胖子當(dāng)著我的面吹牛唉窃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纹笼,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纹份,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了廷痘?” 一聲冷哼從身側(cè)響起蔓涧,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笋额,沒想到半個月后元暴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡兄猩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年茉盏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枢冤。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸠姨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淹真,到底是詐尸還是另有隱情讶迁,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布核蘸,位于F島的核電站巍糯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏客扎。R本人自食惡果不足惜祟峦,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望徙鱼。 院中可真熱鬧搀愧,春花似錦、人聲如沸疆偿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杆故。三九已至,卻和暖如春溉愁,著一層夾襖步出監(jiān)牢的瞬間处铛,已是汗流浹背饲趋。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留撤蟆,地道東北人奕塑。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像家肯,于是被迫代替她去往敵國和親龄砰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容