MVC 三层架构中的 M 表示 Model,V 表示 View,C 表示 Controller。它将整个项目分为三层:展示层、逻辑层、数据层。熟悉 Django 的朋友可以这么映射,M 就是我们编写的 models.py 表示数据层,定义数据的存储,而 V 就是 views.py,里面存放着大量的业务逻辑,C 就是 urls.py 控制着路由的访问。
距离上次更新已经有 7 天了,只要停下来一天,就会有第二天,第三天,越是不写,就越不知道写什么。这就是惯性的力量,无论是勤劳还是懒惰,都会产生惯性,于是勤劳者越来越勤劳,懒惰者越来越懒惰,学霸越来越霸,学渣越来越渣。时间一长,就会觉得自己根本无法改变自己,总会回到我们习以为常的状态。所以,朋友们,一定要警惕惯性,他使我们越来越好,也会使我们越来越坏,这不,我又逼着自己更新了。
之所以停止了更新,一方面是懒惰的小人击败了勤奋,另一方面是因为时间不够用。下班后就那么点时间,用于这个就不能用于那个,而我又是一个喜欢写代码的人,一旦开始写代码,时间就飞快的流失,从晚上 8 点写到晚上 12 点,也是一眨眼的功夫,明天还要上班,我不可能再熬夜。熬夜会把第二天废掉,得不偿失。最近在学习并尝试 golang 的 Web 开发,已经入门了,从以前 Django 的 MVC 模式,也渐渐的切换到了 Golang 的 DDD 模式,感觉 DDD 更具有面向对象风格,而 MVC 更像是一种面向过程的风格。
今天展开来说,什么是 MVC,什么是 DDD,它们分别适合什么样的场景。
什么是 MVC、什么是 DDD
MVC 三层架构中的 M 表示 Model,V 表示 View,C 表示 Controller。它将整个项目分为三层:展示层、逻辑层、数据层。熟悉 Django 的朋友可以这么映射,M 就是我们编写的 models.py 表示数据层,定义数据的存储,而 V 就是 views.py,里面存放着大量的业务逻辑,C 就是 urls.py 控制着路由的访问。前端请求首先访问 Controller,然后是 View,最后是 Model,这就是面向数据访问的过程来定义的架构。
MVC 的缺点就是虽然 M 和 V 是两份文件,但是数据和业务逻辑高度耦合的,也就是说,M 只负责了数据的定义,而数据的操作都在 V,一旦修改了 M,改 V 是真是苦不堪言,这种将数据与操作分离的特点,破坏了面向对象的封装特性,是一种典型的面向过程的编程风格。
与之对应,将数据和操作定义在一起,就是 DDD,全称叫领域驱动设计(Domain Driven Design,简称 DDD),领域驱动设计这个概念并不新颖,早在 2004 年就被提出了,不过现在又被大家重视起来,还是基于微服务的兴起,微服务就是大服务拆分为小服务嘛,这样就要做好业务模块划分,自然也就加速了领域驱动设计的盛行。
DDD 开发模式实现的代码,也是按照 MVC 三层架构分层的。Controller 层还是负责暴露 API 接口,M 层还是负责数据存取,V 层负责核心业务逻辑。它跟 MVC 的主要区别还是 M 和 V 的不同。传统的 M 只定义数据数据的结构,不定义数据的操作,而 DDD 开发模式,M 不仅定义数据的结构,还定义数据的操作。
比如 Django 的 M 和 V 可能是这样的:
M
#models.py
fromdjango.contrib.auth.modelsimportAbstractUser
fromdjango.dbimportmodels
#数据模型的定义
classUser(AbstractUser):
"""
数据的定义
"""
...
classMeta:
db_table='user'
verbose_name='用户信息'
verbose_name_plural=verbose_name
M
#views.py
classUserViewSet(viewsets.ModelViewSet):
"""
数据的操作、增删改查
"""
...
Golang 的M:
//User.go
typeUserstruct{
//数据的定义
...
}
//数据的操作、增删改查
func(u*User)BeforeSave()error{
...
}
func(u*User)Prepare(){
...
}
func(u*User)Save(db*gorm.DB)(*User,error){
...
}
func(u*User)UpdateAUser(db*gorm.DB,uiduint32)(*User,error){
...
}
func(u*User)DeleteAUser(db*gorm.DB,uiduint32)(int64,error){
...
}
Golang 的V
func(server*Server)DeleteUser(whttp.ResponseWriter,r*http.Request){
vars:=mux.Vars(r)
user:=models.User{}
uid,err:=strconv.ParseUint(vars["id"],10,32)
iferr!=nil{
responses.ERROR(w,http.StatusBadRequest,err)
return
}
tokenID,err:=auth.ExtractTokenID(r)
iferr!=nil{
responses.ERROR(w,http.StatusUnauthorized,errors.New("Unauthorized"))
return
}
iftokenID!=0&&tokenID!=uint32(uid){
responses.ERROR(w,http.StatusUnauthorized,errors.New(http.StatusText(http.StatusUnauthorized)))
return
}
_,err=user.DeleteAUser(server.DB,uint32(uid))
iferr!=nil{
responses.ERROR(w,http.StatusInternalServerError,err)
return
}
w.Header().Set("Entity",fmt.Sprintf("%d",uid))
responses.JSON(w,http.StatusNoContent,"")
}
里面调用了M中的 DeleteAUser,以后修改 Model 时,只需要修改函数 DeleteAUser,而不需要修改V。
注意,MVC 和 DDD 与编程语言和框架都没有关系,因为正好手边有对应的代码,就拿来用了。
MVC 和 DDD 分别适合什么样的场景?
MVC 适合简单的业务,DDD 适合复杂的业务,为什么这么说呢?
如果系统业务比较简单,简单到就是基于 SQL 的 CRUD 操作,那么根本不需要动脑子精心设计 DDD 模型,MVC 模型就足以应付这种简单业务的开发工作。因为业务比较简单,即便我们使用 DDD,那模型本身包含的业务逻辑也并不会很多,设计出来的领域模型也会比较单薄,跟 MVC 差不多,没有太大意义。
你可能会问,DDD 不就是把部分数据的操作放在了模型里面吗,为什么就适合复杂的业务呢?
不夸张地讲,MVC 模式的开发,大部分都是 SQL 驱动(SQL-Driven)的开发模式。我们接到一个后端接口的开发需求的时候,就去看接口需要的数据对应到数据库中,需要哪张表或者哪几张表,然后思考如何编写 SQL 语句来获取数据。之后就是定义 models.py 编写 views.py 中的视图函数,你可以这么理解,views.py 中就是各种 SQL 语句。而 SQL 语句是不能复用的,新接口开发即使有部分相同的逻辑,也只能重新编写视图函数。
而 DDD 开发模式下,我们需要事先理清楚所有的业务,定义领域模型所包含的属性和方法。领域模型相当于可复用的业务中间层。新功能需求的开发,都基于之前定义好的这些领域模型来完成。越复杂的系统,对代码的复用性、易维护性要求就越高,我们就越应该花更多的时间和精力在前期设计上。DDD 开发模式,正好需要我们前期做大量的业务调研、领域模型设计,所以它更加适合这种复杂系统的开发。
最后的话
平时做 Web 开发,基本上,都是使用 MVC 架构,就连 Spring 的官方 Demo 也是 MVC 模式,也就是说 MVC 仍然是主流,因为项目之前就是 MVC 架构,保持不变的成本最小。
但 MVC 是典型的面向过程风格的设计,不适合复杂的系统,比如金融类系统、账务核算系统。DDD 架构把数据和操作封装在一起,对数据的操作可以复用,是面向对象风格的设计,比较适合复杂的业务系统。
一句话,简单的系统,就用 MVC,复杂的系统就用 DDD。
©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经