← 全部书单 / 系统设计

《企业应用架构模式》

《企业应用架构模式》封面
作者: 马丁·福勒
出版社: 机械工业出版社
出版年: 2004-7
原作名: Patterns of Enterprise Application Architecture
8.7
★★★★★
豆瓣评分 · 414 人评价
未标记阅读状态
OA、ERP、电商后台这类企业软件怎么写才不乱?前人踩过的坑提炼成“模式词汇表”,架构师案头的词典。

总体观点

企业应用翻来覆去就是那几类问题:业务逻辑放哪、对象怎么存进数据库、网页怎么分层。人人重复发明轮子、重复踩坑。福勒把业界验证过的解法整理成50多个模式,写成这本“模式词典”。

核心论点:架构设计不是玄学,是有据可查的“模式语言”。业务逻辑三种放法各有利弊,选错后期改不动;对象和关系数据库的“阻抗失衡”,用数据映射器、工作单元弥合。选模式就是做权衡,没有银弹。

它第一次系统回答了“企业应用怎么分层、怎么组织代码”。分层、领域模型、数据映射器、MVC成了之后二十年主流框架的底座——你天天用的很多概念都来自它。

核心观点

  1. 1. 业务逻辑三种放法:事务脚本、表模块、领域模型

    事务脚本:一个请求写一个过程,简单直接,适合小系统。表模块:按表组织、一个表配一个类,适合中等复杂度。领域模型:按业务概念建模,“订单”是有行为的对象,适合复杂业务。复杂度越高越往领域模型走;小项目硬上就是大炮打蚊子。

    个人记账用流水账本(事务脚本)就行,小公司按科目设账(表模块),上市公司得有完整会计体系(领域模型)。报销小工具用事务脚本两周上线;核心交易系统用领域模型,三年后加新业务不用推倒重来。
  2. 2. 分层:表现层、领域层、数据源层各干各的

    三层:页面只管展示,业务规则放中间层,数据库访问放底层。上层调下层,不许反过来。换数据库、换前端都不动业务逻辑,测试也能一层层测。这是全书的地基。

    餐厅:服务员只管点菜上菜,厨师只管做菜,采购只管进货。换收银系统不用重训厨师,换供应商不用重印菜单,各层独立变化、互不牵连。
  3. 3. 对象和数据库天生不对付,得请个“翻译”(数据映射器)

    面向对象讲“对象套对象”,关系数据库讲“表和外键”,硬凑就是又臭又长的SQL拼接。数据映射器是个专职翻译:对象只管业务,翻译负责存进表、捞出来拼回对象。Hibernate、MyBatis本质上就是干这个的。

    中外合资谈判得配翻译:中方说中文(对象),外方说英文(SQL)。没翻译,双方只能互相学对方语言,最后两边都说不利索——代码里SQL和业务逻辑搅成一锅粥,谁也改不动。
  4. 4. 工作单元:一次业务操作,要么全存,要么全不存

    下单要写订单表、扣库存、记流水,中间崩了怎么办?工作单元是个“记账本”:改动先记下来,最后统一提交。失败整体回滚,数据不会一半一半,还把多次数据库交互合并成一次。

    银行转账:扣A的钱和给B加钱必须同时成功,绝不能只扣不加。工作单元就是“同时”的保证人:要么两边一起变,要么当没发生过。
  5. 5. 延迟加载:用到了再去查

    查订单顺带把1000条明细全查出来?太浪费。延迟加载:先查个壳,用到明细时再去拿。省内存省查询,但用不好会变成“查一次触发1000次小查询”(N+1问题),省的全吐回去还倒贴。

    看电子书:先加载目录,点进哪章才加载正文。打开书就把500页全下载,流量直接爆炸;但每翻一页都重新下载,还不如一开始全下完。分寸要拿捏好。
  6. 6. 服务层:给业务逻辑开个统一的“前台”

    网页、App、第三方都要调“下单”,不能各调各的。服务层在领域逻辑外包一层统一入口:校验参数、调领域逻辑、记日志、管事务,套路收拢到一起。对外只有一个门,里面再复杂也不怕。

    公司前台:访客、快递、外卖先登记再分发,不让人直接闯进办公室找人。前台顺手做访客登记(日志)和身份核验(校验)。
  7. 7. 模式是词汇,不是教条

    模式是“准确讨论设计”的共同语言,不是“必须这么写”的圣经。开会说“这里用个数据映射器”,团队立刻懂你在解决什么、付出什么代价。但生搬硬套和不用一样糟——脱离上下文谈模式就是耍流氓。

    “爆炒”“清蒸”是词汇,告诉你火候手法的区别;放多少盐还得看今天的菜。评审时说“这块事务脚本就够了,别上领域模型”,一句话大家就懂——模式语言让讨论变精确。
