我對移動端架構的思考

本文由玉剛說寫做平臺提供寫做贊助前端

原做者:Mr.Sreact

版權聲明:本文版權歸微信公衆號玉剛說全部,未經許可,不得以任何形式轉載android

架構就像是一場進化史,根據不一樣時期的需求,演變出不一樣的架構,車輪滾滾,到今天,移動端框架百花齊放,讓人應接不暇。可是其中的本質是磨滅不了的,換言之根本沒有磨滅而是隱藏到了人們所看不到的地方,可是依舊發揮着不可或缺的做用。ios

爲何須要架構?數據庫

  • 一個Activity走天下,包含各類模塊和功能
  • 臃腫類太多
  • 不一樣功能,不一樣層次拎不清楚,混合在一塊兒
  • 重複代碼太多,複用性爲差
  • 沒法協做開發,
  • 耦合嚴重,bug太多 等等

當咱們新進一個公司,接受別人的項目的時候,基本都會說句MMP,SHI同樣的代碼啊,啥玩意啊,搞得什麼啊。編程

我擦,我就改了一個參數,怎麼全亂套了,一個功能怎麼天上地下都須要改啊。服務器

沒有經受過痛苦的人,是不會想了解架構的,只有痛苦過的人,纔會急切的瞭解架構,好好作人,不做孽。微信

進化1.0 MVC架構

人們剛接觸編程,相信第一個遇到的框架就是MVC,無論你經意仍是不經意寫出來的Android程序他就是MVC框架,只不過是MVC框架的某一個變種(最混亂的那種)。Android系統自己就根據MVC建造的。併發

  • XML的View層
  • Activity/Fragment的Controller層
  • 數據Model層。

咱們編寫程序剛開始應該是這種結構

image.png

View層和Controller交織在一塊兒。在Activity裏面處理各類事件和邏輯,界面的顯示和更新都在這裏,除了按功能分出去的模塊外,能在Activity裏面寫的都會堆在這裏面,代碼經常達到上千行,別說別人,本身再回到頭看的時候也是頭皮發發麻。

因此咱們開始試着學Android系統的MVC來梳理代碼。固然每一個人從衆理解的也不大同樣。 無論是單向依賴仍是雙向依賴都是爲了把處理的職責交給Controller,這一點是不變的,因此無論你用的是哪種形式都是不打緊的,沒有對與錯。根據本身的需求選擇最適合的一種依賴關係。

image.png

優勢:

因爲MVC很好的分離了視圖層和業務層,因此它具備如下優勢

  • 耦合性低
  • 開發速度快
  • 可維護性高
  • 易於理解
缺點:
  • 因爲MVC的設計思想是從Model出發,而沒有考慮到View端的複雜性,這樣致使的問題是Model難以符合複雜多變的View端變化。致使Model的做用很小,而不少View層的職責也轉移到了Controller層。Controller變得臃腫不堪。耦合性也變高了。
  • 測試困難

MVC使用的誤區

其實我在剛開始編程的時候,

誤區一:一度認爲Model就是實體類(Entity)

正解:是MVC的Model應該有兩個功能:

  • 處理業務邏輯
  • 提供View顯示的數據
誤區二:把業務邏輯所有放在Controller端

正解:Model也會處理業務邏輯

這兩個誤區其實也和MVC的構成有關係,很容易讓人誤解,可是本質上仍是不理解MVC,特別是對Model的做用不明白。

其實Model在MVC框架裏面的做用不只僅是Entry,Model在MVC中起着很重要的做用,它更應該是業務邏輯的真正實現層,而Controller層更應該做爲一個橋接的做用,把View的求情轉發給Model,再把Model處理結束的消息告訴View。這樣作也就是界面和代碼(邏輯)分離。

進化2.0 MVP

可是踏入誤區的人太多了,你們都在Activity裏面處理邏輯由於太方便了(寫的很爽)。 可是這樣以後,咱們Activity的職責太多了,耦合也嚴重,因此咱們就想着怎麼能給Activity減負,同時把耦合也降下來,因此就想找個哥們來替Activity分擔的責任,你們最後都只有一個責任,各層關係也相對好理解,你們照着這個方式寫,那多好,不用加班,每天都很快樂。

