模型、視圖與控制器(MVC)——輸入、更新、呈現
在一張互動畫布上呈現模型、視圖與控制器(MVC)模式:用戶輸入如何抵達控制器、更新模型,再經視圖呈現出來。
MVC 用一條規則把應用程式分成三部分:控制器處理輸入,模型擁有狀態與規則,視圖負責呈現模型——而視圖與控制器都不會直接觸碰狀態。
模型、視圖與控制器(MVC)——輸入、更新、呈現
The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.
How to read this visual
- 按箭頭畫出的次序跟著這個迴路走:用戶到控制器、到模型、到視圖,再回到用戶。
- 三條直欄就是三幕:輸入抵達、狀態更新、輸出呈現。
- 各條泳道就是關注點的分離——每一條泳道擁有一種工作,沒有一條泳道會去做別人的。
輸入
「用戶與介面互動」啟動這個迴路,而「控制器接收輸入」就是那位交通指揮:它讀取動作,判斷那代表甚麼,然後指示模型。控制器的備註把規則寫得明白——它本身不持有任何狀態,這就是它可以處理許多請求而毋須記住任何東西的原因。
更新
「控制器更新模型」跨進了模型的泳道,而「模型持有狀態與業務規則」就是模型的定義:它是資料以及規範資料那些規則的唯一真實來源。「模型把改動通知觀察者」是通知的那一半——模型不會告訴視圖要畫甚麼,它只是宣告有東西改變了,而任何數目的視圖都可以聆聽。
呈現
「視圖依據模型重新呈現」是視圖唯一的工作:讀取模型,然後顯示它。它的備註點出了令 MVC 不致瓦解的那份紀律——視圖從不改動資料,它只會查詢與顯示。「用戶看見更新後的介面」在用戶那一列把圓合上,而每一次互動都是在那裡開始,也在那裡結束。
Key relationships and takeaways
- 控制器處理輸入;模型擁有狀態;視圖負責呈現——三項職責,三條泳道。
- 視圖與控制器都不會寫入資料;所有改動都流經模型。
- 模型是通知觀察者,而不是命令視圖,所以一個模型可以驅動許多個視圖。
- 這種分離令每一部分都可以單獨測試——這正是這個模式最初的回報。
- MVC 是許多現代模式的祖先(MVVM、MVP、Redux 式的 store),它們全部都保留了同一種分離。
When to use this visual
- 在開發者去讀某個框架的文件之前,先向他們介紹這個模式——那個三角形就是每一個框架都在實作的地圖。
- 解釋為甚麼一個代碼庫難以改動:在視圖裡處理狀態就是違反 MVC,而這在畫布上是看得見的。
- 把 MVC 與整潔架構那張圖解裡的分層架構作比較。
運作方式
把你的框架對應到這個三角形上
用你實際框架的組成部分為三個方框改名——一個路由檔案當作控制器、你的 ORM 模型當作模型、你的樣板當作視圖——好讓這個模式變得具體。
加入路由這一步
如果你的框架有路由,就在用戶與控制器之間插入一個路由步驟,並把它連到它所派送的那個控制器。
呈現多個視圖
加入第二個視圖方框,兩者都聆聽同一個模型——一個列表視圖與一個詳情視圖——用來示範這個模式所依賴的觀察者關係。
加入持久化層
在模型之外延伸出一個資料庫步驟,並註明它由模型擁有,控制器與視圖都不會直接觸碰它。
常見問題
甚麼是 MVC?
MVC——模型、視圖與控制器——是一種把應用程式分成三部分的軟件模式:控制器處理輸入,模型擁有資料與業務規則,視圖負責呈現模型。這種分離的好處,是每一部分都可以獨立開發與測試,而同一個模型可以由許多個視圖來展示。大多數網頁框架都是建基於這個模式。
模型為甚麼是 MVC 的中心?
因為模型是唯一的真實來源。如果控制器與視圖都可以寫入資料,它們就會各自漂移並爭奪狀態。把所有改動都留在模型裡,意味著資料規則只有一個落腳點,而視圖永遠是一個一致模型的投影。圖解把模型的兩個方框放在它們自己的泳道,正是因為這個原因。
如果我把邏輯放進視圖會怎樣?
你會得到一種有時被稱為「肥大視圖」的反模式:顯示用的代碼與業務規則混在一起,不呈現出來就無法測試,而且會與模型漸行漸遠。同樣的批評也適用於一個持有業務邏輯而不是把工作交出去的控制器。MVC 的紀律,就是每一條泳道都留在自己的泳道裡——圖解裡那三列分開的方框,就是把這條規則畫了出來。
MVC 與現代框架有甚麼關係?
大多數現代框架都以新的名稱保留了這個三角形:MVVM 加入了一層 view-model,MVP 為視圖配上一個 presenter,而像 Redux 這類狀態管理程式庫,本質上就是加了更嚴格通知規則的模型。畫布的核心迴路——輸入改變狀態,狀態驅動輸出——就是它們每一個都保留下來的不變量。
用 QueryChart(FlowJam)編輯這張圖解
把上面這張 MVC 畫布開啟為你自己的圖表——把方框改名成你的框架,並追蹤你自己的請求路徑。