FAQ-如何理解 MVC 中的 Model?

現在還是學生,沒有啥大型項目的開發經驗。之前在一些網路公司實習的時候也做過一些開發,基本上都是用個MVC框架做Web開發。

按照我的理解,Model應該是用來傳遞數據的一種封裝,但是這種封裝在一些腳本語言中基本上體現不出來,感覺在Python等腳本語言中Model已經被充分弱化了(以前做Java EE開發的時候好歹還會有一些Model對象),有時一個數組一個字典就能實現所謂的封裝。

現在我的開發中,Controller中充斥著各種業務邏輯,然後用Dict這樣的數據類型隨手封裝一個Model,再把這個Model送到模板系統View中。。感覺在這樣的操作之下,Model已經被弱化得不像是一個單獨的模塊了,感覺我現在把MVC框架已經用成了VC框架了,所以現在很困惑Model到底體現在什麼地方……

(很有可能是我做的項目太小了,很多地方做的都不太規範,望大神們解答)


按照我的理解,Model應該是用來傳遞數據的一種封裝,但是這種封裝在一些腳本語言中基本上體現不出來,感覺在Python等腳本語言中Model已經
被充分弱化了(以前做Java EE開發的時候好歹還會有一些Model對象),有時一個數組一個字典就能實現所謂的封裝。

你理解錯了,把幾個模式、概念搞混了。

用來「傳遞數據」的封裝對應的架構(設計)模式是 Value Object,它的作用是在軟體架構的各個層次(如 Model、View)之間傳遞數據,例如你說的用一個數組或一個字典,在 JEE 里常用的是 Java Bean。

而 MVC 是另一種常見的架構模式,這裡的模型(Model)或 Model Object 通常指的是應用邏輯層(也叫領域層)的對象,如 Account、Order 等等。這些對象是你開發的應用程序中的一些核心對象,負責應用的邏輯計算,有許多與業務邏輯有關的方法或操作(如 Account.sendEmail()、Order.calculateTotal()、Order.removeItem() 等等),而不是僅僅像 Value Object 那樣用來傳遞數據(getter、setter)。

現在我的開發中,Controller中充斥著各種業務邏輯,然後用Dict這樣的數據類型隨手封裝一個Model,再把這個Model送到模板系統
View中。。感覺在這樣的操作之下,Model已經被弱化得不像是一個單獨的模塊了,感覺我現在把MVC框架已經用成了VC框架了,所以現在很困惑
Model到底體現在什麼地方……

從一開始你對 MVC 以及 Model 對象的理解就是錯誤的。

為什麼要在 Controller 中放各種業務邏輯?業務邏輯這原本就不是 Controller 的職責。應該把這些業務邏輯抽取出來,放到合適的各個 Model 對象中。

幾個可能的主要錯誤:

1、把業務邏輯放在 MVC 的 Controller 中,這種設計是不合理的。

MVC 中的 Controller(也叫 View Controller,視圖控制者)的主要職責是管理和處理用戶的輸入,並根據用戶在 View 上的輸入、系統當前狀態和任務的性質,挑選後台合適的一些 Model 對象(也叫領域對象 Domain Object)來處理相應的業務邏輯,並把經處理後的用戶輸入請求等信息傳遞給 Model 對象。View Controller 本身不應該負責一個應用程序中業務邏輯的計算。

2、把 Model Object 混同於 Value Object,從而得出 Model 沒什麼用的誤解。

3、混淆了 MVC 中的 View Controller 與整個應用的集中控制者 Application Controller。

混淆視圖控制器與應用控制器這兩種控制器,是許多初學者在學習 MVC、OOAD 、軟體架構設計時常見的一個誤解。


看描述你的項目大概是重controller輕model,可能你的model已經退化成為資料庫的增刪改查操作了。其實如果model已經退化成這樣的話,建議可以直接使用DAO等其他方式可以去掉Model了。

拋開MVC的功能,Model層的復用性比Controller強,View層的復用性最弱。所以說根據開放封閉原則來說,model層中放的應該是「業務邏輯上不容易變化的東西」。比如「根據id獲取資源結構」這麼個操作,當然這裡的資源結構可能設計到多個表和多個欄位合併等。所以說,model層太弱要不就是你的業務邏輯太簡單,簡單到除了資料庫增刪改查之外沒有其他的邏輯。要不然就是你的controller把很多本該model做的功能做了。具體大概就體現在你發現修改一個需求需要改很多很多個controller。