既然Activty這麼願意和View搞到一塊兒(解耦過高了),那麼就讓他們倆在一塊兒(在一塊兒,在一塊兒,在一塊兒),共同負責View,咱們在招聘一個職業經理人(Presenter)來處理事務,有啥事都找Presenter,你看着多方便啊,MVP是一個真正意義上的隔離View的細節和複雜性的模式

image.png

至於虛線的部分,這個和樓上的MVC的虛線同樣,每一個人的理解不一樣,狀況不一樣,選擇合適的就好,不用糾結誰對對錯,本質不變就能夠的。

這樣就簡單多了,Activity和View兩人各類膩歪秀恩愛,各層的關係也一目瞭然,你們各幹各的事情,想要什麼和Presenter說一聲,有啥事情Presenter也會彙報,簡直爽的不要不要的。Presenter也會處理和View層的交互,Presenter在手天下我有。

優勢:

一、模型與視圖徹底分離(就像牛郎和和織女隔了一個銀河,每次都須要靠燕子來傳信,好可憐~~)

二、能夠更高效地使用模型,由於全部的交互都發生在一個地方——Presenter內部

三、(Presener的複用)一個Presener能夠用於多個視圖(View),而不須要改變Presenter的邏輯。視圖(View)的變化比模型(Model)的變化更頻繁的多 ,因此這樣超級方便。

四、(View的複用)View能夠進行組件化。在MVP當中,View不依賴Model。這樣就可讓View從特定的業務場景中脫離出來,能夠說View能夠作到對業務邏輯徹底無知。它只須要提供一系列接口提供給上層操做。這樣就能夠作高度可複用的View組件。

五、更容易單元測試

缺點:

一、因爲對視圖的渲染放在了Presenter中,因此視圖View和Presenter的交互會過於頻繁。特別是須要修改視圖的時候,Presenter也須要跟着修改,很麻煩。

二、Presenter中除了業務邏輯之外,還有大量的View->Model,Model->View的手動同步邏輯,形成Presenter比較笨重,維護起來會比較困難。

三、其實總的來講就是結構很清晰,業務邏輯也很明白,耦合低,可是就是本身寫的麻煩,Presenter很差維護,工做量太大,太笨重,有點像MVC中的Activity了,職責太多了。也能夠把這三個缺點總結成一句話,麻煩,尾大不掉。

進化3.0 MVVM

可是吧,大家爽了Presenter可就累壞了,大事小事都要通過Presenter,就連放個屁也要Presenter來扒褲子,日子過得久了,Presenter總會有意見啊,不帶這麼使喚人的。

咱們就想啊,之前過多的依賴Activity形成結構混亂,耦合過高,後來有了Presenter,雖然耦合大大下降,可是仍是過於依賴Presenter,爲啥總會過於依賴某一個東西呢,就不能你們都乾點活,耦合性也不高的嗎?就不能你們有事相互通知嗎?非要那麼懶依賴別人嗎?總要有點正能量吧。那麼咱們就把Presenter辭退,引入了一個新的小夥伴VM(ViewModel即 Model of View)它即包含了Modle也有View的狀態。

MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView接口,而是徹底的和View綁定,全部View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。

這種自動同步的緣由其實就是是ViewModel中的屬性都實現了observable這樣的接口,也就是說當使用屬性的set的方法,都會同時觸發屬性修改的事件,使綁定的UI自動刷新。

在android中DataBinding幫助咱們實現MVVM,在XML進行數據綁定,增長了XML的重量,再也不像之前那樣僅僅是佈局,均衡了各部分的職責。

因此MVVM比MVP更升級一步,在MVP中,V是接口IView, 解決對於界面UI的耦合; 而MVVM乾脆直接使用ViewModel和UI無縫結合, ViewModel直接就能表明UI.

image.png

優勢:

一、解決了MVP大量的手動View和Model同步的問題,提供雙向綁定機制。提升了代碼的可維護性。大大方便了開發者。(只有試過才知道有多方便)

二、簡化測試。

三、響應式編程更方便。

缺點:

一、過於簡單的圖形界面顯得大材小用(讓開發者麻煩的都是缺點)

二、視圖狀態較多,ViewModel的構建和維護的成本都會比較高。

三、數據綁定的聲明是指令式地寫在View的模版當中的,這些內容是沒辦法去打斷點debug的。(這是很碉堡的,只能本身細心了)

進化4.0 CLEAN

進化了一代有一點,做爲東家的谷歌坐不住了,給不給我面子了,來來來,我給大家一個終結的,Clean? WTF?這個洋蔥一個的傢伙是誰?再給你一個圈就是五環了~~四個圈圈了不得啊?

