《企业应用架构模式》 二
模式总结
事务脚本
- 模式概要:事务脚本使用过程来组织业务逻辑,每个过程处理来自表现层的单个请求,可以适用于简单的业务场景,可以加快开发速度,去掉繁琐的分层。
-
我的思考:事务脚本并不是指现阶段很多项目中出现的“面条式”代码,而是根据简单业务场景简单处理,不引入复杂分层,一个过程走到底,对于简单/临时性的业务应用,可以快速开发/测试,省去了繁琐的框架搭建。
-
领域建模
- 模式概要:合并了行为和数据的领域对象模型,核心在于将易变的业务逻辑内聚在领域模型中。
- 我的思考:领域建模应当是开发人员/架构师需要加强的能力,通过领域建模对涉及的业务领域有更深入的了解,同时合理的建模,确保业务逻辑内聚,使企业应用更易于维护和迭代。
这方面的理论知识可以参考Eric Evans的《领域驱动干设计-软件核心复杂性应对之道》,实践相关的内容可以参考Vaughn Vernon的《实现领域驱动设计》
初学者在实践DDD的时候,首先需要改变思维方式,业务领域的分析和建模是关键,通过不断的实践总结,形成自己的一套完整的建模战术。
另外,DDD对于复杂性较高的应用系统优势更加明显,我们团队在用户系统和社区系统都进行了DDD的实践,发现相比用户系统,DDD在社区系统的优势发挥的更充分。
最后,DDD需要不停地实践,不要追求一步到位,模型可以不断地迭代完善,DDD的实践也是如此。
- 项目实践:在用户体系和社区服务系统中均有实践,
标识域
- 模式概要:为了在内存对象和数据库之间维护标识而在对象内保存的一个数据库标识域。标识域满足两个特性:唯一性、不可变性。
- 我的思考:在数据库中通常存在两种类型的唯一且不可变键,一个是业务主键,一个物理主键,那么应当使用哪个主键来作为标识域呢?
- 可以根据DDD中介绍的实体和值对象来做区分,如果是实体,那么建议是用业务主键,比如“User”和“Order”,分别可以使用userNo和orderNo来标识。而对于值对象,可以直接使用其物理主键作为标识域,比如“用户点赞信息”,可以使用物理主键id作为标识域,当然也可以使用业务联合主键(userNo和postNo)作为标识域,但是会增加复杂度,不可取
- 另外,通常情况下,我们可以将物理主键命名为以Id结尾,将业务主键命名为No结尾;
- 很多服务场景,需要将实体的标识域暴露给调用方,就要考虑安全性问题,如果你的标识域是顺序递增的long型主键,那么很可能会被攻击者遍历,从而带来一些安全风险,这时候可以做如下两种考虑:标识域不再使用顺序递增的long型主键,而是使用不可遍历的uuid等;如果没法将标识域更改为uuid,那么考虑新建一个域,存储专门供外部使用的uuid值。比如:我们在用户系统中便为User创建了一个使用uuid值的UnionId字段。
- 不建议前后端将标识域明文传递,尤其是越权访问会带来数据泄露问题的场景,比如:查询用户信息,这时候实体的标识域应当考虑从会话中获取,避免越权访问带来的数据风险
- 项目实践:订单系统中,我们使用业务主键orderNo作为Order实体的标识域,且由于orderNo形式为:yyyyMMddHHmmssSSS+sequence,被遍历的成本非常高,因此直接暴露在外使用