首先我想說的是mvc並不是一個好的設計理念,它在web這一塊顯得有些反oo了,比如把本該是實體的方法全部抽到了service中而實體則完全成了一個attributes package,而這個所謂的實體bean則到處充滿了迎合資料庫表結構的痕迹。隨著時間流逝service發生爆炸是遲早的事。

之後便有人提出了DDD領域驅動和充血模型,充血模型簡單來說就是把被service剝奪去的方法還給對象本身形成一個有血有肉的對象,interaction由領域上下文domain context暴露,而剛才提到的充血模型則扮演role,這個role的設計不能一味迎合資料庫的數據結構而應該側重交互用例尊重事實為原則,從這個角度來看你所提到的字典不過是一個用例函數的數據產出而已,這樣你就不會覺得這串字典感覺太「隨意」了而缺乏oo思想進而感覺彆扭了吧?!

而java之所以定勢化思想嚴重我猜測跟它那幾個有名的框架有關吧,編程上的東西哪有什麼固定套路呢?


說個自己理解的MVC,用現實生活中的實例來舉例,如果有說得不對的地方...你們來打我呀!(開玩笑;D,如有不對的地方請幫我指正)

--------我是可愛的MVC 分割線------

夏日炎炎,我們喜歡吹空調。那我們該怎麼樣去控制空調呢?使用空調上的按鈕嗎?可以是可以,但是很麻煩。怎樣才能遠程控制空調的溫度,大小呢?當然是使用空調遙控器!

所以遙控器可以看作MVC里的Controller。如果按照樓主的理解,把所有業務邏輯和功能都寫在Controller裡面,那我可能會認為你手裡拿著一整台空調!而不是遙控器!

那麼空調這台主機呢?可以認為他是一個Model和View的集合體。為啥這麼說呢?

有爭議的原文:

------------------------------------------------------------------------------------------------

因為空調的外觀顏色,大小尺寸,扇葉長什麼形狀,等等,甚至牆體外的空調壓縮外機的外觀大小尺寸,這些都可以看作是空調要被造成什麼樣子的。所以在程序中,可以看作是View。

------------------------------------------------------------------------------------------------

2016.8.7 摘自Shadow的回復,感謝指正!

------------------------------------------------------------------------------------------------

這段話不是很同意,因為你把遙控器當做controller,而mvc當中的controller 是可以控制view的,但是空調的外觀 尺寸 形狀什麼的,遙控器是無法控制的!我覺得這裡的view應該空調的液晶屏顯示的內容和空調輸出的降溫或者升溫的一種效果!雖然這個沒有空調的外觀跟view貼切,但是這才是controller遙控器真正控制的東西,這才是mvc的本質!如果你要沿用空調的外觀尺寸這個view 那我覺得controller應該是生產廠家,而不是遙控板!

------------------------------------------------------------------------------------------------

這個應該都不難理解。

但是有了這些東西還不夠,就好比網站上的前端頁面HTML+CSS+JS,只是一個空架子,並不能對資料庫進行操作,所謂的更刪改查。我們需要讓他根據某種關係某種邏輯組合起來,動起來,為我們服務。這一系列壓縮外部空氣—釋放冷空氣—回收廢氣—排出室外的有關業務邏輯的操作,我們稱之為Model。

那這時候Controller又有什麼關係呢?

Controller相當於把Model和View調用結合起來。如果有機會看到合理的controller代碼,裡面至少包含一個model對應一個view。就好比遙控器上,按一個按鈕,可以調節空調的溫度高低。沒有按鈕(view),你怎麼控制空調呢?空調里沒有預設這樣的功能(model),即使有這個按鈕你又怎麼知道你按下去這個按鈕一定可以控制空調的溫度呢?

以上,靈感突然萌發寫了很多。望指教。


MVC存在的意義是把表現層和數據層解耦,表現層和數據層耦合度太高會使擴展性變差(一個後台只能處理一種類型的前台),容易出錯,維護起來也很麻煩。所以中間加了一個中間層,這樣一個後台系統,在幾乎不做任何修改的情況下,同時支持多種視圖。MVC只是一種思想,不是一個固定的技術,個人感覺中間層要加多厚不能一概而論,只要易於理解易於擴展就行。