image.png

官方的話說來就是:獨立

  • 獨立於框架。該體系結構不依賴於某些特徵庫軟件庫的存在。這容許您將此類框架用做工具,而沒必要將您的系統塞入其有限的約束中。 可測試。能夠在沒有UI,數據庫,Web服務器或任何其餘外部元素的狀況下測試業務規則。
  • 獨立於UI。UI能夠輕鬆更改,而無需更改系統的其他部分。例如,可使用控制檯UI替換Web UI,而無需更改業務規則。
  • 獨立於數據庫。您能夠換掉Oracle或SQL Server,用於Mongo,BigTable,CouchDB或其餘東西。您的業​​務規則未綁定到數據庫。
  • 獨立於任何外部機構。事實上,您的業務規則根本不瞭解外部世界。
依賴規則:

同心圓表明軟件的不一樣領域。通常來講,你走的越遠,軟件就越高。外圈是機制。內圈是政策。

使這種架構工做的首要規則是依賴規則。此規則代表源代碼依賴項只能指向內部。內圈中沒有任何東西能夠對外圈中的某些東西一無所知。特別是,內圈中的代碼不得說起在外圈中聲明的內容的名稱。這包括功能,類。變量或任何其餘命名的軟件實體。外圈中使用的數據格式不該該被內圈使用,特別是若是這些格式是由外圈中的框架生成的話。咱們不但願外圈中的任何東西影響內圈。

官方的話就是繞,其實就是依賴是能向裏依賴,白話就是內圈向外圈提供服務,好比你去食堂吃飯,選擇不一樣的窗口,對着裏面喊到給我來一份魚香肉絲。你不用管裏面的師傅是否是昨天那一個,也不用管裏面的菜是否是昨天的那個口味,你只管你的目的是來一份魚香肉絲就能夠了,裏面的菜和師傅,也不用管你是誰,是否是個漂亮的MM,他們只管本身事情,對他們圈外的不依賴,反正你依賴我就能夠了。

image.png

Clean將核心業務(Domain層)、UI相關(Presenter層)以及數據加載(Data層)彼此獨立開來,不一樣的層之間由接口依次鏈接起來,但卻又彼此不瞭解彼此的具體實現。

優勢:

一、代碼複用性更高 二、更易於測試 三、耦合度更小

缺點:

一、學習難度大(容易懵逼) 二、代碼量大(一個小Demo都夠你寫一壺了)

從MVC->MVP->MVVM->MVP-Clean 後者解決了前者遺留的問題,把前者的缺點優化成了優勢。一代更比一代強,可是都是須要代價的,學習成本更高,更加規範,可是並不必定就誰比誰更好,只有誰更適合你的項目,都有優劣,怎麼選擇須要靠本身了。 其實MVX系列的本質一直未變:

  • 關注點分離原則
  • 高內聚低耦合原則

同時也但願適度設計,不要太過追求某一點。會得不償失。找到最經濟的方案纔是王道,也能夠多種方案配合一塊兒配合。

image.png

如何可以更好的將多種架構表如今一款APP裏面呢?對!組件化。

組件化

image.png

組件化開發就是將一個app分紅多個模塊,每一個模塊都是一個組件(Module),開發的過程當中咱們可讓這些組件相互依賴或者單獨調試部分組件等,可是最終發佈的時候是將這些組件合併統一成一個apk,這就是組件化開發。

不一樣的Module咱們根據職責劃分選擇不一樣的架構,能夠最經濟的開發一款APP。

image.png

目前成熟的方案有阿里的ARouter,經過路由的方式進行通訊,感興趣的同窗能夠學習下。

優勢

一、低耦合 二、能夠針對測試(下降測試成本) 三、複用性強 四、支持並行開發 五、適合使用多進程 六、減少編譯時間

缺點

一、不適合小型應用或者獨立開發 二、各組件開發人員聯調,開發進度不一致等問題

應用場景

假如一個app用戶量很大,業務豐富,好比某寶,很明顯不是一個小團隊能夠開發的了的,若是不分模塊的話,工程的複雜度就太大了,編譯時間估計半天都完不成,維護更不用說了,簡直不是人乾的了。因此很適合分模塊來開發。各個模塊的耦合性也能降到最低,不至於一個模塊有問題,牽連別的模塊。編譯時間也會大大減少。每一個模塊至關於一個小APP,更容易靈活的編譯,編寫。測試也只須要測試本模塊,最後聯調總體就能夠了。因此說業務越複雜,組件化越有優點。

