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 的概念呢。

参考资料


<<:  JavaScript 函数 | 一级函数

>>:  策略也是需要经过验证的 - backtrader

Day 5 基本 flask 函式 (2)

前言 今天会继续探讨其他的 flask 的函式。如果说昨天的函式是用来给予使用者回应,那今天提到的函...

Day -6 条件式

python 条件式 if,注意 python run code 是 依据 code 排版 ,前後顺...

Windows的此版本即将过期

使用运行Windows 10的计算机时,您可能会得到「此Windows版本即将过期。Windows版...

Day 7 情报收集 - Information Gathering (Network & Port scanners)

今天子标题是Network & Port scanner,其实跟前面介绍的几个工具功能好像有...

[想试试看JavaScript ] 物件

Javascript 中将资料型态分成,基本型别(Primitive)与物件型别(Object)两大...