美文网首页全栈工程师修炼指南
MVC架构解析:模型(Model)篇

MVC架构解析:模型(Model)篇

作者: 码农架构 | 来源:发表于2020-11-10 10:26 被阅读0次

概念

模型就是当我们使用软件去解决真实世界中各种实际问题的时候,对那些我们关心的实际事物的抽象和简化。比如我们在软件系统中设计“人”这个事物类型的时候,通常只会考虑姓名、性别和年龄等一些系统用得着的必要属性,而不会把性格、血型和生辰八字等我们不关心的东西放进去。

更进一步讲,我们会谈领域模型(Domain Model)。“领域”两个字显然给出了抽象和简化的范围,不同的软件系统所属的领域是不同的,比如金融软件、医疗软件和社交软件等等。如今领域模型的概念包含了比其原本范围定义以外更多的内容,我们会更关注这个领域范围内各个模型实体之间的关系。

MVC 中的“模型”,说的是“模型层”,它正是由上述的领域模型来实现的,可是当我们讲这一层的时候,它包含了模型上承载的实实在在的业务数据,还有不同数据间的关联关系。因此,我们在谈模型层的时候,有时候会更关心领域模型这一抽象概念本身,有时候则会更关心数据本身

贫血模型和充血模型

贫血模型

这里的“血”,就是逻辑。它既包括我们最关心的业务逻辑,也包含非业务逻辑 。因此,贫血模型(Anemic Domain Model),意味着模型实体在设计和实现上,不包含或包含很少的逻辑。通常这种情况下,逻辑是被挪了出去,由其它单独的一层代码(比如这层代码是“Service”)来完成。

严格说起来,贫血模型不是面向对象的,因为对象需要数据和逻辑的结合,这也是贫血模型反对者的重要观点之一。如果主要逻辑在 Service 里面,这一层对外暴露的接口也在 Service 上,那么事实上它就变成了面向“服务”的了,而模型实体,实际只扮演了 Service API 交互入参出参的角色,或者从本质上说,它只是遵循了一定封装规则的容器而已

充血模型

充血模型(Rich Domain Model)。在充血模型的设计中,领域模型实体就是有血有肉的了,既包含数据,也包含逻辑,具备了更高程度的完备性和自恰性,并且,充血模型的设计才是真正面向对象的。在这种设计下,我们看不到 XXXService 这样的类了,而是通过操纵有状态的模型实体类,就可以达到数据变更的目的

  • 无论是充血模型还是贫血模型,它和 Model 层做到何种程度的解耦往往没有太大关系。

内部层次划分

层次划分过多、过细,并不利于开发人员严格遵从和保持层次的清晰,也容易导致产生过多的无用样板代码,从而降低开发效率。下面是一种比较常见的 Model 层,它是基于贫血模型的分层方式。

image.png

在这种划分方式下,每一层都可以调用自身所属层上的其它类,也可以调用自己下方一层的类,但是不允许往上调用,即依赖关系总是“靠上面的层”依赖着“靠下面的层”。最上面三层是和业务模型实体相关的,而最下面一层是基础设施服务,和业务无关。

CQRS 模式

你也许听说过数据库的读写分离,其实,在模型的设计中,也有类似读写分离的机制,其中最常见的一种就叫做 CQRS(Command Query Responsibility Segregation,命令查询职责分离)。

一般我们设计的业务模型,会同时被用作读(查询模式)和写(命令模式),但是,实际上这两者是有明显区别的,在一些业务场景中,我们希望这两者被分别对待处理,那么这种情况下,CQRS 就是一个值得考虑的选项。

为什么要把命令和查询分离?

简单来说,CQRS 模式下,模型层的接口分为且只分为两种:

  • 命令(Command),它不返回任何结果,但会改变数据的状态。
  • 查询(Query),它返回结果,但是不会改变数据的状态。

思考读写分离, 如果要向数据库插入一条数据, 那么各个字段是被指定的, 是确定的, 而读 (查询) 时, 查询条件不是确定的 (查询条件不符合数据字段描述).

知识点:

  • 在 [第 04 讲] 我们学习 REST 风格的时候,我们把 HTTP 的请求从两个维度进行划分,是否幂等,以及是否安全。按照这个角度来考量,CQRS 中的命令,可能是幂等的(例如对象更新),也可能不是幂等的(例如对象创建),但一定是不安全的;CQRS 中的查询,一定是幂等的,且一定是安全的。
  • 在 [第 07 讲] 我们学习 MVC 的一般化,其中的“第二种”典型情况时,Controller 会调用 Model 层的,执行写入操作;而 View 层会调用 Model 层,执行只读操作——看起来这不就是最适合 CQRS 的一种应用场景吗?

扩展阅读

  • AnemicDomainModel,Martin Fowler 写的批评贫血模型的文章,他自己提出了贫血和充血的概念,因此我们可以到概念的源头去,看看他做出批评的理由是什么。
  • 【基础】在模型层我们经常会和数据库打交道,SQL 是这部分的基础,如果你完全不了解 SQL,可以阅读 W3school 上的 SQL 基础教程(左侧目录中的基础教程,内容简短)。
  • 文中提到了查询对象(Query Object),这其实是一种常见的设计模式,文中举例说明了是怎么使用的,但是,如果你想知道它是怎么实现的,可以阅读 Query Object Pattern 这篇文章,上面有很好的例子。
公众号:码农架构

相关文章

网友评论

    本文标题:MVC架构解析:模型(Model)篇

    本文链接:https://www.haomeiwen.com/subject/kddlbktx.html