架構淺談之 MVC
很多人表示對架構沒有任何概念,想了解下架構,但是看了網上的一些文章又覺得云里霧里,其實架構遠沒有那么難,今天從這篇文章開始我來給大家談談架構,爭取讓大家都看得懂。
什么是架構?
對于架構,業界從來沒有一個統一的定義,架構一詞最初來自建筑業,假如我們要蓋一棟大樓,那在完成這么一項重大工程之前肯定需要建造師的建筑圖紙,而這建筑圖紙可以說是建筑業架構的最核心體現,它描述了這棟大樓的外觀、內部構造、戶型設計、材料做法以及設備、施工等,有了建筑圖紙,才能整體的規劃整個工程,從大局出發,有序的推進項目的發展,最大程度的提高生產力。
所以歸根結底,架構的目的就是為了提高生產力。而軟件領域的架構主要體現在模塊之間的「高內聚,低耦合」,這六個字聽起來有點難以理解,其實通俗來講就是單一職責的功能封裝成模塊,在模塊內部高度聚合,模塊與模塊之間不會互相依賴,即低耦合。比如我們常用的網絡庫、圖片加載庫,這都是屬于兩個模塊,在每個模塊內部功能單一,代碼高度內聚,但是網絡庫與圖片加載庫又不互相依賴,都可以獨立工作,互不干擾,這就是所謂的低耦合。
而我們追求「高內聚,低耦合」的目的很簡單,我們想讓開發人員只專注于一點,提高開發效率的同時,也對代碼的健壯性與擴展性有很大好處。試想,如果你做的功能需要同時跟四個部門進行合作,依賴于他們的模塊,那么你的開發效率肯定奇低,而且依賴過高,其他部門的代碼稍一改動很可能就會對你產生影響,而且問題還不容易定位,這將是一個定時炸彈。
所以,架構的重要性不言而喻,但是架構有一條原則:千萬不要過度設計!
如果你蓋的是棟大樓,你肯定需要建造師的建筑圖紙,但是如果你蓋的是一間茅草屋,你覺得你還需要請個建造師來先給你設計一張建筑圖紙再開工么?可能花在設計建筑圖紙的時間都夠你蓋完了。所以架構一定得看不同場景的需求,如果你的工程總共就十來個文件,那么你在開發的過程中運用各種設計模式、考慮各種分層,只會讓原本簡單的東西復雜化,還會增加工作量,這違背了架構的初衷。
最原始、最簡單的東西反而是最高效的,只不過我們的項目慢慢變得龐大,那些最原始的框架與結構滿足不了我們的需求了,這個時候我們必須從整體出發重新考慮整個項目的架構,通過架構來幫助我們提高生產力,減少重復繁雜的工作量,提升工作效率。
三層架構
說到架構,就不得不談到最經典的三層架構的概念,三層架構最初是微軟提出的,并且推薦各應用程序都應該遵守這種分層方式,而現今大多數應用程序基本都遵守這三層分層式架構。這三層架構分別是: 表示層、業務層、數據訪問層 。
我們拿訪問一個網站來舉個例子。你在瀏覽器輸入一個網址,訪問一個網站的時候,這中間經過了這么一個過程,用戶在瀏覽器輸入 url,然后瀏覽器向 Server 發起一個 http 請求,Server 拿到這個 http 請求之后會根據相關的條件到數據庫查詢相關數據,然后把數據以特定的格式(網站是 html 格式)返回給瀏覽器,瀏覽器再根據特定數據渲染出相應頁面。
這其中就對應了三層架構,首先對用戶來說,瀏覽器就是表示層,它主要是與用戶交互的頁面,根據用戶的輸入與事件,處理并顯示返回的特定數據。我們知道數據是一切應用程序的基礎,如果沒有數據,那么沒有任何意義,所以 Server 端必須要一個強大的數據庫來存儲所有用戶交互產生的數據,而對這些數據的處理,包括增、刪、改、查就屬于數據訪問層。那么連接表示層與數據訪問層的就是業務邏輯層,這包括后端程序中模型設計、驗證、業務規則、各種計算等。
所以后端的架構是很復雜的,它除了有復雜的業務邏輯之外,還有存儲、性能、并發、負載均衡等等,所以架構師一職最初也是針對服務端提供的職位。
MVC
隨著移動端的普及,手機端的應用程序功能越來越大,項目也越來越復雜,所以移動端架構也被越來越多的人關注與重視,但是移動端架構遠沒有服務端復雜,一是移動端的數據來源于服務端,不必有專門的數據存儲,最多有本地的緩存以及一些必要的小型數據庫,對于一些復雜的業務邏輯也更多的放在服務端,而且客戶端不必考慮成百上千萬用戶的同時訪問,移動端通常更應該把精力專注在 UI、交互、體驗上,所以客戶端的架構沒有那么重,但是為了讓移動端代碼分層更加清晰,代碼擴展性更好,以及更好的高內聚、低耦合,目前有一系列的移動端架構方案,大家耳熟能詳的比如 MVC、MVP、MVVM、Clean 等,今天就先來針對 Android 開發,來講講 MVC 的概念。
MVC 是 Model(模型)、View(視圖)、Controller(控制器) 的縮寫,其中 View 層處理界面顯示,Controller 層用來處理用戶的交互與事件,Model 層則用來定義實體對象與處理業務邏輯。
這么說難免有點晦澀難懂,我們來拿我們最熟悉的 Android 開發來舉例。
Android MVC
其實 Android 開發本身默認的就是一套 MVC 實現。
View 層 :Android 開發中的 xml 布局就是我們的 View 層,默認情況下也建議 View 都盡量用 xml 實現,當然對于一些復雜的就需要我們自定義 View 了,自定義 View 同樣也是屬于 View 層,只不過大多數時候還是 xml 布局用的最多;
Controller 層 :毫無疑問,Android 默認也給我們提供了 Controller,就是 Activity & Fragment,仔細想想,是不是用戶的交互事件,如輸入、點擊、滑動等都是在 Activity、Fragment 中處理的?關于這點有人認為 Activity & Fragment 屬于 View 層,這個我是不認可的,View 應該專注界面的顯示,Controller 處理用戶的交互,提供給 View 需要的數據,從而讓 View 正確的顯示出來,而這都是 Activity & Fragment 的工作。
Model 層 :Android 中對 View 與 Controller 有了定義,其實沒有對 Model 層做定義,而大部分架構都不會對 Model 層做定義,因為 Model 本身是跟業務相關,針對不同的業務模型,定義需要的數據模型與實體類,以及相關的業務邏輯處理,雖然 Android 沒有明確定義 Model 層,但是我們在開發中都會定義一個專門的 model package 用來統一管理所有的 model 文件,如 User、Order、Chat 等。
這里做個補充,因為對于部分初學者可能不理解什么是 Model,Model 的具體職責以及什么是所謂的業務邏輯?這里姑且說明下:
1. Model 即模型,也就是數據模型,通常就是所謂的 JavaBean 實體類,比如在界面上我們要顯示一些用戶信息,這個時候我們必須定義一個 User 對象,這個 User 對象也即所謂的 Model,如
public class User {
private int age;
private String name;
private ...
public void setAge(int age) {
}
public int getAge() {
return age;
}
...
}
通常這個就是 Model 的主要功能。
2. Model 就是一個數據模型的定義,定義了供我們使用的數據實體類而已。因為大部分我們的數據來源都是來自后端,客戶端不需要處理太多的業務邏輯,所以大部分情況下 Model 也就只包含基本的屬性與 get、set 方法。但是,并不是說明客戶端不包含任何業務邏輯,比如我們除了顯示用戶的基本信息外還需要顯示用戶的身體質量指數(也就是 BMI),這個值不是一個 Model 自帶的屬性,而是根據一些屬性通過一定的算法算出來的,這也就是所謂的業務邏輯。
BMI 的算法很簡單,就是體重(kg)÷ (身高^2(m)),有人可能直接在顯示的頁面把這段算法寫出來,比如直接在 Activity 有如下代碼:
textView.setText(String.valueOf(user.weight / (user.height * user.height)));
這個當然是可以,但是很糟糕,因為你需要在每一個顯示的地方都寫這么一段代碼,而它本身是屬于業務邏輯的,所以你應該把這個算法放在 User 的 model 里處理:
public class User {
private int age;
private String name;
private float weight;
private float height;
...
...
public float getBMI() {
return weight / height * height;
}
}
然后只需要在需要顯示的地方調用 user.getBMI() 這個方法就 ok 了,這個算法其實就是所謂的簡單的業務邏輯。
當然以上只是舉個例子,其實很簡單的概念,但是對于一些初學者可能不能理解,特此說明下,實際開發過程中,所有跟 model 相關的一些計算都可以算作業務邏輯,而這也是 Model 的第二個重要作用。
MVC 與三層架構的關系
有人可能會問了,你一會三層架構,一會 MVC 的,他倆之間到底是什么關系?
三層架構是一種軟件領域最普遍的分層式架構,而 MVC 是在三層架構的基礎上設計的一種框架型架構,三層架構是一種宏觀的概念,而 MVC 就是一種比較具體的三層架構的框架實現,我們在 MVC 的基礎上把不同類別的代碼文件進行分類就可以了,所以他們之間的關系可以用下圖來表示:
上圖可以看到,View 層和 Controller 層都屬于三層架構的表示層,而 Model 層屬于業務層,有人又問了,那數據訪問層怎么沒有相對應的呢?這個就是有爭議的地方了。
有人認為 Model 層除了定義業務需要的實體類與簡單的邏輯算法處理之外,還應該包括對數據庫的操作、對網絡等的操作等,這對后端開發來說沒問題,因為后端的數據全部來源于數據庫,而且后端可以很方便的跟數據服務器進行連接,而 Model 的業務邏輯大多都是來自對數據的處理,所以這種方式很正常。
但是對于客戶端來說差別就大了,我們知道客戶端的數據來源大多來自服務端的接口請求,但是很可能同時有本地數據庫、本地的文件都能提供數據,比如可能會有離線操作,比如可能為了用戶體驗,用戶斷網的時候會做緩存處理,也就是說客戶端的數據來源有多種多樣,而 Model 本身的主要職責應該定義業務需要的數據模型以及簡單的邏輯處理,如果同時也要處理本地數據庫與網絡數據未免變得臃腫起來,而且職責不清晰。
所以,我是非常不建議在 Model 層做多余的數據處理工作的,而對應三層架構我強烈建議客戶端的開發中應該多一層 data 層,也就是所謂的數據處理層,這一層包含了對 database、network、sharedpreference 等數據的處理,Model 層回歸最簡單、最本質的模型職責,只定義業務需要的數據模型與簡單的邏輯處理即可。
MVC 的優缺點
雖然 Android 開發框架并不是嚴格意義上的 MVC,但是顯而易見,默認的開發就是 MVC 框架,優點也很明顯,學習成本很低,理解很容易,對 UI 層與業務層做了分離,我們只需要對 Model 層與 data 層做個簡單的分層與封裝,就是一個擴展性還不錯、還算清晰的開發架構。
但是缺點也很明顯,隨著功能的不斷迭代與越來越復雜的交互處理,Controller 層也就是 Activity、Fragment 中的代碼越來越多,變得很臃腫,難以維護,尤其在需求變化的時候,改起來特別痛苦,我甚至見過一個 Activity 有幾千行代碼的情況,試想這得多痛苦,當然出現這種情況本身也有程序員自己的問題,但是這暴露了 MVC 這種架構的缺點。
MVC 可以說是最經典的架構模式,它適用于大部分的開發場景,如果你對架構不怎么了解,那么建議老老實實的使用 MVC,在此架構基礎上進行封裝與優化絕對夠了,只是項目到了一定體量了,需求也越來越復雜,總歸是會碰到難以擴展、Controller 層發展成“死胖子”的情況,這個時候怎么解決呢?且聽下回分解,當然下篇什么時候我也不清楚。
來自:http://mp.weixin.qq.com/s/GuO5wdo2rJgvHH6mErLgqw