小結

移動端架構的差別化體如今通訊機制上。通訊機制主要分爲3種: 1) 對象持有 2) 接口持有 3) 路由

對象持有最簡單,可是解耦率最低; 接口持有較爲複雜,實現解耦的需求,可是解耦不完全,相互持有交互方的接口; 路由機制能夠實現徹底解耦,實現組件化。

完了嗎?不不不~~移動端不只僅Android和iOS,還有前端,上面僅僅是MVX的進化史,同時還有不一樣分支的進化。

當下移動端的趨勢,愈來愈向大前端靠攏了,Android的道友們也愈來愈瑟瑟發抖,看到RN,Flutter等等的興起,愈來愈以爲僅僅學習Android是不夠的,還要學習跨平臺,大前端的知識。俗話說他山之石能夠攻玉,咱們對架構的思考也是如此,不能僅限於本身的一畝三分地,也要學習下友軍的套路。

這類通常都是響應式視圖的系統,MVVM就是個響應式,因此其實都是有聯繫的。

進化 5.0 Flutter/ReatNative

  • Flutter 是Google用以幫助開發者在Ios和Android兩個平臺開發高質量原生應用的全新移動UI框架,也是聽說要把Android替換掉的一個恐怖存在(目前如今仍是個弱雞)

  • ReactNative 讓開發者使用 JavaScript 和 React 編寫應用,利用相同的核心代碼就能夠建立 Web,iOS 和 Android 平臺的原生應用。React Native 的宗旨是,學習一次,高效編寫跨平臺原生應用。

ReatNative

JS 開發者能夠用相似DOM編程模型就能夠開發原生APP,畫UI只須要畫到virtual DOM 中,不須要特別關心具體的平臺, RN 會把應用的JS代碼編譯成一個js文件,RN的總體框架目標就是爲了解釋運行這個js 腳本文件,經過bridge 傳遞到native , 而後根據數據屬性設置各個對應的真實native的View。

image.png

RN官方給的框架是Flux:

image.png

  • action 封裝請求
  • dispatcher 註冊處理器、分發請求
  • store 是處理器,處理業務邏輯,保存數據
  • view 根據store提供的數據進行展示;接受用戶的輸入併發出action請求。

解耦很細,作一個功能會涉及不少地方,因此人們對於這個官方架構進行簡化,因而有了Reflux。

Reflux:

Reflux.png
這個三層框架就大大簡化了flux的複雜交互。無論是面向對象仍是面向狀態,其實本質上是一致的。三層框架可以很好處理視圖,數據,事件,邏輯的問題。

咱們也能夠參考另一種架構Redux。

Redux:

Redux.png
咱們能夠看出 其實也是分爲三層,組件,Store,Action。組件綁定這Action和state,store reducer都是頁面單例,易於管理。action爲請求dto對象,是請求類型,請求數據的載體,reducer是處理請求的方法。不容許有狀態,必須是純方法。必須嚴格遵照輸入輸出,中間不容許有異步調用。不容許對state直接進行修改,要想修改必須返回新對象。

這就是面向狀態編程

react的組件只關注數據的最終狀態,數據是怎麼產生的並不關心。這個是RN的核心思想。

  • 優勢 一、提高產品迭代速度,APP迭代週期變短 二、減小研發成本(可不,ios和android均可如下崗了) 三、提高開發測試效率(不用雙端兩套代碼分開測試了)

  • 缺點 一、原生有些功能實現不了或者說很複雜 二、須要掌握IOS和Android的知識,我的學習成本高 三、須要兼容IOS和Android(很苦逼)

Flutter

今年穀歌推出了Flutter的Beta版本,離正式的出生愈來愈近了。咱們來看看這個新同窗吧。

Flutter主要解決了移動開發中的兩個重要問題,一是原生應用程序的性能與平臺的集成;二是提供多平臺、可移植的UI工具包支持高效應用開發。

和RN的跨平臺思想不一樣

RN是將一種設計理念延伸到兩個平臺,而Flutter則實現了一套代碼,部署多個平臺。解決了RN開發須要IOS和Android基礎的窘迫和成本。在Flutter中,每一個應用程序都是Widget,這點和其餘的應用框架不同,Flutter的對象模型是統一的,也就是控件。

