第八章 需求 (Before the Project)
一、导读
8.1 本章学习目标
理解需求的本质:不是"用户想要什么",而是"用户需要解决什么问题"
掌握需求挖掘(Elicitation)的技巧:如何从用户那里获取真正的需求
学会区分功能性需求(Functional Requirements)和非功能性需求(Non-Functional Requirements)
理解用户故事(User Story)的编写方法和验收标准(Acceptance Criteria)
掌握需求优先级排序(Prioritization)的方法:MoSCoW、Kano 模型等
学习需求文档(PRD)的编写原则:什么该写、什么不该写
理解需求变更的必然性及其管理策略
掌握原型(Prototype)在需求验证中的作用和局限性
8.2 为什么本章如此重要
需求是软件项目的起点,也是项目失败的最常见原因。据统计,软件项目中超过60%的缺陷可以追溯到需求阶段的问题——不是代码写错了,而是从一开始就理解错了要做什么。一个需求错误,无论后续的架构、编码、测试做得多好,最终交付的都是错误的产品。
需求的困难在于它的"隐性"。用户往往无法清晰地表达自己真正需要什么——他们知道自己"不舒服",但无法准确描述"病因"。更复杂的是,用户说出来的"想要"(want)和他们真正的"需要"(need)之间往往存在差距。一个声称"我需要一个报表功能"的用户,真正需要的可能是"我需要在每天早会上快速了解关键指标的状态"——而解决方案可能不是报表,而是一个实时仪表盘。
需求还是变化的。市场在变、用户在变、竞争对手在变、技术在变。试图在项目开始时"锁定"所有需求是不现实的。务实的做法是:接受需求的可变性,建立灵活的流程来管理变更,通过快速迭代来逐步明确需求。
8.3 核心问题引导
"用户想要的"和"用户需要的"有什么区别?如何发现真正的需要?
需求挖掘中最常见的陷阱是什么?如何避免?
功能性需求和非功能性需求为什么需要分别对待?
用户故事的"三个C"(Card, Conversation, Confirmation)分别代表什么?
如何对需求进行优先级排序?当所有需求都被标记为"最高优先级"时怎么办?
需求文档应该详细到什么程度?过度详细和不够详细各有什么风险?
需求变更是"好"还是"坏"?如何管理变更而不让项目失控?
原型在需求验证中的价值是什么?它有什么局限性?
二、核心概念详解
概念一:需求挖掘(Requirements Elicitation)
需求挖掘不是"记录用户说的话",而是"发现用户真正的问题"。用户通常以解决方案的形式表达需求:"我需要一个按钮"、"我想要一个报表"。但这些是"方案",不是"需求"。需求挖掘的目标是穿透方案,找到背后的问题。
有效的挖掘技巧包括:问"为什么"(Five Whys)——连续追问五个"为什么"来穿透表面需求。用户说"我需要一个导出按钮",问为什么——"因为我要把数据放到 Excel 中做分析"——真正的需求可能是"我需要对数据进行自定义分析",解决方案可能是在线分析工具而非导出。
观察而非询问——有时用户自己都无法描述他们的工作流程。通过观察用户的实际操作,你可以发现用户自己都没意识到的痛点和需求。这比直接问"你需要什么功能"有效得多。
提供原型而非讨论规格——人们对抽象的讨论往往低效,但对具体的原型可以给出有价值的反馈。一个可交互的原型比100页需求文档更能帮助澄清需求。
概念二:用户故事(User Stories)
用户故事是一种轻量级的需求描述方式,格式为:"作为[角色],我想要[功能],以便[价值/目的]"。例如:"作为仓库管理员,我想要扫描商品条码快速入库,以便减少手动输入的错误和时间"。
用户故事的核心不是文档,而是"对话的占位符"(Card)。故事卡片本身只包含足够的信息来记住要讨论什么,真正的细节在对话中产生。这就是用户故事的"三个C":Card(卡片——简短的需求描述)、Conversation(对话——开发者与用户之间的详细讨论)、Confirmation(确认——验收标准,定义什么时候故事算"完成")。
验收标准(Acceptance Criteria)是用户故事中最容易被忽视但最重要的部分。它将模糊的需求转化为可验证的条件:" GIVEN 用户在登录页面,WHEN 输入正确的用户名和密码并点击登录,THEN 跳转到首页并显示欢迎信息"。验收标准不仅是测试的依据,也是需求是否被正确理解的验证。
概念三:非功能性需求(Non-Functional Requirements)
功能性需求描述系统"做什么"(What the system does);非功能性需求描述系统"做得怎么样"(How well it does it)。性能、安全性、可用性、可维护性、可扩展性——这些都是非功能性需求。
非功能性需求经常被忽视,因为它们不如功能性需求那么"可见"。用户会说"我需要一个搜索功能"(功能性),但很少主动说"搜索结果需要在500毫秒内返回"(非功能性)。然而,如果搜索需要30秒才能返回结果,用户会认为这个功能"不好用"——即使功能上它是"正确的"。
非功能性需求应该在项目早期就明确定义,因为它们对架构设计有决定性的影响。一个需要支持百万并发的系统,与一个只需要支持100并发的系统,架构选择完全不同。如果等到开发后期才考虑非功能性需求,往往需要大规模的架构重构。
概念四:需求优先级管理(Prioritization)
资源永远是有限的——时间、人力、预算都有上限。不可能所有需求都实现,因此需要优先级排序。优先级排序的核心挑战不是"技术",而是"政治"——每个利益相关者都认为自己的需求最重要。
MoSCoW 方法将需求分为四类:Must Have(必须有——没有它系统就没有价值)、Should Have(应该有——很重要但可以暂时绕过)、Could Have(可以有——锦上添花)、Won't Have(这次不做——明确排除,避免范围蔓延)。
Kano 模型从用户满意度的角度分类需求:基本型需求(Must-be)——没有会不满意,有了觉得理所当然(如系统不能崩溃);期望型需求(One-dimensional)——做得越好越满意(如加载速度);兴奋型需求(Attractive)——没有不会不满意,有了会非常惊喜(如智能推荐)。
优先级排序的关键原则是:先做高价值、高风险的需求。高价值确保投入有回报,高风险确保不确定性尽早暴露。不要按照"容易实现"来排序——那会导致"先摘低处的果子"的陷阱,把真正重要但困难的需求拖到最后。
概念五:需求变更管理(Managing Change)
需求变更是不可避免的——不是"会不会变"的问题,而是"变多少"和"多快变"的问题。试图在项目开始时"锁定"需求是不现实的,也是不明智的——因为你可能会锁定错误的需求。
但"接受变更"不等于"无限制地接受变更"。每次变更都有成本——重新设计、重新编码、重新测试。如果变更不受控制,项目会陷入"永远做不完"的困境。
管理变更的策略包括:建立变更控制流程——每次变更都需要评估影响(时间、成本、风险),由相关负责人审批;使用迭代开发——短迭代(1-2周)意味着变更只影响当前迭代,不会打乱长期计划;维护需求追踪矩阵——记录每个需求的来源、状态和关联,确保变更的影响可评估。
三、深入分析与讨论
讨论一:需求沟通中的认知偏差
需求沟通中的很多问题源于认知偏差。确认偏差(Confirmation Bias)——产品经理在描述需求时,倾向于关注支持自己假设的信息,忽视矛盾的信息。锚定效应(Anchoring Effect)——第一个被提出的方案会成为"锚",后续的讨论都围绕这个锚展开,即使存在更好的方案。
知识的诅咒(Curse of Knowledge)——当一个人深入了解某个领域后,很难想象"不了解这个领域的人是怎么想的"。这导致需求描述中充满了领域术语和隐含假设,开发者按照字面意思实现,结果与用户的真实期望不符。
对抗认知偏差的方法包括:使用原型和可视化——具体的、可交互的制品比抽象的文字描述更难产生歧义;引入"魔鬼代言人"——指定一个人专门挑战假设和提出反面观点;进行需求评审——让不同角色(开发、测试、用户)从不同角度审视需求,发现盲点。
讨论二:敏捷与需求的关系
敏捷方法论对需求管理带来了根本性的改变。传统的瀑布模型试图在项目开始时定义所有需求,然后按顺序设计、编码、测试、交付。敏捷承认了需求的不可预测性,采用渐进式的需求定义——只详细定义当前迭代的需求,未来的需求保持粗略。
产品待办列表(Product Backlog)是敏捷需求管理的核心工具。它是一个持续维护的、按优先级排序的需求列表。列表顶部的需求详细且明确(即将实现),底部的需求粗略且模糊(未来可能实现)。每个迭代开始前,从列表顶部选取需求进行详细定义和估算。
敏捷的需求管理还强调"可工作的软件是进度的主要度量"。不是需求文档的页数,不是功能点的数量,而是真正交付给用户的、可工作的功能——这才是衡量需求是否被满足的标准。
讨论三:需求验证的多种手段
需求验证是确保"我们理解了正确需求"的关键步骤。验证手段包括:需求评审(由开发、测试、用户等多方参与,检查需求的完整性、一致性、可行性);原型测试(让用户与原型交互,观察他们是否能完成预期任务);用户故事映射(User Story Mapping,将用户故事按照用户旅程组织,发现遗漏的场景)。
A/B 测试是需求验证的"终极武器"——当不确定两个方案哪个更好时,同时实现两个版本,让真实用户的选择来决定。虽然成本较高,但对于关键决策,A/B 测试提供的数据比任何讨论都可靠。
需求验证应该尽早进行——在代码编写之前。一个在原型阶段发现的问题,修复成本是几分钟的讨论;一个在测试阶段发现的问题,修复成本是几天的返工;一个在上线后发现的问题,修复成本可能是数周的重构和用户沟通。
四、实践案例
案例一:Five Whys 揭示真正需求
某企业的内部系统用户提出需求:"我们需要一个审批流程功能,所有采购请求都需要经过三级审批。"开发团队开始设计复杂的审批流程引擎。
在需求挖掘会议中,团队使用 Five Whys 方法追问:为什么需要三级审批?——"因为财务部门需要控制成本"。为什么财务部门需要控制成本?——"因为过去出现过部门超支的情况"。为什么会出现超支?——"因为各部门没有预算意识"。为什么没有预算意识?——"因为他们看不到自己的实时预算使用情况"。
真正的需求浮出水面:不是"三级审批流程",而是"各部门需要实时看到自己的预算使用情况"。解决方案从复杂的审批引擎变成了简单的预算仪表盘——开发周期从三个月缩短到两周,而且更好地解决了根本问题。
案例二:原型测试发现需求误解
某医疗系统项目,需求文档描述:"医生可以在患者列表中选择患者,查看详细信息。"开发团队按照字面意思实现了一个列表页面,点击患者跳转到详情页面。
在原型测试中,发现医生的实际工作流是:他们需要同时对比多个患者的信息(如比较同一病症的不同治疗方案的效果)。"列表→详情"的跳转模式完全不符合医生的工作方式——他们需要的是可以在一个屏幕上并排查看多个患者的信息。
这个发现导致了对需求的重大修正:从"查看单个患者详情"变为"多患者信息对比视图"。如果这个误解在开发后期才被发现,返工成本会非常高。原型测试在早期暴露了需求理解中的关键偏差。
五、常见误区与注意事项
误区一:把解决方案当作需求
"我需要一个 XX 功能"是解决方案,不是需求。需求是背后的问题和目标。当你听到解决方案时,追问"为什么需要这个?""它解决什么问题?""还有其他方式解决这个问题吗?"来找到真正的需求。
误区二:忽视非功能性需求
"功能做完了再考虑性能"是最常见的错误之一。非功能性需求对架构有决定性影响,事后考虑往往需要大规模重构。在项目早期就明确非功能性需求的目标值(如响应时间 < 500ms,可用性 > 99.9%)。
误区三:试图在项目开始时定义所有需求
需求是渐进明确的。试图在第一天就定义所有细节,不仅浪费时间(很多细节会在开发过程中自然明确),还可能导致"锁定错误的需求"。采用渐进式的需求定义:近期的详细,远期的粗略。
误区四:需求文档过度详细或过度简略
过度详细的文档(每个按钮的位置、颜色都规定)限制了开发团队的创造力和判断力;过度简略的文档(只有一句话)导致理解偏差和返工。好的需求文档描述"什么"和"为什么",把"怎么做"留给开发团队。
误区五:害怕需求变更
需求变更不是"敌人",它是学习和适应的自然结果。关键不是阻止变更,而是管理变更——评估影响、控制范围、确保每次变更都带来足够的价值来证明其成本。
六、本章小结
本章探讨了软件项目开始前的需求工程。需求挖掘的核心是穿透"用户想要的"找到"用户需要的"——Five Whys、观察、原型都是有效的挖掘工具。用户故事以"Card-Conversation-Confirmation"的模式提供了一种轻量级但有效的需求描述方式。
非功能性需求(性能、安全性、可用性等)对架构有决定性影响,必须在项目早期明确。需求优先级排序(MoSCoW、Kano)帮助团队在有限资源下做出明智的选择。需求变更是不可避免的,关键是建立管理变更的流程而非试图阻止变更。
最终,需求工作的目标不是产出一份完美的文档,而是确保团队对"要做什么"和"为什么做"有共同的理解。这种理解是通过持续的对话、验证和反馈来建立和维持的——它不是一次性的活动,而是贯穿整个项目的过程。
七、思考题与练习
选择一个你项目中的功能需求,使用 Five Whys 方法追问背后的真正需求。记录你的发现。
为一个假设的产品编写5个用户故事,每个故事包含完整的验收标准(Given-When-Then 格式)。
列出你项目的功能性需求和非功能性需求。分析非功能性需求是否在项目早期就被充分考虑。
使用 MoSCoW 方法对你当前的需求列表进行优先级排序。分析排序结果是否合理。
为一个需求创建低保真原型(纸质原型或数字原型),让一位同事使用原型完成任务,观察并记录发现的问题。
回顾你项目中一次需求变更的经历:变更的原因是什么?影响有多大?当时的管理流程是否有效?
比较瀑布模型和敏捷模型在需求管理上的差异。分析在什么场景下哪种模型更合适。
编写一份一页纸的需求摘要(不是详细文档),描述一个你熟悉的项目的核心需求。练习用最少的文字传达最关键的信息。