《企业应用架构模式》

总体观点
企业应用翻来覆去就是那几类问题:业务逻辑放哪、对象怎么存进数据库、网页怎么分层。人人重复发明轮子、重复踩坑。福勒把业界验证过的解法整理成50多个模式,写成这本“模式词典”。
核心论点:架构设计不是玄学,是有据可查的“模式语言”。业务逻辑三种放法各有利弊,选错后期改不动;对象和关系数据库的“阻抗失衡”,用数据映射器、工作单元弥合。选模式就是做权衡,没有银弹。
它第一次系统回答了“企业应用怎么分层、怎么组织代码”。分层、领域模型、数据映射器、MVC成了之后二十年主流框架的底座——你天天用的很多概念都来自它。
核心观点
-
1. 业务逻辑三种放法:事务脚本、表模块、领域模型
事务脚本:一个请求写一个过程,简单直接,适合小系统。表模块:按表组织、一个表配一个类,适合中等复杂度。领域模型:按业务概念建模,“订单”是有行为的对象,适合复杂业务。复杂度越高越往领域模型走;小项目硬上就是大炮打蚊子。
个人记账用流水账本(事务脚本)就行,小公司按科目设账(表模块),上市公司得有完整会计体系(领域模型)。报销小工具用事务脚本两周上线;核心交易系统用领域模型,三年后加新业务不用推倒重来。 -
2. 分层:表现层、领域层、数据源层各干各的
三层:页面只管展示,业务规则放中间层,数据库访问放底层。上层调下层,不许反过来。换数据库、换前端都不动业务逻辑,测试也能一层层测。这是全书的地基。
餐厅:服务员只管点菜上菜,厨师只管做菜,采购只管进货。换收银系统不用重训厨师,换供应商不用重印菜单,各层独立变化、互不牵连。 -
3. 对象和数据库天生不对付,得请个“翻译”(数据映射器)
面向对象讲“对象套对象”,关系数据库讲“表和外键”,硬凑就是又臭又长的SQL拼接。数据映射器是个专职翻译:对象只管业务,翻译负责存进表、捞出来拼回对象。Hibernate、MyBatis本质上就是干这个的。
中外合资谈判得配翻译:中方说中文(对象),外方说英文(SQL)。没翻译,双方只能互相学对方语言,最后两边都说不利索——代码里SQL和业务逻辑搅成一锅粥,谁也改不动。 -
4. 工作单元:一次业务操作,要么全存,要么全不存
下单要写订单表、扣库存、记流水,中间崩了怎么办?工作单元是个“记账本”:改动先记下来,最后统一提交。失败整体回滚,数据不会一半一半,还把多次数据库交互合并成一次。
银行转账:扣A的钱和给B加钱必须同时成功,绝不能只扣不加。工作单元就是“同时”的保证人:要么两边一起变,要么当没发生过。 -
5. 延迟加载:用到了再去查
查订单顺带把1000条明细全查出来?太浪费。延迟加载:先查个壳,用到明细时再去拿。省内存省查询,但用不好会变成“查一次触发1000次小查询”(N+1问题),省的全吐回去还倒贴。
看电子书:先加载目录,点进哪章才加载正文。打开书就把500页全下载,流量直接爆炸;但每翻一页都重新下载,还不如一开始全下完。分寸要拿捏好。 -
6. 服务层:给业务逻辑开个统一的“前台”
网页、App、第三方都要调“下单”,不能各调各的。服务层在领域逻辑外包一层统一入口:校验参数、调领域逻辑、记日志、管事务,套路收拢到一起。对外只有一个门,里面再复杂也不怕。
公司前台:访客、快递、外卖先登记再分发,不让人直接闯进办公室找人。前台顺手做访客登记(日志)和身份核验(校验)。 -
7. 模式是词汇,不是教条
模式是“准确讨论设计”的共同语言,不是“必须这么写”的圣经。开会说“这里用个数据映射器”,团队立刻懂你在解决什么、付出什么代价。但生搬硬套和不用一样糟——脱离上下文谈模式就是耍流氓。
“爆炒”“清蒸”是词汇,告诉你火候手法的区别;放多少盐还得看今天的菜。评审时说“这块事务脚本就够了,别上领域模型”,一句话大家就懂——模式语言让讨论变精确。
全书思维导图 · 知识脉络树
全书结构
-
第1章 分层
将企业级系统严格划分为表现层、领域层与数据源层,层与层单向依赖,高层不知晓底层技术细节以实现隔离演进。
表现层由网页切换为微信小程序或原生 App 时,只需适配接口传输格式,底层的订单领域计算与数据库操作完全无需改动。 -
第2章 组织领域逻辑
在事务脚本(简单直线业务)、表模块(基于结构化数据集)与领域模型(复杂对象行为网络)三大范式之间权衡选型。
简单的后台录入页面用事务脚本十几行写完最快;而涵盖阶梯计费、优惠叠加与退款拆单的复杂电商结算必须使用领域模型。 -
第3章 映射到关系数据库
化解对象与关系数据库之间的阻抗失配(类继承、多对多关联),在表数据入口、活动记录与数据映射器间做出架构抉择。
复杂企业应用选用数据映射器(Data Mapper,如 Hibernate/MyBatis),将内存中的业务对象与数据库表结构完全解耦。 -
第4章 Web表现层
运用 MVC 模式分离输入处理、模型更新与界面渲染,在页面控制器(Page Controller)与前端控制器(Front Controller)间选型。
Spring MVC 和众多 Web 框架采用前端控制器(DispatcherServlet)统一拦截请求、完成鉴权与日志,再分发给具体的业务 Controller。 -
第5章 并发
处理跨请求长时间业务交互时的并发冲突,权衡悲观离线锁、乐观离线锁(基于版本号 version)与粗粒度锁的适用场景。
用户编辑合同草稿时在数据库加一个 `version` 字段,提交时执行 `WHERE id=1 AND version=2`,如果被他人抢先修改则提示冲突。 -
第6章 会话状态
在客户端会话(Cookie/Token)、服务器端内存 Session 与集中式数据库/Redis 会话间权衡系统无状态性与性能开销。
集群环境下将用户登录会话统一放在 Redis 集中缓存中,应用服务器保持完全无状态,使得前端节点可以随时弹性增减。 -
第7章 分布策略
分布式进程间通信开销极其昂贵,分布式系统的首要定律是“不要分布”;若必须跨网络,则采用粗粒度的远程门面与 DTO。
避免循环发起二十次网络 RPC 请求分别获取商品属性,而是通过远程门面(Remote Facade)一个接口打包返回所需的完整 DTO。 -
第8章 通盘考虑
综合考虑业务复杂度、并发吞吐要求、重构成本与团队技能水平,严密组合各个模式词汇,杜绝过度设计的教条主义。
初创期内部报表系统选择简单的 Active Record 快速开发上线,随着业务规则膨胀演化后再平滑重构为分层的领域模型。 -
第二部分 模式(领域逻辑、数据源、对象-关系与Web模式)
企业级持久化底层百科:工作单元(跟踪变更合并事务)、标识映射(确保同一记录唯一实例)与延迟加载(按需加载关联)。
工作单元(Unit of Work)记录一次业务操作中所有新增、修改和删除的对象,在事务提交前按最优顺序执行单次批量数据库写入。