為什么要使用框架
使用框架帘靡,是為了提高生產(chǎn)效率知给。
什么是生產(chǎn)效率?
上學(xué)的時(shí)候描姚,導(dǎo)師曾說:我以前上學(xué)那會(huì)兒涩赢,什么都得自己寫,別的不說轰胁,光把界面畫出來就夠發(fā)表篇論文了谒主,哪像你們現(xiàn)在,拿個(gè)鼠標(biāo)拖幾下就能弄出界面來赃阀。
這就是生產(chǎn)效率霎肯。
為什么使用框架能提高生產(chǎn)效率?
做過軟件的人都知道榛斯,我們開發(fā)一個(gè)軟件观游,其實(shí)就是把現(xiàn)實(shí)中的業(yè)務(wù)映射到軟件中去,這是一個(gè)對(duì)現(xiàn)實(shí)去做軟件建模驮俗,去做代碼實(shí)現(xiàn)的過程懂缕,而現(xiàn)實(shí)又是極度復(fù)雜的,做工程的基本常識(shí)是王凑,越復(fù)雜的東西風(fēng)險(xiǎn)就越高搪柑,所以軟件開發(fā)是充滿未知風(fēng)險(xiǎn)的聋丝,面對(duì)未知風(fēng)險(xiǎn),我們是茫然且恐懼的工碾,在茫然之下弱睦,我們最直接的反應(yīng)是:這種事一般要怎樣做,有什么經(jīng)驗(yàn)渊额,有沒有什么套路况木。
框架就是這樣一種套路,因?yàn)樗呀?jīng)通過某種范式旬迹,完成了對(duì)業(yè)務(wù)的解析火惊、映射和分層,在充滿未知的軟件開發(fā)中奔垦,框架的存在使開發(fā)有一定規(guī)矩可循屹耐,使常見的問題容易得到解決,使開發(fā)人員更專注于具體業(yè)務(wù)宴倍。
一般來說张症,使用框架有這樣幾點(diǎn)好處:
1、加快開發(fā)速度鸵贬。很多框架會(huì)幫你實(shí)現(xiàn)一些通用的、偏底層的實(shí)現(xiàn)脖捻、例如用IDE繪制軟件界面阔逼、用Hibernate讀寫數(shù)據(jù)庫、用EventBus傳遞事件地沮、用HttpClient處理網(wǎng)絡(luò)請(qǐng)求等(Android開發(fā)的框架會(huì)更多一些)嗜浮,除非是特殊的環(huán)境或有特別的訴求,否則沒有開發(fā)者愿意花費(fèi)大量的時(shí)間和精力摩疑,自己再造一遍輪子危融。
2、降低開發(fā)風(fēng)險(xiǎn)雷袋。還是造輪子的問題吉殃,每個(gè)輪子都會(huì)有缺陷,但是大家都在用的輪子楷怒,相對(duì)更加可靠蛋勺,發(fā)現(xiàn)缺陷也容易及時(shí)得到修復(fù)。
3鸠删、方便團(tuán)隊(duì)協(xié)作抱完。一般情況下,軟件開發(fā)都是團(tuán)隊(duì)行為刃泡,團(tuán)隊(duì)開發(fā)就要求在成員之間協(xié)調(diào)一致地并行工作巧娱,這就要求接口一致碉怔、風(fēng)格一致等,這會(huì)帶來很多管理上的問題禁添,而使用框架能較好地輔助這一點(diǎn)撮胧。
4、框架本身的優(yōu)勢上荡。每個(gè)框架的出現(xiàn)都是為了解決某些問題趴樱,像我們今天要討論的MVP、Flux和RxAndroid酪捡,都是為了解決日益復(fù)雜的業(yè)務(wù)邏輯導(dǎo)致軟件不可控的問題叁征,MVP的思路是“挪”,在MVC的基礎(chǔ)上把業(yè)務(wù)邏輯從View中挪走逛薇;Flux的思路是“單向流”捺疼,用嚴(yán)格的單向數(shù)據(jù)流去實(shí)現(xiàn)比較容易跟蹤檢測的邏輯結(jié)構(gòu);RxAndroid的思路則是“鏈?zhǔn)竭壿嫛庇婪#煤瘮?shù)反應(yīng)式編程的思想把邏輯啤呼、代碼和線程統(tǒng)統(tǒng)簡化為一條鏈?zhǔn)秸{(diào)用。
MVP
關(guān)于MVP的經(jīng)典表述可以參考Google開源項(xiàng)目Android Architecture Blueprints呢袱。
MVP想解決的問題是官扣,Google原來為Android準(zhǔn)備的MVC分層架構(gòu)中,C的存在極其薄弱羞福,存在嚴(yán)重的Activity膨脹的問題惕蹄,在很多開發(fā)中,Activity既是顯示界面治专,又是業(yè)務(wù)邏輯卖陵,從一開始就沒有分散職能,Activity會(huì)隨著業(yè)務(wù)的變化急速膨脹张峰,邏輯膨脹泪蔫,代碼膨脹,文件膨脹喘批,長期連續(xù)迭代下來撩荣,一個(gè)Activity的代碼很容易拖到幾千行甚至上萬行,代碼的復(fù)用性谤祖、可讀性和可維護(hù)性都變得非常糟糕婿滓。
這種情況下,一個(gè)比較合理的思路就是“挪”粥喜,把業(yè)務(wù)邏輯從Activity中挪出來凸主,挪到Presenter中去,讓Activity回歸View的角色额湘,從此Presenter專注于業(yè)務(wù)卿吐,View專注于顯示旁舰。業(yè)務(wù)邏輯不再受Activity生命周期的影響,Activity也擺脫了業(yè)務(wù)邏輯無法復(fù)用的囧境嗡官。
“挪”業(yè)務(wù)邏輯的MVP箭窜,基本解決了Activity膨脹的問題,View層變得相對(duì)簡單而安全了衍腥,而Presenter層中的業(yè)務(wù)邏輯磺樱,也比較容易做單元測試,做代碼復(fù)用婆咸,做進(jìn)一步的抽象和分離竹捉。
但是MVP中的業(yè)務(wù)邏輯仍然復(fù)雜,而且邏輯流和數(shù)據(jù)流基本處于只要不出bug尚骄,就可以放任自流的狀態(tài)块差,體現(xiàn)在業(yè)務(wù)邏輯上就是無數(shù)錯(cuò)綜交叉的業(yè)務(wù)線,體現(xiàn)在業(yè)務(wù)數(shù)據(jù)(Model)上就是無數(shù)的調(diào)用入口倔丈,長期運(yùn)轉(zhuǎn)下來憨闰,會(huì)發(fā)現(xiàn)越復(fù)雜的業(yè)務(wù)就越難以追蹤邏輯運(yùn)轉(zhuǎn)和數(shù)據(jù)狀態(tài),對(duì)軟件的維護(hù)擴(kuò)展非常不利需五。
也就是說鹉动,MVP需要一個(gè)狀態(tài)管理工具,用來督促開發(fā)者按照一定規(guī)律處理狀態(tài)的讀寫宏邮,避免代碼變成一團(tuán)亂麻训裆。
Flux
關(guān)于Flux的經(jīng)典內(nèi)容可以參考Facebook的移動(dòng)架構(gòu)Android Flux
Flux試圖用“單向流”去實(shí)現(xiàn)狀態(tài)管理,它是一個(gè)單向綁定的單向數(shù)據(jù)流結(jié)構(gòu)蜀铲,一般我們看到的圖是這樣子的:
Flux是一個(gè)單向環(huán),它實(shí)現(xiàn)業(yè)務(wù)的基本流程如下:
1属百、View響應(yīng)操作并創(chuàng)建對(duì)應(yīng)的Action
2记劝、Action調(diào)用單例的Dispatcher去統(tǒng)一處理所有請(qǐng)求
3、Dispatcher持有所有Store對(duì)象族扰,通過回調(diào)讓Store處理數(shù)據(jù)
4厌丑、Store處理數(shù)據(jù)后,發(fā)出事件(EventBus)通知View更新解密
5渔呵、View接收Store的事件后怒竿,刷新頁面
上面的圖并不能表現(xiàn)Dispatcher的中心作用,我們可以看這個(gè)圖:
可以看到扩氢,F(xiàn)lux實(shí)際上比MVP更啰嗦耕驰,要?jiǎng)?chuàng)建更多的對(duì)象,使用更多的訂閱和回調(diào)录豺,依賴EventBus去刷新頁面...
但是朦肘,F(xiàn)lux能把所有的業(yè)務(wù)都引流到一個(gè)Dispatcher單例中處理饭弓,這實(shí)際上建立了一種機(jī)制,這種機(jī)制能在同一個(gè)地方查詢狀態(tài)媒抠、改變狀態(tài)弟断、傳播狀態(tài)的變化,這就是MVP缺少的那種狀態(tài)管理工具趴生。
在這種機(jī)制下阀趴,所有的業(yè)務(wù)都是從某處開始并進(jìn)入Dispatcher,再離開Dispatcher去往某處結(jié)束苍匆,中間不可能有循環(huán)刘急,每條業(yè)務(wù)邏輯都只朝著終點(diǎn)方向運(yùn)行,這就實(shí)現(xiàn)了Flux“單向流”的思想锉桑,這就是單向數(shù)據(jù)流排霉。
單向數(shù)據(jù)流對(duì)軟件開發(fā)來說,意味著什么呢:
如上圖所示民轴,單向數(shù)據(jù)流攻柠,意味著業(yè)務(wù)邏輯得到了有效的管理,我們可以很清楚地知道每條業(yè)務(wù)線上會(huì)發(fā)生什么后裸,不會(huì)發(fā)生什么瑰钮,軟件的狀態(tài)和行為變得容易預(yù)測,代碼的可讀性和可預(yù)測性得到提高微驶,業(yè)務(wù)流程得以簡化浪谴,容易排除錯(cuò)誤,這給開發(fā)和維護(hù)帶來了極大的便利因苹。
Flux當(dāng)然也有問題苟耻,他太啰嗦,代碼復(fù)用太差扶檐,會(huì)有嚴(yán)重的action類膨脹問題凶杖。感興趣的開發(fā)者可以再去了解一下相對(duì)簡潔許多的Redux,目前主要在web開發(fā)中和React一起使用款筑,對(duì)Redux的介紹可以參考Redux中文文檔
RxAndroid
RxAndroid其實(shí)就是在Android中使用RxJava智蝠,詳細(xì)內(nèi)容可以參考給 Android 開發(fā)者的 RxJava 詳解
RxJava 是個(gè)了不起的工具,它使代碼的編寫和維護(hù)更加容易奈梳,而且更少出錯(cuò)杈湾,它的思路和MVP/Flux完全不同,如果說MVP/Flux關(guān)注的是類的分層和分工攘须,那么RxJava關(guān)注的就是純粹的業(yè)務(wù)邏輯鏈條漆撞。
RxJava通過訂閱事件驅(qū)動(dòng)的鏈?zhǔn)竭壿嬚{(diào)用,把復(fù)雜的異步邏輯維持成為一條簡單的鏈?zhǔn)浇Y(jié)構(gòu),來保持邏輯和代碼上的簡潔叫挟,這也使業(yè)界普遍認(rèn)為Rx編程屬于“函數(shù)響應(yīng)式編程(FRP)”艰匙,因?yàn)樗孟癫辉僖蕾囉谕ㄟ^面向?qū)ο螅∣O)的設(shè)計(jì)來解決問題,而是通過 “鏈?zhǔn)健钡乃季S方式抹恳,實(shí)現(xiàn)基于訂閱事件驅(qū)動(dòng)的簡潔的鏈?zhǔn)秸{(diào)用员凝,訂閱事件驅(qū)動(dòng)的基本思想如下:
用被觀察者去發(fā)出事件,在觀察者中響應(yīng)事件奋献,形成異常簡潔的邏輯鏈條健霹,這種簡潔即是RxJava的魅力和優(yōu)勢所在。
一段RxJava的典型代碼是這樣的:
我們看到瓶蚂,所有的事情都在同一個(gè)鏈?zhǔn)秸{(diào)用里完成了糖埋,其中的訂閱和事件我們都不陌生,這也不是它保持簡潔的秘訣窃这,RxJava保持簡潔的秘訣在于鏈?zhǔn)秸{(diào)用瞳别,而鏈?zhǔn)秸{(diào)用的秘訣在于,每次邏輯調(diào)用后返回的對(duì)象杭攻,都是自己或自己的同類祟敛,并包含了繼續(xù)鏈?zhǔn)秸{(diào)用的方法。
通過把復(fù)雜的業(yè)務(wù)維持成一條簡單的鏈?zhǔn)浇Y(jié)構(gòu)兆解,保持邏輯和代碼上的簡潔馆铁,這種做法的好處是顯而易見的,簡潔锅睛、優(yōu)雅埠巨、高效,而且現(xiàn)實(shí)中的業(yè)務(wù)線幾乎可以照葫蘆畫瓢地映射為代碼中的邏輯鏈现拒。
當(dāng)然RxJava也有他的問題辣垒,就是對(duì)代碼的掌控變?nèi)趿恕D馨褟?fù)雜問題用簡單形式表達(dá)出來當(dāng)然很了不起印蔬,但是復(fù)雜邏輯被表達(dá)為簡單鏈條后乍构,一方面擺脫了臃腫的代碼,另一方面卻因?yàn)榇a邏輯過于緊湊扛点,給排查故障帶來了障礙,比如說新手常犯的一個(gè)錯(cuò)誤是岂丘,忘記將網(wǎng)絡(luò)請(qǐng)求分配到異步線程去工作陵究,而默認(rèn)搭配的Retrofit網(wǎng)絡(luò)框架是無法在Android主線程上工作的,整條業(yè)務(wù)鏈從一開始就中斷了奥帘,但開發(fā)者能看到的直接反饋是業(yè)務(wù)鏈的結(jié)尾沒有輸出铜邮,很難精確定位到故障點(diǎn),只好對(duì)整條鏈路進(jìn)行檢查,這對(duì)開發(fā)和維護(hù)也是不利的松蒜。
感興趣的開發(fā)者也可以去閱讀我以前寫的文章RxAndroid使用初探—簡潔扔茅、優(yōu)雅、高效
如何選擇
在框架的選擇上秸苗,沒有最好的框架召娜,只有最合適的框架,特別是很多框架只是一種編程思想惊楼,你很難說自己在編程時(shí)會(huì)特意使用某種思想玖瘸,又特意不使用某種思想,就像前些年熱炒的設(shè)計(jì)模式一樣檀咙,不要為了使用而使用雅倒,能恰到好處地需要解決你的問題,就是適合你的弧可。
更詳細(xì)點(diǎn)說蔑匣,使用框架的問題不僅在于如何把框架應(yīng)用到你的項(xiàng)目中,也在于如何在不必要用框架地方保持清爽簡潔棕诵,比如如果你的頁面非常簡單裁良,沒有很多互動(dòng),就不要使用Rx年鸳、Redux趴久、Flux,甚至MVP也不需要搔确,你就簡單地在一個(gè)Activity里實(shí)現(xiàn)就好彼棍。
總的來說,合適的就是最好的膳算,不要過度設(shè)計(jì)座硕,保留在必要時(shí)重構(gòu)代碼的能力就好。畢竟涕蜂,對(duì)于軟件工程來說华匾,完備周全的設(shè)計(jì)往往起不到應(yīng)有的作用,反而是快速交付机隙,快速迭代的策略越來越被證明是一種低風(fēng)險(xiǎn)的模式蜘拉,不過,這個(gè)話題就是另外一個(gè)范疇了有鹿。
參考資料
Google開源項(xiàng)目Android Architecture Blueprints
Facebook的移動(dòng)架構(gòu)Android Flux