核心观点:
一、无论是 MVC 的分层,还是 DDD 的分层,本质是因为职责不同,职责不同体现的是,方法的内容不同。方法的内容就是职责,代表 做了哪些事情
,而所做的事情,才是我们重点关注的东西。
二、至于有的公司强制,定义的 Request,再加上 VO,DTO,DO,再加上,Domain,完全是无能的管理者的无效的过度管理的产物。至于为什么,我后边会解释,为什么叫无能的管理者的无效的过度管理的产物。
- 无能的管理者,是不知道项目分层的本质是职责的不同
- 无效的过度管理,是说这么多乱碰碰的定义是没有无效的过度管理
三、罗永浩说的一句话是对的:这个世界是一般中年人掌握的世界,他不只有制定规则的权利,还有解释规则的权利。
背景
我曾经和别人讨论过一个问题,就是,我的 接口Request
在 持久层
(DAO) 能不能引用到?
- 我的结论是可以引用。
讨论项目分层
查看维基百科的MVC
先说,MVC 分层是什么:我特意去查询了 维基百科关于 MVC 的解释: https://zh.wikipedia.org/wiki/MVC
引用来自维基百科
MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
。。。
- 模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
- 视图(View) - 界面设计人员进行图形界面设计。
- 控制器(Controller)- 负责转发请求,对请求进行处理。
实际范例
这里有一个通过 JavaScript 所实现的基于 MVC 模型,需要注意的是:MVC 不是一种技术,而是一种理念。
Java 平台企业版 (J2EE)
和其他的各种框架不一样,J2EE为模型对象(Model Objects)定义了一个规范。
视图(View)
在J2EE应用程序中,视图(View)可能由Java Server Page(JSP)担任。生成 View 的代码则可能是一个servlet的一部分,特别是在客户端服务端交互的时候。
控制器(Controller)
J2EE应用中,Controller 可能是一个servlet。
除了可直接以J2EE来撰写外,亦可用其他框架来撰写,常见的有Struts2、Spring Framework……等等。
模型(Model)
Model 则是由一个实体Bean来实现。
Java Swing
Swing是一个标准的MVC结构。ComponentUI代表View,负责描画组件。组件尤其Model层,比如JTextField的Document、JTable的TableModel、JTree的TreeModel等等。Control可能不是很明显,我们可以将Event机制看作Swing团队为开发者设计的Controller。
作为Java开发者,如果想理解MVC的结构,学习Swing的确是个不错的选择。
仔细阅读:维基百科对 MVC 的解释,发现了没有,其实,对我们 JAVA 开发人员来说,其实我们经常接触到的 MVC 也就是 Spring MVC 的 Controller 。
M
就是 我们的 controller 方法里的 参数和返回值V
在前后分离的项目中已经被前端给承接走了C
就是我们 controller 的一个方法
结论:MVC 并没有说我们的 Controller、Service、Dao 的分层
查看维基百科的 DDD
关于 DDD
是 领域驱动设计
的简称:所以在维基百科上,我们查询 领域驱动设计
链接:https://zh.wikipedia.org/wiki/領域驅動設計
Repository
对于检索特定域对象的方法应该委派给 Repository 对象,因为这样可以很容易地互换替代存储的实现
Service
强调与其他对象的关系,只定义了可以为客户做什么,不应该替代 Entity 和 Value Object 的所有行为
发现了没有,维基百科对 DDD 的定义,也没有说我的 Repository 的参数必须在我 Repository 层去定义,也没有说,我的 Service 的参数必须在我 Service 层去定义。
结论:DDD 也没有说我们的每层的参数必须单独的定义。
猜测 Controller、Service、DAO 的由来
其实,我们在学习 JAVA 的时候,一般先学 语法、然后是面向对象、然后是,数据库操作,最后就是搞一个 MVC项目
玩一玩了。
其实,我们再重新看一下我们的所谓的 MVC项目
的分层到底做了哪些事情。
- Controller:处理请求转发
- Service:处理业务逻辑
- DAO:处理持久化操作
仔细思考我说的话,他们的分层根本原因是处理的职责不同。职责不同,是因为他们所对应的方法的参数不同。
项目分层的本质
职责就是做了哪些事情,这个做了哪些事情,本质就是,方法的内容是怎么写的。
究竟是什么时候,有了,Query、Request、Response、VO、DTO、DO 的区别了呢?好像突然就流行了?
罗永浩说的一句话是对的:这个世界是一般中年人掌握的世界,他不只有制定规则的权利,还有解释规则的权利。
其实,他说不出来为什么,但是他就想这么做。如果他即使讲不清楚为什么的时候,或者说,你真的讲到了他的知识盲区了。
他就会跟你说一句话:“我是你的上级,你应该服从我。”这才是很多软件项目 半生坎坷、折戟沉沙的根本原因。
在我的多年的最佳实践中,DO 是必须的,Request、Repsonse 是必须的(而且,每个接口都需要有独立的 Request、Response,不能共享)。至于其他的什么 VO、DTO 都不是必须的。
那复杂的业务逻辑应该怎么做?
业务逻辑的处理流程的编排是另外一个问题:
可以看我引用的关于 一文教会你如何写复杂业务的代码 基于过程分解就可以解决 80% 的问题。
这个跟参数定义也没有关系。
所以,回到我最初的问题,至于,别人为了反驳我而讲的,什么 因为 DDD、MVC 是站不住脚的。**至于,项目分层是因为,处理的对应逻辑职责不同。**这句话,其实很多人都理解不到。
这句话,理解不了,我认为他很无能。至于说无效呢?那就是,你定义了很多 DTO,VO,依然没有你觉你 业务逻辑
的复杂性的问题。
业务逻辑的代码,我认为有三个点很重要:
- 可读性
- 扩展性
- 开发效率
这个并不是定义一个 DAO 的 Query 就可以解决的。 所以我说这是一个无效的管理措施。
这里分享一下,我曾经负责过的 50 个微服务的量级的项目分层怎么做的:
最佳实践是什么
其实最重要的还是,把其中的依赖管理给做好,比如,Web 层引用不到 @Table
之类的持久层注解,Dao
层,引用不到 manager
层的类定义。如果这个做不到,那么工程结构就是一团乱麻。
可以关注我,回头,我可以分享,这一套如何用
- 微服务架构怎么做?
- DDD 架构怎么做?