時代演進,技術也隨之發展。到今天,APP已然成爲絕大多數互聯網企業用來獲取用戶的核心渠道。與此同一時候,伴隨着業務量的增加,越來越大、越來越多的APP也在不斷地、持續地挑戰着每一個移動端研發人員的知識深度,而咱們的移動端技術人員也在這個不斷接受挑戰的過程當中,成就了今天的移動互聯網時代。餓了麼移動APP就是這樣一個挑戰,多用戶量、多業務量,在接受着不少其它更挑剔用戶的同一時候,默默地、不斷地演進着移動端的架構。編程
咱們常說,脫離業務談架構就是純粹的刷流氓。餓了麼移動APP的發展也是其業務發展的一面鏡子。網絡
在餓了麼業務發展的早期。移動APP經歷從無到有的階段。爲了高速上線搶佔市場,傳統移動APP開發的MVC架構成了「短平快」思路的首選:數據結構
這樣的架構以層次結構簡單清晰。代碼easy開發而被大多數人所接受。架構
在MVC的體系架構中,Controller層負責整個APP中主要邏輯功能的實現;Model層則負責數據結構的描寫敘述以及數據持久化的功能;而View層做爲展示層負責渲染整個APP的UI。框架
分工清晰,簡潔明瞭;並且這樣的系統架構在語言框架層就獲得了Apple的支持,因此很適用於APP的startup開發。工具
而後,這樣的架構在開發的後期會由於其超高耦和性,從而造就龐大Controller層。而這也是一直被人所詬病。終於的MVC都從Model-View-Controller走向了Massive-View-Controller 的終點。組件化
「短平快」的MVC架構幫助餓了麼移動APP高速搶佔了市場。post
而隨着代碼量的不斷添加。臃腫的Controller層也在漸露頭角。而業務上。餓了麼移動APP也從單一APP發展爲多APP齊頭並進的格局。這時候,假設減小耦合,複用已有模塊成了架構的第一要務。性能
架構中,模塊複用的第一要求即是代碼的功能組件化。組件化意味着擁有獨立功能的代碼從系統中進行抽象並剝離,再以「插件」的形式插回原有系統中。這樣剝離出來的功能組件,便可以供其它APP進行使用,從而減小系統中模塊與模塊之間的耦和性;也同一時候提升了APP之間代碼的複用性。動畫
餓了麼移動對於組件有兩種定義:公有組件和業務組件。公有組件指的是封裝得比較好的一些SDK。包括一些第三方組件和本身內部使用的組件。如iOS中最著名的網絡SDK AFNetworking,Android下OKHttp。都是這類組件的表明。而對於業務組件,則定義爲包括了一系列業務功能的整體,好比登陸業務組件。註冊業務組件,即爲此類組件的典型表明。
對於公有組件,餓了麼移動採取了版本號化的管理方式,而這在iOS和Android平臺上也早有比較成熟的解決方式。好比,對於iOS平臺,CocoaPods基本上成爲了代碼組件化管理的標配。在Android平臺上,Gradle也是很是成熟和穩健的方案。採用以上管理工具的還有一個緣由在於,對企業開發而言,代碼也是一種商業機密。基於保密性的目的,支持內網搭建私有server成爲了必需。以上的管理工具均可以很是好地支持這些操做。
對於業務的組件化。咱們採取了業務模塊註冊機制的方式來達到解耦合的目的。每個業務模塊對外提供對應的業務接口,同一時候在系統啓動的時候向Excalibur系統註冊本身模塊的Scheme(Excalibur是餓了麼移動用來保存Scheme與模塊之間映射的系統,同一時候能依據Scheme進行Class反射返回)。 當其它業務模塊對該業務模塊有依賴時。從Excalibur系統中獲取相關實例,並調用對應接口來實現調用,從而實現了業務模塊之間的解耦目的。
而在業務組件,即業務模塊的內部,則可以依據不一樣開發者的偏好,來實現不一樣的代碼架構。如現在討論得比較火的MVVM, MVP等,都可以在模塊內部進行而不影響整體系統架構。
這時候的架構看起來更像是這樣:
這樣的E(Excalibur)M(Modules)C(Common)架構以高內聚、低耦合爲基本的特色。以面向接口編程爲出發點。減小了模塊與模塊之間的聯繫。
該架構的另一大優勢則在於攻克了不一樣系統版本號的兼容性問題。這裏舉iOS平臺下的WebView做爲樣例來進行說明。Apple從iOS8系統開始提供了一套更好的Web支持框架——WebKit。但在iOS7系統下卻沒法兼容,從而致使Crash。使用此類架構,可以在iOS7系統下仍然註冊使用傳統的WebView來渲染網頁,而在iOS8及其以上系統註冊WebKit來做爲渲染網頁的內核。即避免了Apple嚴格的審覈機制。又達到了動態載入的目的。
移動APP的開發有兩種不一樣的路線。Native APP和Web APP。
這兩種路線的差異相似於PC時代開發應用程序時的C/S架構和 B/S架構。
以上咱們談到的都屬於典型的Native APP,即所有的程序都由本地組件渲染完畢。這類APP長處是顯而易見的,渲染速度快、用戶體驗好。缺點同一時候也十分突出:出現了錯誤必定要等待下一次用戶進行APP更新才能夠修復。
Web APP的長處剛好就是Native APP的缺點所在,其頁面全部採用H5撰寫並存放在server端。每次進行頁面渲染時都從server請求最新的頁面。一旦頁面有錯誤server端進行更新便能立馬解決。
只是其弊端也easy窺見:每次頁面都需要請求server。形成渲染時等待時間過長。從而致使的用戶體驗不夠完美,並且性能上較Native APP慢了1-2個數量級;與此同一時候還會致使不少其它的用戶流量消耗。還有一個缺點則在於,Web APP在移動端上調用本地的硬件設備存在必定的不便。只是這些弊端也都有對應的解決方式,如PhoneGap將網頁提早打包在本地以下降網絡的請求時間;同一時候也提供一系列的插件來訪問本地的硬件設備。
然而,雖然如此。其渲染速度上仍是會略微存在必定的差距。
Hybrid APP則是綜合了兩者優缺點的解決方式。
餓了麼移動對於此二類APP的觀點在於,純粹展現性的模塊會更適合使用Web頁面來達到渲染的目的;而不少其它的數據操做性、動畫渲染性的模塊則更適合採用Native的方式。
基於以前的EMC架構,咱們將部分模塊又一次進行了架構:
Hybrid-EMC架構中。Web做爲一個子模塊,註冊增長到整個系統中。從而實現讓業務上需要高速迭代的模塊達到實時更新的效果。
通過這些年的業務發展,Hybrid提供的展現界面更新方案也逐漸地沒法知足APP更新迭代的需要。
所以愈來愈多的動態部署的方案被提了出來,比方iOS下的JSPatch, waxPatch。Android下的Dexpose,AndFix, ClassLoader。都是比較成熟Hot Patch動態部署解決方式。
這些方案的思路都是經過下載遠程server的代碼來動態更新本地的代碼行爲。
React-Native則屬於還有一種動態部署的方案,其核心原理在於經過JavaScript來調用本地組件進行界面的渲染。
而餓了麼移動APP發展到今天。各個APP綜合用戶量已通過億。所以一個很小的Bug所帶來的問題均可能會直接影響到幾萬人的使用。爲了保證APP的穩定性和健壯性,Hot Patch方案也就成了當下最有待解決的問題。
依據80%的用戶訪問20%頁面這一80/20原則,保證這20%訪問最頻繁的頁面的穩定性就是保證了80%的APP的穩定性。所以,餓了麼移動對於部分訪問最頻繁的模塊進行了React-Native備份。
當這部分頁面出現故障時,APP可以經過server的配置,本身主動切換成React-Native的備份頁面。而與此同一時候開發者開發一個小而精的Hot Patch來修復出現的問題。當Hot Patch完畢修補後。再切換回Native APP的原生功能。
這時候的架構看起來會像是這樣:
HotPatch-EMC的架構主要目標在於解決移動APP的穩定性問題。經過RN與Native的主備,可以下降系統APP出錯帶來的失誤成本。
咱們都知道。對於軟件project來講,這世上沒有銀彈。對於架構而言事實上也很的適用。業務的不斷更新,帶來了餓了麼移動APP架構的不斷演進。
架構沒有真正的好壞之分。僅僅要適用於本身的業務,就是好的架構!
原文連接:http://www.jianshu.com/p/2141fb0dc62c