android開發框架總結 (一)從java基本原則細數MVP的“七宗罪”

前言

我們都知道,MVP是在MVC的基礎上做了一次升級,相比MVC,MVP中P層與V層隔離,V層只負責UI,業務邏輯由抽象出來的P層負責,真正意義上的隔離View的細節和複雜性的模式.......

好了好了,上面是網上MVP“鼓吹”的基本套路。“欲想讓其滅亡,必先使其膨脹”今天,反其道而行之,我們來羅列MVP的“七宗罪”

 

MVP的“七宗罪”

有一定經驗的工程師都知道,我們的java有六大基本原則,我們在編程的時候,應該儘量去遵循面向對象思想,遵循六大基本原則。而有時候,爲了“合理”,我們會多繞很多“彎路”,比如要實現降低類間的耦合,不得已我們會寫出很多接口,這就造成了代碼膨脹。耦合度與代碼量之間,我們常常要做到取捨,沒有絕對的合理,只有相對的優化。MVP在追求它的自身理念的同時,也“不小心”違背了部分原則。

 

在開頭,先簡單來看看MVP的缺點

1.粒度不好控制,控制不好就需要寫過多的類和接口
2.如要重用presenter可能會實現過多不需要的接口
3.Presenter和View通過接口通信太繁瑣,一旦View層需要的數據變化,那麼對應的接口就需要更改

 

違背開閉原則

我認爲MVP設計的初衷是MVP三層分別用中間件銜接,三者可分由不同開發者開發,相互間實現無縫銜接。在MVP中,只有P層負責邏輯,具有獨立意志與決定權,是三層的主導,而V與M都只是工具,,V與M層的替換應該是得非常簡單。

可是,在實際中,V層與P層依賴性太強,V確實與M分開了,可是當我們業務涉及了視覺交互,UI邏輯要修改時,V與P相牽連,都要配合做改動,這樣就做不到我們上面初衷所設想的,P層編寫者要不斷被不是本質工作的任務牽連,着違背了開放封閉原則。形式上解耦,但是職責分工還是耦合

 

違背單一職責原則(可解決)

在項目中,如果有fragment,我們經常把fragment作爲V層,爲了降低V與P的耦合,會在其主activity中去實例化P層的接口,這裏,我們是不把activity當初V層,而實際上,activity就應該是V層的一部分,如果把它當做V層,那V層持有P層的引用,這違背了單一職責原則。實際上,藉助其他工具庫是可以解決這個問題的。用Dagger2,實現“依賴注入,控制反轉”,不由調用者決定調用誰,把控制的主導權交給被注入者來決定,這就符合了單一職責原則,V層專心UI工作,如果要替換被注入的類,由注入者來改,調用者是感知不到的變化,不改動代碼,從而減低耦合。實際上,解決方法已經在上文給出了。

違背迪米特原則

迪米特也就最少知道原則,這部分與上面開閉原則比較像,不做展開(像指定是導致違背原因相像,而不是原則本身像)

 

違背接口隔離原則(可解決,比較麻煩)

由回到了我們上面的問題,MVP中,一大難題是如何控制好P層接口的粒度,如果粒度太小,那麼一旦業務多起來,我們的P層會非常臃腫。而如果粒度太小,那麼我們一個P層確實可以達到複用,可卻導致了我們不同需求的V層複用同一個P層接口時,要實現好多我們不需要的方法,這就是非常典型的違背了接口隔離,接口的實現類不應該實現沒有的方法。

如果把控好P層的粒度可以解決這個問題,不過,在項目一開始就能把控好我們的業務,這要求對業務及代碼的掌控能力比較強,這是比較考驗經驗的,所以解決其來也不簡單。而且,我認爲接口的一個好處是可以在一開始對該接口的實現類有一個大體的把控,起到了引導的作用。如果這樣看,那麼多寫接口未必是壞事,相反,爲了避免P層膨脹,強行讓接口可複用,這就導致接口成爲了代碼的“束縛”。

 

違背依賴倒置與里氏替換原則

??!!

我數着基本原則也就六個,這是全都搞砸了??!!

好啦好啦,這兩個純屬開玩笑的,再違背下去,MVP都快要“十惡不赦”了。

那麼有人會說,你這不是“槓精”嗎,欲加之罪何患無辭!照你這麼說,MVP怎麼可能會有人用,這不是吹毛求疵嗎?

非也非也,MVP能做到成爲主流的框架,自然有他的很多優勢。這裏我強行“擡槓”,不是說它不好,只是在強調它不一定就合適。

我所想表達的是,在開發中,我們選擇主流的不一定就是對的,比如我們選擇圖片加載框架,我們看到Glide封裝的最完善易用,我們就貿然使用了它,卻沒考慮到他的庫非常佔內存,其他庫也許更合適。

 

本文意義所在

在開發過程中,最難的並不是完成應用的開發工作,而是在後續擴展維護的過程,如何讓應用系統能擁抱不斷的變化迭代,在不破壞原有穩定性的基礎上提高可擴展性,達到高內聚,低耦合。這是爲什麼要追求穩定的系統框架設計。

回到主題,上面列舉其違背原則,是想說,我們的MVP在實際不同的項目中,並不是一成不變的,根據不同的情況我們可能會在MVP的基礎上做改動。比如某公司由於人員分配,V層與P層有不同團隊人員並行開發,那麼爲了做到彼此並行,那麼我們就會像我上面強行“擡槓”那樣,要求其解決“接口隔離,單一職責原則的問題”,解決粒度的問題。具體做法可能會是在MVP基礎上,在V與P之間加一層路由,實現解耦,也可以是通過使用LiveData+ViewModel,甚至使用EventBus來實現各層之間的通訊。不同情況不同做法,編程是沒有一套絕對的標準,這些都是要根據需求,根據人員配置,選擇合適的做法,並接受其帶來的弊端。

 

 

我們的MVP在大的項目中的使用相對還是比較得心應手的,但是,如果你的項目不大,並且由一個人開發。你強行使用MVP,那麼你項目的前期可能得重複寫好多接口,這很讓人頭大。

相比MVP,MVVM在某些方面更加友好,其實好多有經驗的工程師,更傾向於在MVP與MVVM之間取得一個折中,一種比較優雅的寫法是MVP+LiveData+ModeView+LifeCycle+Dagger2。

有的人看到這裏已經坐不住了,別急,都看到這了,那我就不往下講了。。。。。。。。。。。

 

 

 

 

哈哈,開玩笑的。關於架構的選擇與優化,我會在後面搞一個比較詳細的系列來與大家一起交流學習。涉及了MVVM,架構組件,以及對於MVVM與MVP的優化。本文僅作爲該系列的引子。旨在追求一套適合個人的框架。

在本系列的另一篇博客中,博主算是非常詳細地對比了MVP與MVVM兩者的優缺點,分析瞭如何在兩者中做選擇,也算是乾貨滿滿(容我自誇一下,哈哈)附上鍊接 android開發框架總結 (二)MVP與MVVM優缺點對比

謝謝你的閱讀,如果有收穫,不要吝惜你的點贊。如果有偏頗,請你指出,相互學習進步。謝謝你!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章