架构文档:连接系统职责、运行场景与实现
从读者问题选择视图,分清软件对象、源码、实例和阶段,用静态文档站案例连接结构、部署、搜索、交付、证据与变更维护。
从读者要判断的事情开始
接手一个项目时,读者通常需要回答:系统为谁完成什么事情,哪些对象负责结果,一次操作经过哪里,故障会影响谁,以及修改后怎样检查和交付。架构文档将这些问题连接起来,让读者从抽象职责进入具体工作。
本页面向懂基本编程、了解源码和配置、初次接触某个项目的读者。这里的“视图”是围绕一类问题选择的系统信息,可以由图、表和文字共同表达。例如,结构视图说明职责及关系,运行视图追踪一个具体场景,部署视图说明软件实例在某个环境中的位置。先确定当前要支持的判断,再选择视图和细节。阅读路径的一般安排见知识组织与理解路径;本页集中处理系统对象、边界和跨视图对应。
| 读者问题 | 需要建立的认识 | 可采用的表达 |
|---|---|---|
| 系统为谁完成什么,哪些事情由外部承担? | 使用者、系统目的、外部系统及责任边界 | 上下文文字或关系图 |
| 由哪些应用、存储或模块承担职责? | 组成、重要接口、调用或数据联系 | 职责表、结构图及必要局部展开 |
| 这些软件运行在哪里? | 环境、实例、网络及访问条件 | 部署图、环境差异表 |
| 一次操作怎样得到结果? | 触发、参与者、顺序、状态和失败含义 | 步骤、时序图、状态说明 |
| 怎样开发、发布和恢复? | 源码入口、检查、产物、版本与操作前提 | 修改入口表、交付流程、诊断说明 |
| 为什么这样选择,何时需要重估? | 驱动约束、替代方案、理由与代价 | 就近说明或重要决策记录 |
这张表用来发现当前问题缺少什么。一个命令行工具可能只需职责、输入输出和操作说明;多应用系统可能需要分开运行和部署。C4 官方也建议只选择增加价值的层级。图和章节的数量随解释需要决定。1
先分清对象和关系
软件、源码、实例和阶段
“订单服务”可以表示一种软件职责,“订单服务生产实例 A”表示该软件在某个环境中的运行实例,orders/ 表示源码组织位置,“构建订单服务”表示交付阶段的动作。这四种对象相互关联,各自回答不同问题。
C4 的 container 是应用或数据存储等运行边界。浏览器应用、服务端应用和内容存储都可以承担这样的职责。Java 包、源码目录和库用于组织代码;Docker 容器提供一种执行环境。文档中采用“应用”“存储”“执行节点”等容易识别的名称,并在需要使用 C4 术语时交代其含义。2
| 表达的关系 | 含义 | 需要核对什么 |
|---|---|---|
| 系统包含应用,应用包含组件 | 软件职责的分解 | 子对象属于哪个整体,是否仍保留必要外部联系 |
| 模块导入库 | 源码依赖 | 实际导入、用途及启用路径;不能仅据此确认运行调用 |
| 客户端请求服务 | 运行联系 | 请求方向、动作、协议和影响结果的条件 |
| 构建器生成静态文件 | 生成关系 | 输入、生成阶段、输出及后续消费方 |
| 应用实例运行在设备上 | 部署映射 | 实例属于哪个软件对象,适用哪个环境 |
| 构建通过后部署 | 工作步骤依赖 | 工作流中是否真的存在该依赖,前置失败怎样处理 |
结构层级表达“由什么组成”;观察视角表达“此刻要看什么”;部署映射连接软件与环境;工作阶段表达事情的先后。4+1 方法将逻辑、进程、开发组织和物理部署分开,并用场景连接它们,提供了检查混淆的办法。源码模块组织属于其 development view,进程与并发属于 process view;使用这些名称时要保留原来的关注点。3
边界和身份怎样帮助判断
边界可以表达软件责任、业务所有权、网络访问或信任条件。图上的框应说明自己表达哪一种边界。一次外部 API 调用穿过网络边界,也可能穿过所有权和信任边界;这些条件影响错误处理、认证和维护责任,不能全靠同一个外框暗示。
同一对象在不同视图中保持身份对应。例如 order-api 是应用,order-api-prod-a 是生产实例;场景中执行校验和写入的参与者应接回 order-api 的职责。简单单页直接使用稳定名称即可;多个对象重名或跨多页频繁引用时,稳定标识能减少误认。
进入局部时说明展开哪个上层对象、哪些外部联系继续存在,以及此次省略哪些细节。接口、权限、持久化和异步边界会改变行动判断时,需要保留。纯内部函数划分在支持具体修改时再展开。总览和局部的链接可以用“跟踪提交订单”“查看生产位置”“定位校验实现”等任务命名,使读者能返回所属上下文。
用一个系统建立跨视图联系
下面使用 doc-test 的静态文档站作为案例。事实基线来自 2026-10-04 的代码调研:提交 3c75cac9d5017a313862905d7e67744c462a4a69 加当时工作树,Next.js 16.3.8、Fumadocs Core 16.15.18、Fumadocs MDX 15.4.6、Mermaid 12.0.0。2026-10-05 整理时又读取静态导出、source 和搜索关键入口,确认下面所依赖的主要处理路径仍在。案例说明代码和配置,线上部署状态、浏览器体验与历史技术检查各有独立范围。4
系统目的很简单:作者保存正文,用户决定公开范围,读者阅读并搜索。MDX 是能够包含组件的 Markdown 正文形式;source 是过滤后内容的统一读取入口,页面及派生资源从这里取得内容。生产构建生成公开文件,浏览器取得文件并执行交互。
组成回答职责问题
本图范围为生产访问阶段,回答“由谁显示页面,由谁提供文件,搜索计算在哪里进行”。doc-client 和 static-site 是本案例的稳定身份。
外框表示软件责任范围,节点说明角色或职责,箭头表示使用或请求方向。浏览器运行 React 与 Fumadocs 客户端代码,资源服务提供生成的 HTML、脚本和索引。索引返回浏览器后,由客户端查询。这里将托管和文件存储合并为一个职责对象,省略 CDN 内部结构和正文显示组件。
源码里存在 Next.js、React 和搜索 route 等名称,还不足以决定线上运行边界。本案 next.config.ts 设置 output: 'export',搜索 route 使用 force-static 和 staticGET,因此生产访问的说明聚焦静态文件与浏览器;构建期处理放到交付说明中。
部署回答位置问题
下图把相同对象映射到生产目标环境。wrangler.jsonc 配置 out/ 为 Cloudflare Workers 静态资源目录,所以下图表示配置中的部署目标。确认实际线上版本还需要部署记录。
位置框表示设备或平台,实例接回组成图的软件身份,箭头表示网络请求。本案没有核查副本、地域、缓存策略或权限设施,因此没有用重复节点和基础设施图标暗示这些能力。C4 部署图也将软件实例、部署节点和适用环境作为明确对象。5
本地开发另有 Next 开发进程,它读取工作树并保留草稿。生产构建在本地或 CI 的 Node 环境执行,负责内容过滤与生成。配置中的生产访问由浏览器读取已部署文件。这些阶段分别说明,读者就能判断“开发中可见”“构建中被过滤”“线上版本未更新”来自哪些关系。
运行场景回答怎样得到结果
搜索场景选取成功加载页面、索引可达的条件,追踪首次查询到打开结果。下面按代码重建交互,输入调度和取消细节没有展开。
消息说明参与者交互,自调用表示浏览器本地处理,opt 表示有条件的加载,虚线表示返回。staticClient 按 from 缓存加载 Promise,索引复用限定在当前模块运行期。默认地址 /api/search 提供构建时导出的 JSON,搜索计算在客户端进行。索引下载失败时底层代码抛出错误;本案没有观察 UI 的错误展示,也不承诺自动重试。6
生产过滤在构造 source 前发生,草稿及草稿入口后代不进入公开内容集合,索引从同一 source 生成。因此“源码已有正文”和“公开搜索能找到正文”之间还隔着页面状态、祖先入口、构建和实际部署版本。相邻解释把图中的对象接回条件,读者无需从另一份成果补齐这条关系。
运行场景可以发现静态结构没有充分回答的问题:完成是收到请求、返回结果还是数据已持久化?重试会否重复执行?取消影响请求还是已保存状态?在队列、事务或权限机制中,这些区别会改变行动,需要沿状态与规则继续解释;具体方法见技术机制的讲解。arc42 运行视图同样关注代表性用例、外部接口、启停和异常,数量由架构相关性决定。7
交付过程回答版本怎样到达读者
正文和目录元数据先经 MDX 编译,随后在 source 构造前过滤草稿,由统一 source 派生页面、导航、搜索、标签和引用,静态导出到 out/。public/ 文件直接复制,资源的公开边界另行管理。
交付需要进一步说明产物、版本和失败处置。以下图源来自 2026-10-04 核对的部署工作流,表达当时配置逻辑;本页没有查询外部执行状态。设置或构建失败会停止后续交付,这两条前置失败省略在图外。8
节点表示动作或判断结果,箭头表示步骤依赖与条件分支。恢复步骤依赖可恢复的旧版本;首次部署可能没有这个条件。该工作流恢复软件版本,本案没有业务数据库迁移,因此数据恢复不在其证明范围内。
当时的记录脚本查询实际部署版本与流量比例,保存传入的动作结果,未断言恢复到期望版本,也未再次执行恢复后冒烟。工作流保持失败可见。PR CI 和预览由独立工作流触发,配置没有“CI 通过才开始预览”的依赖;理想交付顺序需要与真实工作流分别核对。
这些限定使“配置了恢复动作”“动作实际成功”“恢复后页面可用”具有可辨的依据。架构文档据此提供定位和判断入口,操作细节交给项目已有的交付与恢复说明。
把图文接到理由和实现
每张图写清它所表达的含义
图的标题和附近说明让读者识别对象范围、视角、环境或版本,以及当前实现、历史基线或目标状态。重要边写具体动作、方向和决定判断的条件,例如“通过 HTTPS 获取索引”“生成静态页面”“保存订单记录”。请求方向、数据返回和源码依赖可以分别表示,图例交代使用的箭头、分组和线型。C4 的 notation 指导提供了这些核对点;这里按当前表达任务选择记法。9
文字解释职责、条件、理由及后果,表格连接环境、实现和检查,图帮助定位关系。复杂图的重要信息需要有可获得的文字说明;颜色可以辅助,必要边界不能只靠颜色辨认。W3C 的复杂图指导支持提供完整信息的文字替代。具备这些内容仍需另行核查实际渲染和辅助技术效果。10
定位入口和有效路径
源码定位有用的程度,取决于读者能否从职责追到有效入口。本案用下面的表连接代表性工作,无需增加代码级图。
| 工作 | 实现位置及所支撑的关系 | 检查时还要关注 |
|---|---|---|
| 改公开条件 | apps/site/src/lib/content-filter.ts 的 filterPublishedFiles,由 source.ts 在 loader 前调用 | 页面与祖先条件、派生索引是否采用同一范围 |
| 改索引输出 | apps/site/src/app/api/search/route.ts 的 staticGET 与 force-static | 静态文件是否生成,下载端是否同步 |
| 改搜索接入 | search-dialog.tsx 的 SearchDialog,经 provider.tsx 注入 | 客户端配置、索引契约、实际错误与交互另验 |
| 改标签与引用 | content-index.ts 的 createContentIndex | 输入是否仍为过滤后页面,引用是否正确解析 |
| 改部署和恢复 | 部署、回滚、预览工作流及 wrangler.jsonc | 触发和依赖、旧版本条件、执行后如何确认 |
路径是追踪入口。文件移动后核对关键符号和调用,库升级后核对真实导入。本案安装的 orama-static 模块实际使用 zbsearch,说明模块历史名称与当前实现可能不同。部署配置给出目标,线上版本需要环境证据,Git 的 main 提交也不能单独证明线上状态。6
当前说明与决策记录各自回答什么
当前架构说明回答这个版本怎样工作,重要决策记录回答选择依赖哪些约束、考虑过什么替代、带来哪些代价。ADR 是保存一次架构重要决定的方式。Nygard 原文要求保留被替代决定的历史状态与新记录入口,使后来者能理解取舍的上下文。决策获接受、实现落地和效果达到需要分别核对。11
局部理由可以就近写清,长期影响结构、接口、依赖和质量的决定值得保存独立记录。例如选择静态搜索可能减少在线服务依赖,也意味着客户端要下载索引,索引规模和加载成本可能改变选择。这个例子是条件化取舍说明;本页没有把它写成 doc-test 的已记录设计意图。取得当时决策依据后,才能准确说明项目为何选择它。
随语义变化维护文档
维护先确定信息的主要位置:源码和配置维护实现,架构说明维护抽象职责和关系,场景维护状态与行为,操作说明维护交付和恢复,决策记录维护理由,既有测试与 CI 保存执行结果。图和文字可以重复名称及必要回顾;完整规则与环境清单集中维护,避免多处相互冲突。
变更影响按对象、关系、条件和结果追踪。源码目录只是定位线索。改网络或权限要查部署和信任边界;改消息格式要查生产者、消费者和异常;改重试要查状态、重复执行与完成条件;改构建和恢复要查产物、版本与操作入口。没有改变某张图所表达的含义时,该图可以保留。arc42 同步维护建议强调明确责任并控制易变细节,本文将其落实到已有变更流程中的语义核对。12
例子:索引地址改变,哪些说明受影响
构造一个目标变更:把索引地址从 /api/search 移到 /search-index.json,搜索仍在浏览器本地执行,公开范围仍由同一 source 决定。此变更用来说明影响分析;新路由和下载配置未实现。
先识别变化的是生成端与下载端之间的地址契约。客户端改 from,生成入口也必须产生目标文件。同步核对静态托管、索引检查和诊断路径。下面仅表现目标片段,前提是新文件已生成且 from 已同步。
参与者身份、查询位置、HTTPS 联系和公开条件没有变化,所以组成图与部署图可以保留。运行场景中的具体地址改变,生成和客户端下载的实现定位随之改变。排障从旧文件查找路径转到新文件。静态导出检查以及使用旧地址的草稿与冒烟检查也需要同步;只修改业务路径可能使部署检查失败并触发恢复。旧端点下的测试结果保留自己的基线,新路径另需执行证据。
构造方案没有新增长期重要理由,本例无需新增 ADR。如果实际变更涉及缓存、兼容或发布约束,再判断是否要记录独立取舍。维护后保留当前说明和必要历史,不默认长期累积每次变化的前后图。
什么时候考虑共享架构模型
少量图可以在文档内维护可编辑源,相邻图文在同一次修订中核对。多视图反复复用对象和关系时,共享模型能集中定义,再从模型选择视图。Structurizr DSL 和 LikeC4 提供此类能力,但模型仍是一份经过选择的描述,需要核对它与实现的对应。引入收益取决于真实复用与维护负担;工具能力比较保留在架构方法调研。
代码自动提取能帮助定位路径、依赖和部署资源,业务责任、实际启用、失败含义与理由仍要核查。保持可编辑源和必要重建条件,导出图片由源生成。工具迁移时检查身份、关系语义和导出损失,避免在源与产物各维护一套结构。
判断文档支持到了哪一步
沿读者任务回查:能否说明系统目的和责任;场景参与者能否接回结构;软件实例能否接回环境;代表性修改能否定位实现、影响和检查;失败条件及恢复前提是否足以支持行动;版本变化后是否能找到应修改的说明。某个问题仍缺决定性条件时,补内容或明确限制该判断。
技术检查确认 MDX、图源、链接或产物,代码核对确认实现路径,案头审读发现解释和跨视图冲突,运行观察确认具体环境中的行为,目标读者试读观察理解和任务完成。历史案头与技术试用的输入、版本和结果在架构方法调研保留;本页的图文没有由这些记录获得浏览器、辅助技术或真实读者效果保证。一般质量判断与修订方法见质量、修订与维护。
依据
Footnotes
-
Philippe Kruchten,1995,Architectural Blueprints—The “4+1” View Model of Software Architecture,PDF 第 1–2、4–7、10–13 页,关注点、对应及裁剪。本页借鉴概念,没有实施整套方法或声明标准符合性。 ↩
-
实现入口为
apps/site/next.config.ts、apps/site/src/lib/source.ts、apps/site/src/lib/content-filter.ts、apps/site/src/lib/content-index.ts、apps/site/source.config.ts与apps/site/wrangler.jsonc。2026-10-04 调研的完整版本与技术试用范围见架构方法调研。 ↩ -
C4,Deployment diagram,软件实例、部署节点、单一环境和基础设施。 ↩
-
apps/site/src/app/api/search/route.ts、apps/site/src/components/layout/search-dialog.tsx、apps/site/src/components/provider.tsx;Fumadocs Core 16.15.18 的dist/search/client/orama-static.js中loadDB、getDBCached、staticClient和zbsearch导入。本页说明静态输入、下载和缓存实现,未观察错误展示或浏览器网络。 ↩ ↩2 -
arc42,6. Runtime View,场景选择、参与对象、启停与异常及可用表达方式。 ↩
-
2026-10-04 只读核对
.github/workflows/ci.yml、preview.yml、deploy.yml、rollback.yml与apps/site/scripts/record-deployment.mjs所得基线。工作流配置、外部执行与恢复后观察分别判断;本页整理未执行外部交付操作。 ↩ -
C4,Notation,标题、图例、对象类型和职责、关系标签与方向;本页采用按问题选择的表达,不声称完全遵循其全部记法建议。 ↩
-
W3C WAI,Complex Images,复杂图主要信息的可获得文字描述。 ↩
-
Michael Nygard,2011,Documenting Architecture Decisions,重要决策、Context、Decision、Status 和 Consequences。 ↩
-
arc42,FAQ H-3,同步源码与文档、明确责任、控制不稳定局部细节。维护触发和上述案例分析是本文的应用判断,没有长期成本测量。 ↩
最后更新于