主题:附录 B. AgentClinic 领域地图
难度级别:中级
预计学习时间:6-8 小时(理论 + 实践)
先决条件: 基础 Web 开发知识(HTTP、路由、请求)
熟悉关系型数据库(SQL、表、关联)
理解 MVP(最小可行产品)概念
TypeScript/JavaScript 基础知识
理解测试原则(验证事实、断言)
学习目标: 独立设计学习项目的领域模型,确定实体、其属性和关联,类似于 AgentClinic
将项目的完整功能分解为 SDD 周期的各个阶段,解释添加路由的顺序并论证每个阶段的优先级
为每个阶段制定最小可验证事实,创建可自动化的验证清单
在所有规范中一致地应用领域词汇表,识别并修正术语不一致之处
区分属于学习领域的元素与需要单独规范的元素,并论证此决策
概述:AgentClinic 是一个学习项目讽刺作品,通过「程序代理诊所」示例演示 SDD 周期(规范驱动开发)。领域地图描述了该项目的结构:存在哪些实体(代理、疾病、疗法、预约、反馈),它们如何相互关联,哪些路由服务于用户场景,以及全部功能如何分布在开发阶段中。核心思想——领域有意保持简单,但足够丰富,以展示 SDD 的所有方面:从第一个「Hello Hono」到带有计数器检查的管理面板。同时,项目有意排除复杂的真实场景(支付、授权、外部集成),以便焦点始终保持在通过规范进行开发的过程本身。
核心概念: 领域地图:项目业务领域的可视化及文本描述,包括实体、其属性、关联和边界。在 AgentClinic 中,领域地图充当开发人员、测试人员和规范之间的通用语言。它不规定具体实现,但设定项目运作的框架。
实体:具有明确语义的关键业务领域对象。在 AgentClinic 中有五个主要实体:代理(程序助手)、疾病(代理的重复性问题)、疗法(帮助代理的方法)、预约(用户申请)、反馈(反馈)。每个实体都有一套属性和在规范中的使用规则。
SDD 周期(规范驱动开发):一种开发过程,其中规范(requirements.md、plan.md、validation.md)引导实现。项目不是一次性构建所有内容,而是分阶段发展,每个阶段都以清晰的可验证事实开始,并以确认这些事实结束。
可验证事实:关于系统行为的具体、客观可测量的陈述,可以自动化。例如:「GET / 返回 200」或「无效表单被拒绝」。事实取代了模糊的需求,如「应用程序应该快速运行」。
开发阶段:时间和范围有限、产生具体可交付成果的阶段。在 AgentClinic 中有六个阶段:Hello Hono → 代理和疾病 → 疗法 → 预约 → 反馈 → 管理面板。每个阶段添加新的路由和验证事实,但不破坏之前的内容。
最小路由集:足以展示领域的 URL 路径集合。并非所有路由都在第一阶段需要——这是 SDD 迭代性原则。路由使用技术英文名称(/agents、/ailments),而用户场景使用俄语描述并应用领域词汇表。
领域词汇表:所有规范中统一术语的约定。禁止对「代理」实体使用同义词,如「机器人/助手/模型」。技术名称(路由、表、文件)保持英文,用户场景使用俄语并采用统一术语。
学习领域边界:明确列出未经单独规范不属于项目的内容:真实医学术语、真实个人数据、支付场景、基于角色的授权、外部邮件发送、复杂图表、与真实服务的集成。此限制保持对 SDD 过程的聚焦。
练习: 标题:为新项目设计领域模型
问题:假设您需要创建一个学习项目「AgentLibrary」——程序代理的图书馆。确定至少 4 个实体、其属性和示例,类似于 AgentClinic 的实体表。然后描述需要哪些路由以及它们如何分布在 SDD 的各个阶段。
解答:步骤 1:确定实体。例如:图书(标题、作者、描述)、代理读者(名称、偏好类型)、反馈(评分、文本、日期)、书架(名称、公开/私有)。步骤 2:以表格格式设置属性并附示例。步骤 3:设计路由:/、/books、/books/:id、/agents、/reviews、/shelves。步骤 4:分解为阶段:(1) Hello Hono — GET / 返回 200;(2) 图书 — 列表和详情页;(3) 代理和反馈 — 图书的相关反馈;(4) 书架 — 创建和管理收藏。步骤 5:为每个阶段制定 2-3 个可验证事实。
难度:中级
标题:规范中的术语审计
问题:给定 AgentClinic 项目中三个不同文件的片段:(1) requirements.md:「机器人应显示其问题列表」;(2) plan.md:「创建 symptoms 表以存储助手的重复故障」;(3) validation.md:「GET /agents/:id 返回相关 ailments 列表」。找出所有违反领域词汇表的地方,解释为什么它们有问题,并正确重写这些片段。
解答:违规:「机器人」代替「代理」,「问题」代替「疾病」,「symptoms」代替「ailments」,「助手」代替「代理」。问题:同一实体的不同术语在团队中造成混乱,使文档搜索复杂化,导致代码(ailments 表)与规范(symptoms)之间的不一致。正确版本:(1)「代理应显示其疾病列表」;(2)「创建 ailments 表以存储代理的重复疾病」;(3) 无需更改——已正确。
难度:中级
标题:扩展领域:边界分析
问题:团队提议在 AgentClinic 中添加诊所评分系统(类似 Google 评论)以及优先预约的付费订阅。使用「不属于学习领域」部分的准则分析此提议。描述哪些组件违反边界,并提出保持教育价值的替代方案。
解答:边界违规:付费订阅——支付场景(明确禁止);区域聚合评分系统——复杂图表和潜在真实个人数据;优先预约——隐式基于角色的授权(普通 vs 高级用户)。替代方案:现有「反馈」实体中的简单满意度量表(1-5 星),不关联用户,无聚合,无支付。作为单独阶段添加:「扩展反馈」,包含事实「反馈包含 1-5 评分」,「平均评分显示在 /feedback 页面上」。
难度:高级
标题:数据库模式设计
问题:基于描述的 AgentClinic 实体和最小路由,设计考虑所有关联的完整 SQL 模式。解释为什么 agent_ailments 是关联表而不是 agents 中的字段。描述如果添加需求「一种疗法治疗特定代理的特定疾病」,模式将如何变化。
解答:基础模式:agents(id, name, description);ailments(id, title, description);therapies(id, title, description);agent_ailments(agent_id, ailment_id)——多对多关联:一个代理可以有多种疾病,一种疾病可以存在于多个代理。需要关联表,因为 agents 中的数组字段违反第一范式并使查询复杂化。appointments(id, name, message, ailment_id, created_at);feedback(id, name, message, created_at)。新需求下添加 agent_ailment_therapies(agent_ailment_id, therapy_id, effectiveness_rating),其中 agent_ailment_id 是 agent_ailments 表的复合键或单独 id。这将关联转变为三重关联:代理-疾病-疗法。
难度:中级
标题:为「预约」阶段制定可验证事实
问题:为 AgentClinic 的「预约」阶段制定至少 5 个可验证事实,涵盖:成功创建、必填字段验证、不存在疾病处理、显示已保存记录、时间戳。指出哪些事实可以用单元测试验证,哪些需要集成测试。
解答:事实:(1) 有效数据的 POST /appointments 返回 201 和重定向——集成测试;(2) 无 name 字段的 POST /appointments 返回 400 及错误信息——单元测试(表单验证)+ 集成测试;(3) ailment_id=999 的 POST /appointments 返回 400 或 404——集成测试(需要数据库);(4) 成功 POST 后的 GET /appointments 包含创建的记录——集成测试;(5) 记录的 created_at 在测试时间的最近一分钟内——集成测试。单元测试可用于 (2) 的数据验证级别,无需数据库。其余需要完整技术栈。
难度:中级
案例研究: 标题:EdTech 初创公司将单体原型迁移到 SDD 阶段
场景:初创公司在 3 个月内「仓促」开发了教育平台原型:课程、课时、家庭作业、聊天、支付、分析——全部在一个仓库中,没有测试。招聘新开发人员后发现,没人知道哪些功能正常工作,哪些是「演示用的占位符」。投资者要求提供功能正常的证明。
挑战:8 人团队因代码持续冲突无法并行工作。无法向投资者展示具体进展:「几乎完成了」已经说了半年。支付系统破坏聊天功能,分析显示随机数字。需要转向透明、可验证的开发,而无需从头重写一切。
解决方案:技术负责人采用 AgentClinic 方法:确定领域实体(课程、课时、学生、作业、尝试、反馈)并固定领域词汇表。将单体分解为类似 SDD 周期的阶段:(1)「Hello Framework」——基础响应;(2)「课程和课时」——内容浏览;(3)「作业」——创建和检查;(4)「尝试」——保存学生答案;(5)「反馈」——反馈。将支付和分析移至单独规范,状态为「MVP 学习领域之外」。为每个阶段编写包含可验证事实的 requirements.md、plan.md、validation.md。
结果:6 周内团队稳定了平台核心(阶段 1-4)。向投资者展示了具体清单:47 个可验证事实,其中 43 个自动通过。新开发人员凭借领域词汇表 2 天即可上手,而非之前的 2 周。支付系统后来作为单独阶段添加,有自己的规范,不破坏现有功能。团队将关键错误数量从每周 15 个减少到 2 个。
经验教训: 领域地图和统一词汇表消除了「民间知识」——仅存在于个别开发人员头脑中的信息
可验证事实将投资者对话从「几乎完成了」转变为准备就绪的具体指标
明确的领域边界保护团队免受过早复杂性影响,并允许聚焦价值
相关概念: 领域地图
SDD 周期
可验证事实
学习领域边界
领域词汇表
标题:企业项目因违反领域词汇表导致集成失败
场景:大型银行开发内部信贷申请管理系统。项目分配给三个团队:前端(移动应用)、后端(API)、分析(报告)。每个团队在没有统一领域词汇表的情况下使用自己的文档。
挑战:在移动应用中,「客户」指提交申请的物理个人。在 API 中,「客户」是法律实体合作伙伴的内部标识符。在分析中,「客户」表示 CRM 中的任何对象。集成时数据混淆:物理个人的申请归属于法律实体,报告显示不可能的数字。修复需要 3 周时间审计 200+ 端点和 15 个配置文件。
解决方案:事件发生后,引入了类似 AgentClinic 领域词汇表的方法:在公共仓库中固定带有定义的术语。「申请人」——提交信贷申请的物理个人。「合作伙伴」——与银行有合同的法律实体。「申请」——系统中的统一文件。API 中的技术字段名称保持英文(applicant、partner、application),用户场景翻译为俄语并采用统一术语。引入自动文档检查器,验证是否符合词汇表。
结果:新分析师的入职时间从 3 周缩短到 4 天。与语义相关的集成错误数量下降 80%。扩展到抵押贷款申请时,添加了「不动产对象」术语,与现有实体无冲突。该项目成为银行其他部门的范例。
经验教训: 违反领域词汇表不是「风格问题」,而是昂贵集成错误的来源
分离技术名称(英文,用于代码)和用户术语(俄语,用于规范)解决了多语言团队的问题
词汇表检查的自动化(检查器、CI 流水线)比手动说明更重要
相关概念: 领域词汇表
实体
学习领域边界
学习建议: 创建物理或数字「墙图」:将 AgentClinic 实体打印在卡片上并用线连接关联。视觉空间布局比表格阅读更有助于记忆结构
练习「反向翻译」:从代码中获取技术术语(agent_ailments 表、/appointments 路由)并用领域词汇表将其用户语义表述为俄语。这训练在技术上下文和用户上下文之间切换
为 SDD 的每个阶段自己想一个「容易忘记的事实」。例如,对于「预约」阶段——message 字段中的 XSS 检查。与材料中建议的对比——这培养对规范完整性的批判性思维
使用「教学法」:向同事甚至想象中的听众解释 AgentClinic 领域地图。尝试用简单语言解释为什么 agent_ailments 是关联表而不是字段,能快速发现理解中的空白
对当前项目进行「边界审计」:哪些功能「不属于领域」而没有单独规范?此练习将 AgentClinic 概念转移到实际实践中
使用 Given-When-Then 格式或简单事实列表,为其中一个阶段创建 validation.md 文档模板。尝试编写实现其中一个事实的测试——即使是 mentally 也能加强规范与代码之间的联系
额外资源: 原始文档「附录 b. agentclinic 领域地图」:构建本指南的课程原始材料
埃里克·埃文斯的《领域驱动设计》著作:关于领域驱动设计的基础工作——领域地图、限界上下文、统一语言
沃恩·弗农的《实现领域驱动设计》著作:通过代码示例和模式实际实施 DDD 的实用指南
戈伊科·阿季奇的《实例化需求》文章:通过可验证示例制定需求的方法论,与 SDD 周期相关
「事件风暴」工具:通过事件进行团队领域建模的技术——对团队中扩展领域地图有用
SQLite 文档 (sqlite.org/lang.html):用于独立设计类似 AgentClinic 提议的模式的 SQL 官方文档
Hono 框架 (hono.dev):「Hello Hono」阶段使用的轻量级 Web 框架文档——用于路由的实际实现
西蒙·布朗的《软件架构 C4 模型》文章:包括上下文和容器图表的软件架构可视化方法——对扩展领域地图有用
总结:AgentClinic 领域地图不仅仅是玩笑式的隐喻,而是精心设计的掌握 SDD 周期的学习工具。其关键原则:讽刺性但语义精确的域;五个明确定义的实体及其属性和示例;通过六个阶段迭代增加功能并附带可验证事实;统一领域词汇表,分离技术英文名称和用户俄文术语;明确边界,防止过早复杂性。掌握此地图后,开发人员学会设计足够丰富以展示真实模式的业务领域,但又足够简单以进行受控学习。核心技能——将模糊的愿望(「为代理制作诊所」)转化为可自动验证的具体实体、路由、表和事实。