上一篇讨论了架构范式的通用理论。本节以文本处理为例,完整推演一个领域架构范式的构建过程——从问题本质分析到架构设计,从范式提炼到实践验证。文本处理是信息科技的基础能力,从编译器到搜索引擎,从编辑器到自然语言处理,无处不在。它是理解架构范式的绝佳切入点。
文本处理的核心问题是:将输入文本转换为期望的输出。这个转换过程可以用统一模型描述:
输入文本 → [处理管道] → 输出结果但这个模型过于笼统。不同类型的文本处理,其架构范式差异巨大。关键在于区分文本的结构化程度。
编程语言处理、配置语言处理、DSL 处理等强结构化文本。
编译器 Pipeline 是最经典的文本处理架构范式。其核心思想是:将文本处理分解为多个独立的阶段,数据在阶段间以标准化的数据结构传递。
| 决策点 | 选项 | 权衡 |
|---|---|---|
| 词法分析与语法分析的边界 | 正则/自动生成 vs 手写 | 自动生成方便但性能差,手写灵活但开发成本高 |
| AST 的表示 | 具体语法树 vs 抽象语法树 | 具体树保留更多细节(如括号),抽象树更适合分析 |
| 阶段间数据格式 | 统一 IR vs 各阶段自定义 | 统一 IR 便于跨阶段优化,自定义 IR 更灵活 |
| 错误处理 | 急停 vs 错误恢复 | 急停简单但用户体验差,错误恢复复杂但可以一次报多个错 |
编译器 Pipeline 的核心范式要素:
编辑器、文档处理、富文本处理等需要频繁修改文本结构的场景。
DOM 操作范式的核心思想是:将文本加载为内存中的树形数据结构(DOM),通过对树的增删改操作来处理文本。
此范式与《架构分解与全局性功能设计》中的 IO DOM 模式高度一致:
| 决策点 | 选项 | 权衡 |
|---|---|---|
| DOM 粒度 | 细粒度(每个标签一个节点)vs 粗粒度 | 细粒度灵活但内存大,粗粒度省内存但操作受限 |
| 增量更新 | 全量重建 vs 增量 Diff | 全量简单但性能差,增量复杂但性能好 |
| 并发访问 | 读写锁 vs Copy-on-Write | 读写锁粒度难控制,COW 内存开销大 |
大文件处理、日志分析、网络数据流等无法一次性加载到内存的场景。
流式处理范式与《架构分解与全局性功能设计》中的 SAX/Visitor 模式本质相同。它们的核心问题是:
改进方向:将流式处理与 DOM 操作结合——流式处理做初步过滤,DOM 操作做精细处理。
| 原则 | 说明 | 典型反模式 |
|---|---|---|
| 管道正交性 | 各阶段关注点分离,互不干扰 | 阶段间隐式依赖,改一个影响另一个 |
| 中间表示标准化 | 阶段间数据格式明确 | 用全局变量在阶段间传递数据 |
| 可插拔阶段 | 阶段可增删替换 | 阶段间强耦合,无法独立替换 |
| 流式优先 | 大数据场景优先考虑流式处理 | 对大文件做全量 DOM 加载 |
核心权衡:内存效率 vs 处理灵活性。
Go 编译器采用了经典的 Pipeline 范式:源代码 → 词法分析 → 语法分析 → 类型检查 → SSA 中间表示 → 优化 → 机器码生成。各阶段接口清晰,可独立测试。
浏览器渲染引擎融合了多种范式:HTML 解析(Pipeline → DOM)、CSS 解析(Pipeline → CSSOM)、布局(DOM 操作)、绘制(DOM → 像素流)、合成(流式处理)。
正则表达式无法处理嵌套结构,强行解析会导致不可预测的结果。这是典型的范式选择错误——应该使用 DOM 操作范式而非简单的正则匹配。
对 GB 级日志文件做全量 DOM 加载,导致内存溢出。应该使用流式处理范式。
参见第64讲「不断完善的架构范式」——架构范式的通用理论。参见第60讲「架构分解:边界,不断重新审视边界」(详见架构思维/架构设计篇对应章节)——DOM 操作范式与 IO DOM 的对应关系。