知识卡片

三种领域逻辑模式对应的数据源层选择框架

结构图卡

内容

选定领域层模式后,数据源层的选择直接被它驱动。事务脚本的数据源:即便是最简单的事务脚本,也应该把数据库逻辑单独分离出去(而不是让脚本自带数据库操作),可选行数据入口或表数据入口,主要取决于实现平台是否方便、以及系统未来的走向——如果平台提供丰富的记录集工具(尤其是UI工具和事务性断接记录集),天平会明显倒向表数据入口;一旦选定,通常不需要额外的O/R映射模式,因为内存结构和数据库结构高度一致,工作单元也不是必需的(脚本内部跟踪变化通常很容易),并发问题也简单——脚本基本对应一个系统事务,可以整体封装在单个事务里,唯一需要操心的异常是”一个请求读出数据编辑、下一个请求才保存”这种跨请求场景,用乐观离线锁处理即可,实现容易又能避免挂起会话导致的大面积加锁。表模块的数据源:几乎是天作之合的固定搭配——表数据入口与记录集配合得天衣无缝,数据源层基本不需要再加别的功能,如果记录集本身自带某种并发控制机制,它实质上就顺带扮演了工作单元的角色,进一步压低了开销。领域模型的数据源:最复杂也最有意思——模型简单(十几个与数据库相关的类)时活动记录就够用,想要更松耦合可以上表/行数据入口,做不做这层分离工作量差别不大;复杂度继续上升就要考虑数据映射器,它能让领域模型尽可能独立于其他层,但也是三者中实现最复杂的,除非团队实力很强或者找到了简化映射的办法,否则强烈建议直接买一个映射工具;一旦走上数据映射器这条路,全套O/R映射模式都会派上用场,其中工作单元尤其值得关注,因为它是并发控制的焦点。

结构图

flowchart TB
  A["领域层模式"] --> B["事务脚本"]
  A --> C["表模块"]
  A --> D["领域模型"]
  B --> B1["行/表数据入口<br/>视记录集工具丰富度而定"]
  B1 --> B2["无需额外O/R映射<br/>并发靠乐观离线锁"]
  C --> C1["表数据入口(天作之合)"]
  C1 --> C2["记录集自带并发控制<br/>≈工作单元"]
  D --> D1["简单→活动记录"]
  D --> D2["中等→表/行数据入口"]
  D --> D3["复杂→数据映射器<br/>+全套O/R映射模式<br/>重点关注工作单元"]

参考来源

- 位置:《企业应用架构模式》第一部分"表述"之"第8章 通盘考虑"之"8.2 深入到数据源层"(源文件:_epub-src/OEBPS/Text/000051.html、000052.html、000053.html) - 结论依据:原文说明"最简单的事务脚本包含其自身的数据库逻辑,但是,即使在最简单的情况下,我也会尽量避免这样做……选择表模块最主要的原因是有一个好的记录集框架……这就需要一个与记录集配合良好的数据库映射模式,这就是表数据入口……如果领域模型相当简单……则活动记录就可以了……随着复杂度的进一步增加,可以考虑使用数据映射器……我特别推荐工作单元,它是并发控制的焦点",直接支撑本卡结构图。 - 原始内容:在这种情况下,一般使用乐观离线锁。它不但容易实现,而且可以满足用户的需要,并避免了由于挂起会话所导致的大面积加锁情况。