知识卡片
领域模型持久化机制的渐进选型:入口→活动记录→数据映射器
内容
如果领域逻辑简单、领域类和数据库表基本一一对应,直接让每个领域对象自己负责与数据库交互,即活动记录,是最省事的选择——可以把它理解成”从行数据入口出发,把领域逻辑逐步加进这个类里”,尤其当从多个事务脚本中发现重复代码时自然演化出来。但随着领域逻辑变得复杂,活动记录会逐渐力不从心:领域类与表的一对一关系会因为把逻辑拆到更小的类中而失效,关系数据库天生不支持继承,导致策略模式等轻量OO技巧很难用上,而且你会希望脱离数据库也能随时测试领域逻辑。这时给领域模型套一层”入口”(行数据/表数据入口)虽然能缓解一些问题,却仍把数据库方案和领域模型耦合在一起,还平添了入口域到领域对象域之间的转换复杂度——作者因此不推荐把入口用作领域模型的首选持久化机制。真正的解法是让领域模型和数据库彻底独立,用一个专门的间接层(数据映射器)负责两者之间所有的存取映射,让双方能各自独立演化——这是最复杂的一种数据库映射架构,但换来了两层的完全解耦。这些持久化机制并不互斥,但首选机制只应该选一个,不要混用导致凌乱;即便以数据映射器为首选,仍可以用数据入口去封装被视为外部接口的表或服务。
结构图:
flowchart LR
A["领域逻辑简单<br/>类与表一一对应"] -->|复杂度上升| B["活动记录不再够用<br/>(无法用继承/策略等OO技巧)"]
B -->|加一层入口| C["入口耦合数据库方案<br/>仍有转换复杂度,不推荐首选"]
B -->|彻底解耦| D["数据映射器<br/>领域模型与数据库互相独立"]
参考来源
- 位置:《企业应用架构模式》第一部分"表述"之"第3章 映射到关系数据库"之"3.1 架构模式"(源文件:_epub-src/OEBPS/Text/000017.html)
- 结论依据:原文说明"随着领域逻辑变得更加复杂,它就慢慢转变成一个大的领域模型,简单的活动记录开始不能满足要求了……在这种情况下,入口可以解决一些问题,但它仍然将数据库方案和领域模型耦合在一起……我不推荐把入口用作领域模型的首选持久化机制。如果领域逻辑非常简单并且类和表十分一致,使用活动记录就足够了。如果领域逻辑比较复杂,数据映射器才是需要的",直接支撑本卡结构图。
- 原始内容:这个数据映射器处理数据库和领域模型之间所有的存取操作,并且允许双方都能独立变化。这是数据库映射架构中最复杂的架构,但它的好处是把两个层完全独立了。