# Domain领域业务层与ADM模式解说
PhalApi使用的是ADM分层模式,Domain是连接Api层与Model层的桥梁。
## 何为Api-Domain-Model模式?
在传统Web框架中,惯用MVC模式。可以说,MVC模式是使用最为广泛的模式,但同时也可能是误解最多的模式。然而,接口服务这一领域,与传统的Web应用所面向的领域和需要解决的问题不同,最为明显的是接口服务领域中没有View视图。如果把MVC模式生搬硬套到接口服务领域,不但会产生更多对MVC模式的误解,还不利于实际接口服务项目的开发和交付。
仔细深入地再思考一番,接口服务除了需要处理输入和输出,以及从持久化的存储媒介中提取、保存、删除、更新数据外,还有一个相当重要且不容忽视的任务——处理特定领域的业务规则。而这些规则的处理几乎都是逻辑层面上对数据信息的加工、转换、处理等操作,以满足特定场景的业务需求。对于这些看不见,摸不着,听不到的领域规则处理,却具备着交付有价值的业务功能的使命,与此同时也是最为容易出现问题,产生线上故障,引发损失的危险区。所以,在接口服务过程中,我们应该把这些领域业务规则的处理,把这些受市场变化而频繁变动的热区,单独封装成一层,并配套完备的自动化测试体系,保证核心业务的稳定性。
基于以上考虑,在MVC模式的基础上,我们去掉了View视图层,添加了Domain领域业务层。从而涌现了Api-Domain-Model模式,简称ADM模式。
简单来说,
+ **Api层** 称为接口服务层,负责对客户端的请求进行响应,处理接收客户端传递的参数,进行高层决策并对领域业务层进行调度,最后将处理结果返回给客户端。
+ **Domain层** 称为领域业务层,负责对领域业务的规则处理,重点关注对数据的逻辑处理、转换和加工,封装并体现特定领域业务的规则。
+ **Model层** 称为数据模型层,负责技术层面上对数据信息的提取、存储、更新和删除等操作,数据可来自内存,也可以来自持久化存储媒介,甚至可以是来自外部第三方系统。
## 专注领域的Domain业务层
Domain领域业务层,主要关注的是领域业务规则的处理。在这一层,不应过多关注外界客户端接口调用的签名验证、参数获取、安全性等问题,也不应过多考虑数据从何而来、存放于何处,而是着重关注对领域业务数据的处理。
## ADM职责划分与调用关系
传统的接口开发,由于没有很好的分层结构,而且热衷于在一个文件里面完成绝大部分事情,最终导致了臃肿漫长的代码,也就是通常所说的意大利面条式的代码。
在PhalApi中,我们针对接口领域开发,提供了新的分层思想:Api-Domain-Model模式。即便这样,如果项目在实际开发中,仍然使用原来的做法,纵使再好的接口开发框架,也还是会退化到原来的局面。
为了能让大家更为明确Api接口层的职责所在,我们建议:
Api接口服务层应该做:
+ 应该:对用户登录态进行必要的检测
+ 应该:控制业务场景的主流程,创建领域业务实例,并进行调用
+ 应该:进行必要的日记纪录
+ 应该:返回接口结果
+ 应该:调度领域业务层
Api接口服务层不应该做:
+ 不应该:进行业务规则的处理或者计算
+ 不应该:关心数据是否使用缓存,或进行缓存相关的直接操作
+ 不应该:直接操作数据库
+ 不应该:将多个接口合并在一起
Domain领域业务层应该做:
+ 应该:体现特定领域的业务规则
+ 应该:对数据进行逻辑上的处理
+ 应该:调度数据模型层或其他领域业务层
Domain领域业务层不应该做:
+ 不应该:直接实现数据的操作,如添加并实现缓存机制
Model数据模型层应该:
+ 应该:进行数据库的操作
+ 应该:实现缓存机制
在明确了上面应该做的和不应该做的,并且也完成了接口的定义,还有验收测序驱动开发的场景准备后,相信这时,即使是新手也可以编写出高质量的接口代码。因为他会受到约束,他知道他需要做什么,主要他按照限定的开发流程和约定稍加努力即可。
如果真的这样,相信我们也就慢慢能体会到精益开发的乐趣。
至于调用关系,整体上讲,应根据从Api接口层、Domain领域层再到Model数据源层的顺序进行开发。
在开发过程中,需要注意不能**越层调用**也不能**逆向调用**,即不能Api调用Model。而应该是**上层调用下层,或者同层级调用**,也就是说,我们应该:
+ Api层调用Domain层
+ Domain层调用Domain层
+ Domain层调用Model层
+ Model层调用Model层
如果用一张图来表示,则是:
![](http://7xiz2f.com1.z0.glb.clouddn.com/ch-2-api-domain-model-call.png)
为了更明确调用的关系,以下调用是**错误**的:
+ 错误的做法1:Api层直接调用Model层
+ 错误的做法2: Domain层调用Api层,也不应用将Api层对象传递给Domain层
+ 错误的做法3: Model层调用Domain层
#### 这样的约定,便于我们形成统一的开发规范,降低学习维护成本。比如需要添加缓存,我们知道应该定位到Model层数据源进行扩展;若发现业务规则处理不当,则应该进入Domain层探其究竟;如果需要对接口的参数进行调整,即使是新手也知道应该找到对应的Api文件进行改动。