树状思维导图

全书思维导图 · 知识脉络树

💡 拖拽平移 · 滚轮缩放 · 点击分支圆点折叠/展开
已复制思维导图大纲到剪贴板!

全书结构

  1. 第1章 分层

    将企业级系统严格划分为表现层、领域层与数据源层,层与层单向依赖,高层不知晓底层技术细节以实现隔离演进。

    表现层由网页切换为微信小程序或原生 App 时,只需适配接口传输格式,底层的订单领域计算与数据库操作完全无需改动。
  2. 第2章 组织领域逻辑

    在事务脚本(简单直线业务)、表模块(基于结构化数据集)与领域模型(复杂对象行为网络)三大范式之间权衡选型。

    简单的后台录入页面用事务脚本十几行写完最快;而涵盖阶梯计费、优惠叠加与退款拆单的复杂电商结算必须使用领域模型。
  3. 第3章 映射到关系数据库

    化解对象与关系数据库之间的阻抗失配(类继承、多对多关联),在表数据入口、活动记录与数据映射器间做出架构抉择。

    复杂企业应用选用数据映射器(Data Mapper,如 Hibernate/MyBatis),将内存中的业务对象与数据库表结构完全解耦。
  4. 第4章 Web表现层

    运用 MVC 模式分离输入处理、模型更新与界面渲染,在页面控制器(Page Controller)与前端控制器(Front Controller)间选型。

    Spring MVC 和众多 Web 框架采用前端控制器(DispatcherServlet)统一拦截请求、完成鉴权与日志,再分发给具体的业务 Controller。
  5. 第5章 并发

    处理跨请求长时间业务交互时的并发冲突,权衡悲观离线锁、乐观离线锁(基于版本号 version)与粗粒度锁的适用场景。

    用户编辑合同草稿时在数据库加一个 `version` 字段,提交时执行 `WHERE id=1 AND version=2`,如果被他人抢先修改则提示冲突。
  6. 第6章 会话状态

    在客户端会话(Cookie/Token)、服务器端内存 Session 与集中式数据库/Redis 会话间权衡系统无状态性与性能开销。

    集群环境下将用户登录会话统一放在 Redis 集中缓存中,应用服务器保持完全无状态,使得前端节点可以随时弹性增减。
  7. 第7章 分布策略

    分布式进程间通信开销极其昂贵,分布式系统的首要定律是“不要分布”;若必须跨网络,则采用粗粒度的远程门面与 DTO。

    避免循环发起二十次网络 RPC 请求分别获取商品属性,而是通过远程门面(Remote Facade)一个接口打包返回所需的完整 DTO。
  8. 第8章 通盘考虑

    综合考虑业务复杂度、并发吞吐要求、重构成本与团队技能水平,严密组合各个模式词汇,杜绝过度设计的教条主义。

    初创期内部报表系统选择简单的 Active Record 快速开发上线,随着业务规则膨胀演化后再平滑重构为分层的领域模型。
  9. 第二部分 模式(领域逻辑、数据源、对象-关系与Web模式)

    企业级持久化底层百科:工作单元(跟踪变更合并事务)、标识映射(确保同一记录唯一实例)与延迟加载(按需加载关联)。

    工作单元(Unit of Work)记录一次业务操作中所有新增、修改和删除的对象,在事务提交前按最优顺序执行单次批量数据库写入。
返回 系统设计 目录

观点与结构均为转述总结,非原文摘录。封面图片来自豆瓣读书,仅作展示。

豆瓣评分与评价人数为逐本人工核实当天的数值。 · GitHub 仓库 · v1.0.0