iT邦幫忙

2021 iThome 鐵人賽

DAY 8
1
自我挑戰組

馬克的軟體架構小筆記系列 第 8

30-8 之 Presentation Layer - MVC ( Model-View-Controller )

先給個提醒,這和一般人知道的 MVC 可能不太一樣,個人建議是如果你對 MVC 感到很混亂再來看看這篇,不然保持你想的 MVC 我不能說不好

在 《 企業應用架構模式 》這本書中,它只有提到 MVC 這個它放在 Presentation 的模式,而接下來的幾篇文章的我們會多加了兩個模式分別為『 MVVM 』與 『 MVP 』,接下來這篇文章我們要好好的來理解,MVC 最原始的意思。

MVC ( Model-View-Controller )

MVC 最早基本上應該是屬於 presentation,它主要聚焦在畫面根據 model 的互動,它最重要的概念在於將 UI 與 model 分離出來,它的組成如下 :

  • Model : 商業 domain 的部份處理。
  • View : 專門處理 UI 畫面的顯示。
  • Controller : 轉發請求,對請求處理。

傳統上它後他們的關係如下圖,這裡應該會有人覺得很奇怪,為什麼 view 會與 model 有連結,應該有不少人使用是以 Backend 角度來想,那的確沒錯,因為例如 asp.net mvc 應該是 view → controller → model,而 model 不會與 view 有關係。

https://ithelp.ithome.com.tw/upload/images/20210925/20089358BGH5Wd85iA.png
圖片來源: educative-Acing the JavaScript Design Patterns Interview

我當初看到這張圖有是有這想法,因此我去查了一下最原始的 MVC 出在《 A Description of the Model-View-Controller User Interface Paradigm in the Smalltalk-80 System 》這篇論文,它最原始的圖的確 model 會與 view 相互溝通,如下圖 :

https://ithelp.ithome.com.tw/upload/images/20210925/20089358mDfZ3F6xjJ.png
圖片來源: 《 A Description of the Model-View-Controller User Interface Paradigm in the Smalltalk-80 System 》

很多人會混亂的地方

我覺得有兩點,首先第一點在於『 傳統 MVC 應該是 view → controller → model,而 model 與 view 並不會有溝通 』,以 asp.net mvc 來看確是上面這樣,但我覺得當初會這樣做有兩個原因,第一點在於 web 中間多了個 http,而不像原始的 MVC 是設計上一般 gui 工具上。第二點當初我覺得 ASP.NET MVC 設計初宗是為了提現『 分離 』的概念。

然後第二點混亂點在於, 與我們上一篇文章提到的 3-Tier 搞混,MVC 是聚焦畫面與資料的互動模式,這也是為什麼 《 企業應用架構模式 》這本書作者會放在 presentation 層級,而 3-Tier 主要是聚焦在整個軟體架構上。

這些混亂的討論我覺得可以看一下,這篇文章的留言區,就會知道每個人的 MVC 真的完全不一樣。

https://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

範例

我這裡的範例,比較這張圖,因為原始論文 view 對 controller 的行為互動沒連線,但下面這張又缺了 model 對 controller 的變化通知,但論文裡的範例碼是有關係的。

https://ithelp.ithome.com.tw/upload/images/20210925/20089358BGH5Wd85iA.png
圖片來源: educative-Acing the JavaScript Design Patterns Interview

主要分成三個部份 :

  • Controller : 用來處理 view 來的事件,並且進行應的 model 處理,有時後也會由他來更新 view。
  • View : 會和 controller 有行為互動,會監聽 model,並且當監聽的 model 發生變化時,會更新 ui。
  • Model : 資料,當發生變化時,會通知相關訂閱的 view 與 controller。

這裡有幾個重點要注意 :

  • 一個 controller 可能會是 n 個 view 對 n 個 model。這個可以想成,不同的畫面可能有相同的行為操作,而這些操作可能會對應到多個 model。
  • view 與 controller 都會監聽 model 的變化,下面的範例只有 view 監聽,但實際上看原始論文圖是可以的。這裡 view 監聽的意義代表當 model 變化時,會影響到相對應的畫面變化,以下面範例 userModel 的變化,會影響到兩個畫面 userView 與 userListView。
  • controller 可以監聽 model 的原因在於,例如,假設有個訂單 model 成立訂單,那這時 userController 可能會需要知道,因為他這裡有個行為操作為判斷這個用戶是否為第一次購買,在來做相對應的事情。
const EventEmitter = require('events');

class UserView{
    init(controller, model){
        this.controller = controller
        this.model = model
        const that = this
        this.model.on('model-change', () => {
            that.updateView()
        })
    }
    registerUser(name){
        this.controller.registerUser(name)
    }
    updateView(){
        console.log('Update user view !!!')
    }
}

class UserListView{
    init(controller, model){
        this.controller = controller
        this.model = model
        const that = this
        this.model.on('model-change', () => {
            that.updateView()
        })
    }

    updateView(){
        console.log('Update user list view !!!')
    }
}

class UserModel extends EventEmitter{
    create(name){
        console.log(`Create a user#${name}`)
        this.emit('model-change')
    }
}

class UserController{
    init(userView, model){
        this.view = userView 
        this.model = model
    }

    registerUser(name){
        this.model.create(name)
    }
}

const userModel = new UserModel()
const userView = new UserView()
const userListView = new UserListView()
const userController = new UserController()
userView.init(userController, userModel)
userListView.init(userController, userModel)
userController.init(userView, userModel)

userView.registerUser('Mark')

// Create a user#Mark
// Update user view !!!
// Update user list view !!!

小總結

這篇文章的範例是我主要根據最原始論文的內容,所撰寫的我自已覺得最初的概念是這樣的程式碼,不代表一定正確 ~ 請自行判斷 ~ 畢竟 MVC 這個內容如果你有認真去尋找相關資料,應該真的會很混亂 ~ 我也混亂很久,所以我才去找最原始版本的來看看 ~

這個知識點可以用來解釋什麼現象

MVC 會出來,我覺得最主要就是因為 SRP 單一職責原則,所提出的,定義好每部份 ( M、V、C ) 要做什麼事情。

這個知識點可以和以前的什麼知識連結呢 ?

ASP.NET MVC 我真一直以為最原始的 mvc 就是它的樣子,後來才發現它算是改良過的,不如說我覺得比較接近 MVP 啊。

我要如何運用這個知識點 ?

  • 至少我知道最原始的 mvc 長什麼樣子了。
  • 不過我覺得 model 訂閱是個不錯的概念,前端我不太熟,不過現在好像有不少前端 framework 會根據 model state 來改變狀態,不確定這算不算是 mvc 的概念呢。

參考資料


上一篇
30-7 之分層架構 From Patterns of Enterprise Application Architecture
下一篇
30-9 之Presentation Layer - MVP ( Model-View-Presenter )
系列文
馬克的軟體架構小筆記29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言