关于 requirements-scoping
requirements-scoping 是将模糊需求整理为功能、非功能和范围外清单的系统设计技能,帮助设计者在选择架构前明确用户、核心功能、规模和服务目标。
主要功能
- 01清晰重述问题
- 02整理功能需求
- 03量化质量与规模约束
- 04明确范围外事项
- 05记录可修订的假设
适用场景
- 01界定模糊的系统设计题目
- 02确定产品核心能力的优先级
- 03记录延迟与可用性目标
- 04约束变化后重新梳理范围
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ proyecto26/ system-design-skills --skill requirements-scoping安装后在 Claude Code 中输入/requirements-scoping确认已加载。
附带文件references/clarifying-question-catalog.md
详细介绍
需求范围界定
将一个模糊的提示词(“设计一个新闻 Feed”)转化为三个书面清单:系统要做什么(功能需求)、会影响系统设计的数字与质量指标(非功能性约束),以及明确不包括什么(范围外事项)。跳过这一步,是设计出错最常见的原因:最终解决的不是眼前的问题,之后的每个决策也都建立在未经验证的假设之上。这套方法并不是为了放慢进度,而是要让问题具体到足以衡量设计选择。没有这一步,每个组件都只能靠猜,而第一个棘手的追问就会让整个方案土崩瓦解。
何时使用
在任何设计的第 1 步使用,在画第一个方框或命名第一个工具之前。只要需求宽泛(“设计 YouTube”)、含糊(“一个实时系统”),或没有说明规模、一致性或受众,就该使用这套方法。设计过程中一旦出现可能推翻先前假设的新约束,也应再次使用——重新界定范围远比重建系统代价低。最明显的信号是:还没能用一句话说清设计在此处要解决什么问题,就本能地想套用熟悉的架构。这种本能正是陷阱:把记忆中的方案套到一个根本没人认真读过的提示词上。
何时不使用
不要无休止地盘问。目标是获得足够清晰的信息来选择第一个假设,而不是写出完整规格——通常只需提出三到五个关键问题,其余事项写明假设即可。不要过度完善范围:每项纳入的功能都需要设计并给出合理依据,因此应将锦上添花的功能列为范围外(YAGNI)。也不要一遇到质疑就重新界定范围;要区分真正的约束变化和澄清性建议。
先澄清
以下问题最能影响设计,按大致优先级排列:
- 谁会使用,以及如何使用? 受众(消费者/内部/B2B)、客户端(移动端、Web 端或两者)以及一两个核心用户旅程。这些决定了其他所有事项的边界。
- 哪些功能是必需的? 强制列出按优先级排序的候选清单;核心功能正常运作之前,长尾需求都属于范围外。
- 规模如何? DAU/MAU、增长周期(3/6/12 个月)、读写比、对象大小。这些数据是
back-of-the-envelope用来换算 QPS 和存储量的输入——在这里记录,在那里量化。 - 延迟和可用性目标是什么? 明确 p99 指标和几个 9 的可用性目标,并结合用户旅程来确定(读取 Feed 和支付的要求不同)。
- 数据需要多新?数据丢失的后果有多严重? 强一致性与最终一致性、持久性预期会驱动后续最艰难的权衡;在这里记录需求(读取能否接受过时数据?最近写入的数据能否丢失?),一致性模型的理论留给
consistency-coordination。
如果用户无法回答,就明确说出假设并继续(“假设有 10M DAU、读操作为主,最终一致性可以接受”)——写下的假设可以修订,未说明的假设则是隐患。用对方的原话记录每个回答(“最多有 5,000 个好友”“必须能承受一个区域故障”):现在看似无关紧要的细节,之后往往会成为迫使你做出结构性选择的约束。
方法(流程)
从提示词到明确问题的可重复步骤:
- 用一句话重述提示词。“一个服务,用户可以发布简短消息,并按时间倒序查看所关注用户的动态。”这能立即揭示隐藏假设,并尽早获得认同。
- 将功能需求列为用户可见的能力,并以动词开头: 发布消息、关注用户、查看动态、搜索。 这些回答了“系统做什么”——每一项都是参与者可以执行的操作。确保需求可测试,且不涉及实现方式(“存入数据库”不是需求;“查看动态”才是)。
- **排序并精简到核心。**选出定义产品的两三个需求。明确将其余需求推迟——推迟是一项决策,不是遗漏。核心决定设计成败;其他一切都可以后续再做。
- **根据澄清后的答案推导非功能约束。**功能需求说明系统做什么,非功能需求则说明系统必须做得多好:规模(DAU、QPS 输入)、延迟(p99)、可用性(几个 9)、一致性、持久性,以及任何成本或合规限制。这些数字是衡量设计的依据,也是迫使你在任何功能出现之前就做出结构性选择(分片、缓存、队列)的因素。
- **明确列出范围之外的内容。**说明不会构建哪些内容(分析、广告、审核、多区域),让设计保持聚焦,并清楚地界定边界,而不是让边界偶然形成。
- 重述三份清单并确认,然后再开始设计。这是评判后续工作的约定;应将其视为可在约束变化时重新审视的假设,而不是固定规格。
输出应是三份简短清单,而非散文。接下来将非功能指标交给 back-of-the-envelope。
陷阱/容易误导之处
糟糕的范围界定比跳过范围界定更糟,因为它会制造虚假的信心。请留意:
- 形似解决方案的需求。“我们需要 Kafka/缓存/分片”是伪装成需求的答案。应将其还原为实际需要(“应对写入突发”“快速提供读取”),之后再让设计证明需要使用这些工具。
- 未量化的非功能需求。“高规模”“低延迟”“高可用”都无法用于决策。没有数字的需求只是愿望——在它影响选择之前,先通过
back-of-the-envelope将其量化。 - **伪装成面面俱到的范围蔓延。**接受每项功能看似尽职尽责,却会稀释设计、耗费时间。满足目标所需的最小范围才是最佳选择。
- **虚假的范围外项目。**为了逃避难题而排除内容(因为一致性很难就将其删去)会掩盖真正的问题。删减是为了聚焦,而不是为了避开提示词实际考查的难点。
- **将答案视为最终结论。**需求只是一种假设。约束变化时(“现在 p99 < 50ms”“现在我们失去一个区域”),应说明哪些假设因此失效,并重新界定受影响部分的范围,而不是打补丁应付。
- **先问影响小的问题。**先问按钮的颜色,而不是读写比例。应优先提出会影响架构的问题;即使琐碎问题都答得井井有条,系统的真实形态仍可能不明。
- **只顾长篇阐述范围,而不予确认。**范围界定是一场对话。重述三份清单和各项假设,然后暂停以便对方纠正——如果把澄清意见视为对范围的攻击,设计最终就会为错误的问题辩护。
应做与不应做
- 应做 用一句话重述提示词,并优先提出影响最大的 问题(受众、核心功能、规模、延迟/可用性、新鲜度)。
- 应做 写出三份清单——功能性、非功能性、范围外—— 并将每个未解答的问题视为明确且可修订的假设。
- 应做 量化每项非功能性要求(“p99 < 200ms”、“10M DAU”),然后将
原始数字交给
back-of-the-envelope进行计算。 - 应做 在真正的约束发生变化时重新界定范围,并指出哪些假设因此 不再成立。
- 不应做 把解决方案伪装成需求(“我们需要 Kafka”);应陈述需求,让设计来证明工具是否合适。
- 不应做 接受每项功能;将次要需求放到范围外,也不要为了回避难题而 排除它们。
- 不应做 无休止地盘问,也不要长篇大论地阐述范围——只需获得形成初步假设所需的 足够 信息,然后确认并继续。
重要数字
需求范围界定负责收集输入,不负责计算。确定原始
数量——DAU/MAU、每位用户每天的操作次数、读写比、对象/负载大小、保留期限、峰值系数、p99 延迟目标和可用性几个 9 的
目标——然后交给 back-of-the-envelope,由它负责延迟/QPS/
存储表格和换算计算。以下两个数字会影响下游的多数决策,因此应逐字记录:读写比(读操作占 95%
的系统适合缓存;写入突发的系统适合队列)和规模
时间范围(为 1k QPS 设计的系统与为 1M QPS 设计的系统截然不同)。每个数字旁都要写明单位和假设。
图表
范围界定的输出是三份清单,而不是图表——应将它们保留为文本,以便始终作为可编辑的契约,供所有内容追溯。确定范围后的需求足以支撑初步的高层设计时,再使用插件内的 architecture-diagram
技能绘制该设计;需求本身不需要图表。
相关构建模块
back-of-the-envelope— 为它提供输入:此处收集的非功能性数字(DAU、比率、SLA)将用于计算它的 QPS、存储和服务器数量。下一步。scaling-evolution— 为它提供输入:此处界定的增长时间范围决定了需要规划的下一个瓶颈,而设计中途重新界定范围则会为它提供新的限制。api-design和data-storage— 为它们提供输入:此处列出的功能需求和访问模式将在那里转化为具体的契约和架构。consistency-coordination— 所属概念在此处:在此处记录新鲜度和持久性要求;一致性模型理论属于该模块。system-design— 由编排器在第 1 步调用,此时尚未进行估算和高层设计。
参考资料
references/clarifying-question-catalog.md— 按类别分组的完整问题集(功能、规模、延迟/可用性、一致性/持久性、约束)、从模糊到具体的示例,以及可填写的需求模板。在界定实际提示词的范围时,或上述五个问题不足以应对不熟悉的领域时阅读。