model,就跟「數學建模」中的「模」一樣。一個現實中的問題要在人類解決,人類首先需要將其抽象成一個模型來分析。計算機處理現實問題也需要先把其抽象成一個模型來處理。前台的東西是由後台的數據模型是實現。controller只是中間傳達信息的。


model是程序中「什麼」的定義,view是程序中「如何展示什麼」的定義,而controller是程序中「怎麼操作什麼」的定義。你覺得model弱化了,只是因為你沒用到高級的功能,實際上model在整個mvc層中處在很重要的位置,沒有model,controller和view你要寫些什麼?如果你用過一點兒DataAnnotation的東西,就知道model其實是負責定義metadata的,可以通過metadata來修改model被處理的行為,可謂應用程序的支架。

你還不理解因為你還在以代碼為支架編寫程序,而不是以元數據為支架編寫程序,以後項目大了,複雜了,你就知道元數據的好處了。


眾所周知,軟體三層架構模型,展示層、業務邏輯層、數據訪問層。

對於JAVA Web項目,從軟體本身出發,如果項目較大,展示層勢必承擔過多的責任。該層不僅僅需要調用業務邏輯,還需要處理請求參數和負責請求分發,還有可能需要許可權控制等。隨著項目需求的變化,模塊的增多,將java代碼塊嵌在html元素中,不僅可讀性不高,復用性也很難保障,影響後續人員的維護。另外從項目角度出發,前後台是不同的開發人員,針對同一個展示層,既需要寫java,又需要寫html,影響項目進度。因此,將展示層拆分成控制層和視圖層,讓視圖層回歸本質,僅負責展示,也是很自然的想法。

對於分層架構引入MVC模式,其中控制層(一般採用前置控制器方式)和視圖層,剛好契合了上面對於展示層的拆分。我剛開始使用MVC框架,比如strust2,也活生生的把MVC用成了VC,模型層並沒有體現在分層架構中。在新手階段根本沒考慮過面向對象,只是為了實現業務功能,比如用JDBC從資料庫查詢數據,若只有一行數據,使用List&;若有多行數據,使用List&&>。對於業務邏輯處理,就是遍歷集合然後運算,生成的結果還是使用集合容器接收,到了視圖層使用JSTL或者struts2標籤庫解析。對於取值都是採用元素在集合中的位置,很顯然,這樣的做法為以後需求的變化埋下了雷,比如查詢欄位或者運算結果的順序調整一下,即使我都知道每個下標對應什麼字元串,但維護起來真是一種災難!此時,使用對象來承載數據和傳輸結果,也變成了很自然的想法。

接下來,對於模型層對象如何分類,還得從項目業務場景的角度出發,面向對象抽象出業務中的核心要素。比如,有些對象直接與資料庫中數據對應,定義成實體對象;有些對象存儲配置信息,定義成值對象。一般情況下,將對象聲明成pojo形式的javabean。

至於模型層的使用場景,我一般使用在ORM框架、OXM框架、作為DTO在各層之間傳輸,包括在視圖層中用於展示結果。

至於在模型層中是否定義業務邏輯方法,我個人傾向於除了派生屬性,能將業務操作放在業務層就放在業務層來處理。

以上為我的個人理解。最後還是建議你多看看關於多層架構模型和MVC設計模式的資料。另外,繼續多做項目吧。純教科書般的理論總結,並非對於所有業務場景都適用。


我的理解是,就是為了持續性地保存數據,並且把這個過程同其它過程,諸如輸入、輸出和業務邏輯等分離開來。保存前可以進行驗證和格式化等處理,取出保存的數據的過程中和之後可以進行類似的針對性的處理。這個保存的格式可以是常見的資料庫文件,也可以是CSV甚至是INI等。


Model is the place where u generate data. It"s highly recommended that u clarify the logic between these 3 parts first, from the perspective of observer. Draw a DML first! ^ ^.


被展示的內容


推薦閱讀:

get和post区别?
零基礎開始學 Web 前端開發,有什麼建議嗎?
看某前端設計書上說,在 base.css 里先定義一些基礎樣式然後在 html 裡面加上相應的 class,這樣是否和語義化相矛盾?
如何用django在雲虛擬主機上建站?
樹莓派做web伺服器的話,性能怎麼樣?

TAG:Web開發 | 面向對象編程 | MVC | 設計模式 |