Flutter 基本上就是一個 V(View),響應式視圖,它能夠是無狀態或有狀態的 widget,就連 AppCompatActivity 也是一個 widget。是否是很過度?簡單到粗暴。採用widget 和 state分離 ,好比咱們在原生裏大量重複代碼來管理 Activity 的生命週期。可是在 Flutter 中,這是不須要的,從設計的角度就解決了這個問題。就像LifeCycles也是這種思想,解決了生命週期的問題。

對於這種面向狀態編程的思想,架構和RN是相似,同時咱們也期待Google的官方架構指導的出現,會不會有更多的驚喜呢?

image.png
優勢 一、響應式視圖,不須要JavaScript的橋接器 二、性能更好,兼容性更好 三、代碼將AOT編譯爲本機(ARM)代碼 四、美觀,可定製的UI組件,開發人員徹底控制UI組件和佈局 五、熱從新加載

缺點 一、包體很大須要打包本身的SDK 二、佔用內存空間大 三、啓動時間很慢 四、流暢性和原生有差距

不過由於FLutter還沒與正式出版,相信FLutter會解決這些缺點的。

RN和Flutter差異:

對於這二者系統架構的區別 這裏有兩張圖:

Flutter.png
ReatNative.png
咱們能夠看出來 主要差異就是Widgets的差異,還有Bridge中間層的區別,Flutter從理論上的速度要別RN高不少,沒有了中間層的倒轉,有本身的Widgets能夠保證IOS和android上的統一。

實現跨平臺的這兩種方式也是架構設計的體現,Bridge有沒有和Presenter很類似,鏈接着js和系統。RN是將一種設計理念延伸到兩個平臺,而Flutter則實現了一套代碼,部署多個平臺。

不一樣的設計思想,會走向不一樣的路,究竟是哪種走的更好,這個可能就須要隨着時間去檢驗了,雖然理論上FLutter要比RN好不少,可是如今的顯示很殘酷。不過FLutter纔是Beta版本,潛力很是大。

image.png

寫在最後

本文把目前移動端主流的架構順了一遍,也是我本身對架構認識的一個時間軸,從剛開始的胡亂編寫,到後來有些章法,不過仍是對框架的領悟很淺,確定有不少謬論錯輪,但願以我我的對架構的思考能夠拋磚引玉,若是能夠給你一些幫助,那是極好的一件事情了。

無論是RN仍是Flutter,亦或是原生的IOS和Android,其實他們本質編程思想是一致,一樣,隨着更多更方便的框架出來,咱們的理解能力和學習能力受到了很大的挑戰,不少同窗都說學不動,可是事實上技術的更新換代遠比咱們學習新知識要快,每每咱們剛學會這個,又會出了另一個,咱們只要掌握了它的核心思想,就不會那麼累和無奈了。

這就是技和道的差異,經過技最終掌握道,而不是以技學技,那樣沒有終點。

咱們在實際中如何選擇架構,其實這個的因素不少,最關鍵的是一個經濟,好比項目時間比較短,仍是獨立開發,咱們可能就要用MVC了,或者說應用的功能相對簡單,也會取用MVC,至於MVP,或者MVVM,CLEAN,這個對於大型開發,特別是協做開發,有着很大的幫助。由於咱們工做不只僅是技術,還有項目週期,老闆的喜愛,歷史遺留問題,因此選擇最經濟的一個,而不是選擇那個公認最好的那個。

移動端的趨勢愈來愈走向統一了,咱們發現愈來愈多的公司,須要大前端的人才,因此要一直學習,創造時代的人都沒有說累,咱們跟着學習的人更不該該喊累,沒有學不動,只有不想學。同時歡迎你們來剛哥的知識星球,一塊兒激勵,一塊兒砥礪前行。

參考:

React Native運行原理解析 https://blog.csdn.net/xiangzhihong8/article/details/52623852

React Native vs. Flutter 評測 https://mp.weixin.qq.com/s/Or28Gf71wuJrCUP0lKGpGg

ReactNative的組件架構設計 http://react-china.org/t/reactnative/3486

爲安卓開發者介紹的移動開發框架 Flutter https://blog.csdn.net/Px01Ih8/article/details/79683595

歡迎關注個人微信公衆號,接收第一手技術乾貨
相關文章
相關標籤/搜索