1. 三份文档到底在解决什么问题先把话说透需求分析说明书、概要设计说明书、详细设计说明书这三份东西不是写给领导看的门面材料也不是走流程的摆设。它们是一条软件项目从“有人想要”到“有人能做”再到“有人能改”的完整证据链。我见过太多项目需求阶段靠聊天记录设计阶段靠口头传达最后代码写完没人说得清某个字段为什么是32位而不是64位。出了问题翻遍所有文档找不到依据只能靠猜。这三份文档各自承担不同职责。需求分析说明书回答的是“做什么”——用户要什么、系统边界在哪、哪些不做、验收标准是什么。概要设计说明书回答的是“怎么做分几块做”——模块怎么拆、接口怎么定、数据怎么流、技术选型是什么。详细设计说明书回答的是“每一块具体怎么实现”——类怎么设计、算法怎么写、数据库表每个字段什么含义、异常怎么处理。适合谁参考如果你是刚入行的开发、测试或者项目助理这三份文档的样例能帮你快速理解一个正规项目该有的文档骨架。如果你是有几年经验的工程师但一直在大厂拧螺丝、只负责一小块这些样例能帮你补齐从需求到设计的全局视角。如果你是技术负责人这些样例可以直接改吧改吧当模板用省去从零搭框架的时间。我个人的习惯是需求文档写“用户故事验收条件”概要设计写“模块划分接口契约”详细设计写“类图时序表结构异常分支”。三份文档的详细程度是递进的但核心原则一致——每一条描述都要能被验证。需求说“系统要快”这是废话说“首页加载时间在4G网络下不超过2秒”这才是可验证的需求。设计说“用缓存优化性能”这是空话说“热点数据走Redis过期时间300秒降级策略是查主库”这才是可落地的设计。下面我按三份文档分别拆解每份都给出结构框架、关键内容样例、实操中的坑以及我自己的经验参数。你不需要照搬但可以对照检查自己项目缺了什么。2. 需求分析说明书把“想要”翻译成“可验收”2.1 需求文档的核心结构长什么样一份能用的需求分析说明书我通常按这个骨架来组织文档修订记录谁在什么时候改了什么为什么改。别小看这个三个月后有人问“这个需求怎么变了”翻记录比翻聊天记录靠谱。项目背景与目标一段话说清为什么要做这个系统不做会怎样。目标要可量化比如“将订单处理时间从平均15分钟降到3分钟以内”。干系人列表谁提需求、谁用系统、谁维护、谁审批。每个角色标注关注点和影响力。功能需求按模块分组每条需求有唯一编号、描述、优先级、验收条件。非功能需求性能、安全、可用性、兼容性、可维护性。这部分最容易被忽略但出事往往出在这里。约束与假设技术栈限制、预算限制、时间限制、依赖的外部系统。数据需求核心数据实体、数据量预估、数据保留策略。验收标准整体验收的通过条件最好能对应到每条功能需求。我见过最离谱的需求文档是一份Word里塞了200条“系统应支持XX”没有优先级、没有验收条件、没有干系人确认。开发看完直接问“这200条哪些是这次要做的”所以结构不是形式是帮你把模糊变清晰。2.2 功能需求怎么写才不会被开发追着问功能需求最常见的写法是用户故事格式作为[角色]我希望[做什么]以便[达到什么目的]。但光有用户故事不够必须配上验收条件。我习惯用Given-When-Then格式需求编号REQ-ORDER-012 用户故事作为仓库管理员我希望批量导出待发货订单以便安排拣货路线。 验收条件Given 当前有至少1条待发货订单When 点击“批量导出”并选择“按库位排序”Then 生成CSV文件包含订单号、商品编码、库位号、数量四列。Given 当前无待发货订单When 点击“批量导出”Then 提示“暂无待发货订单”不生成文件。Given 导出过程中网络中断When 重新连接Then 已导出的部分不重复、不丢失。这样写开发知道要做什么测试知道要测什么产品知道验收什么。优先级我一般用MoSCoW法Must have、Should have、Could have、Wont have。Must have是上线必须有的Should have是尽量有但可以延期的Could have是锦上添花的Wont have是明确这次不做的。明确说不做什么和说做什么一样重要。2.3 非功能需求最容易被忽略的隐形杀手非功能需求写不好上线后就是灾难。我列几个必须写的维度维度样例指标验证方式性能核心接口P95响应时间≤500ms并发用户≥200压测报告可用性月度可用性≥99.5%故障恢复时间≤30分钟监控统计安全密码加密存储敏感字段脱敏展示操作日志保留180天安全扫描代码审查兼容性支持Chrome/Firefox/Edge最近两个大版本移动端适配iOS 15和Android 12兼容性测试可维护性核心模块单元测试覆盖率≥70%接口文档自动生成CI报告这些指标不是拍脑袋写的。比如P95≤500ms你得先知道当前类似系统的基线是多少用户能忍受多久。我一般会参考内部管理系统P95可以放到1秒面向消费者的页面P95最好在300ms以内。并发用户数按日活峰值的1.5倍估算。这些数字写进需求文档后面架构设计才有依据。注意非功能需求一定要和干系人确认。我遇到过产品经理说“性能要快”追问多快他说“比现在快就行”。这种需求等于没写。必须逼出具体数字。2.4 需求评审怎么开才不浪费时间需求评审不是念文档。我组织评审的流程是提前48小时发文档标注重点评审章节和待确认问题。评审会只讨论有争议的点没争议的默认通过。每个争议点必须有结论接受、拒绝、延期、需要补充信息。会后24小时内发会议纪要明确每条结论的责任人和截止时间。我踩过的坑有一次评审会来了15个人产品念了2小时文档最后没人记得结论是什么。后来我改成“沉默评审争议讨论”会前大家看文档并在共享表格里标注问题会上只讨论标注了“有异议”的条目。评审时间从2小时压缩到40分钟结论还更清晰。另一个经验需求文档的版本号必须和评审记录绑定。V1.2评审通过后任何修改都要升版本号并记录变更原因。否则开发拿着V1.1的文档写代码测试拿着V1.3的文档测对不上。3. 概要设计说明书从需求到模块的第一次跳跃3.1 概要设计的核心任务分而治之概要设计要做的事说白了就是把需求拆成模块把模块连成系统。需求说“用户能下单”概要设计要说“下单功能放在订单模块订单模块调用库存模块扣减库存调用支付模块发起支付订单数据写入订单库”。我写概要设计文档通常包含这些部分系统架构图分层架构还是微服务各层/各服务职责是什么。模块划分与职责每个模块负责什么不负责什么。模块间接口谁调用谁传什么参数返回什么异常怎么处理。数据流设计核心数据从哪来到哪去经过哪些模块。技术选型与理由为什么用这个框架、这个数据库、这个消息队列。部署架构几台机器、怎么部署、怎么扩容。非功能设计性能怎么保证、安全怎么保证、可用性怎么保证。架构图我一般用文字简单框图描述不用复杂工具。关键是每个模块的边界要清晰。我见过一个系统用户模块里写了订单查询逻辑订单模块里又写了用户权限校验最后改一个权限规则要动三个模块。这就是概要设计没做好。3.2 模块划分的实操原则模块划分我遵循几个原则高内聚一个模块只做一类事。比如“用户认证”模块只负责登录、登出、token管理不负责用户资料修改。用户资料修改属于“用户信息”模块。低耦合模块之间通过接口通信不直接访问对方的数据库。订单模块需要用户信息调用户模块的接口不直接查用户表。单一职责一个模块只有一个被修改的理由。如果需求变化时你发现要同时改三个模块说明划分有问题。接口稳定模块内部怎么改都行对外接口尽量不变。接口变了调用方就要跟着改。举个例子一个电商系统的概要设计我可能会这样划分模块职责对外接口依赖模块用户模块注册、登录、权限、用户信息认证接口、用户查询接口无商品模块商品管理、分类、搜索商品查询接口、商品管理接口无订单模块下单、订单查询、状态流转创建订单接口、订单查询接口用户、商品、库存、支付库存模块库存扣减、回滚、查询扣减接口、回滚接口无支付模块支付发起、回调、退款支付接口、退款接口订单这样划分后每个模块可以独立开发、独立测试、独立部署。订单模块依赖多但依赖的是接口不是实现。3.3 接口设计概要设计里最值钱的部分接口设计是概要设计的核心产出。我写接口定义一般包含接口名称与编号请求方式与路径请求参数字段名、类型、必填、说明响应参数字段名、类型、说明错误码定义调用示例幂等性说明超时与重试策略比如创建订单接口POST /api/order/create 请求参数 - userId: Long, 必填, 用户ID - items: Array, 必填, 商品列表 - skuId: Long, 必填, 商品SKU - quantity: Integer, 必填, 数量 - addressId: Long, 必填, 收货地址ID 响应参数 - code: Integer, 200成功 - data: - orderId: Long, 订单ID - totalAmount: Decimal, 总金额 - status: String, 订单状态 错误码 - 40001: 库存不足 - 40002: 商品已下架 - 40003: 地址无效 - 50001: 系统繁忙请重试 幂等性同一userId同一请求ID重复提交返回同一订单。 超时3秒超时后客户端可重试服务端保证幂等。接口定义清楚前后端可以并行开发测试可以提前写用例。我见过接口没定义清楚就开工的项目前端猜字段名后端猜参数类型联调时吵成一团。提示接口的错误码要统一规划。我一般按模块分段用户模块40001-40099订单模块40100-40199支付模块40200-40299。这样一看错误码就知道哪个模块出的问题。3.4 技术选型别为了新而新技术选型是概要设计里最容易吵架的部分。我的原则是成熟优先、团队熟悉优先、社区活跃优先。新框架再炫团队没人会用上线后出问题没人能修就是给自己挖坑。选型时要写清楚理由。比如选MySQL而不是PostgreSQL理由可能是团队更熟悉MySQL、运维体系已支持MySQL、当前数据量不需要PostgreSQL的高级特性。选型文档里要记录备选方案和放弃原因这样后来人问“为什么不用XX”时有据可查。我经历过一次选型翻车项目用了某个当时很火的消息队列结果社区半年后停止维护出了bug没人修最后花了两周迁移到另一个队列。所以选型时我会看几个指标GitHub最近一年提交频率、issue响应速度、是否有商业公司支持、版本迭代是否稳定。这些在概要设计文档里不用写太细但选型时心里要有数。4. 详细设计说明书让编码变成填空题4.1 详细设计的颗粒度写到什么程度算够详细设计写到什么程度我的标准是一个中级开发拿着详细设计文档不需要问人就能写出代码。具体包括类图有哪些类、类之间的关系、每个类的属性和方法。时序图核心流程的调用顺序、参数传递、返回处理。数据库表结构每个字段的类型、长度、约束、默认值、注释。算法逻辑关键算法的步骤、边界条件、异常处理。异常处理每个可能出错的地方怎么处理、返回什么错误码。配置项需要哪些配置、默认值是什么、怎么修改。但也不是越细越好。如果详细设计写到伪代码级别那开发就变成打字员了反而失去意义。我一般对核心模块写到方法级别对边缘模块写到类级别。核心模块是那些逻辑复杂、容易出错、后期改动频繁的模块。4.2 数据库表结构设计字段不是拍脑袋定的表结构设计是详细设计里最需要经验的部分。我设计表结构时考虑字段类型能用INT就不用BIGINT能用VARCHAR(50)就不用VARCHAR(255)。但也要留余量比如用户名VARCHAR(50)够用但考虑到未来可能支持邮箱登录可以放到VARCHAR(100)。索引哪些字段查得多、哪些字段组合查、哪些字段要唯一。索引不是越多越好写入频繁的表索引要克制。约束非空、唯一、外键、默认值。外键在互联网高并发场景下一般不建靠应用层保证。注释每个字段必须有注释说明业务含义。我见过一个表有30个字段一半没注释后来人只能靠猜。举个例子订单表字段名类型允许空默认值索引注释idBIGINT否自增主键订单IDorder_noVARCHAR(32)否无唯一订单编号业务唯一user_idBIGINT否无普通用户IDtotal_amountDECIMAL(12,2)否0.00无订单总金额statusTINYINT否0普通0待支付 1已支付 2已发货 3已完成 4已取消created_atDATETIME否CURRENT_TIMESTAMP普通创建时间updated_atDATETIME否CURRENT_TIMESTAMP ON UPDATE无更新时间状态字段用TINYINT而不是VARCHAR省空间且比较快。金额用DECIMAL不用FLOAT避免精度丢失。order_no加唯一索引防止重复下单。这些细节在详细设计里写清楚开发就不会乱来。4.3 核心流程的时序设计把调用链画清楚详细设计里最有用的是核心流程的时序描述。比如“用户下单”这个流程客户端调创建订单接口传userId、items、addressId。订单服务校验参数userId是否存在、items是否为空、addressId是否有效。订单服务调商品服务批量查询SKU信息校验商品状态和价格。订单服务调库存服务批量扣减库存。如果任一SKU库存不足全部回滚返回40001。订单服务计算总金额生成订单号写入订单表。订单服务调支付服务发起支付。支付服务返回支付链接。订单服务返回orderId、totalAmount、支付链接给客户端。每一步都要写清楚调什么接口、传什么参数、返回什么、异常怎么处理。比如第4步库存扣减失败要回滚已扣减的库存返回明确错误码。第6步支付发起失败订单状态保持待支付允许用户重新发起。我一般用时序图文字说明。时序图用简单的箭头表示不用复杂工具。关键是异常分支也要画出来正常流程谁都会写异常流程才是详细设计的价值所在。4.4 异常处理设计别让系统一错就崩异常处理是详细设计里最容易被跳过、但上线后最要命的部分。我要求每个接口都要定义参数校验失败返回400错误码明确。业务规则不满足返回200但code非成功比如库存不足。依赖服务超时设置超时时间超时后是重试还是降级还是直接失败。依赖服务返回错误根据错误类型决定是重试、降级还是透传。数据库异常连接失败、死锁、唯一键冲突分别怎么处理。未知异常兜底捕获记录日志返回系统繁忙。我一般会定义一个全局错误码表每个错误码对应一个处理策略。比如错误码含义HTTP状态客户端处理服务端处理40001库存不足200提示用户记录日志40002商品已下架200提示用户记录日志50001系统繁忙500提示重试告警日志50002依赖服务超时500提示重试告警日志这样开发写代码时直接查表不用自己发明错误码。测试也可以按错误码设计用例。5. 三份文档的衔接与常见坑5.1 需求到概要别丢信息需求文档里的每条功能需求在概要设计里都要能找到对应的模块。我一般做一个需求-模块映射表需求编号需求描述负责模块接口编号REQ-ORDER-012批量导出待发货订单订单模块API-ORDER-045REQ-ORDER-013订单状态自动流转订单模块内部定时任务这样评审概要设计时可以逐条检查需求是否被覆盖。我见过需求有50条概要设计只覆盖了40条剩下10条开发说“没看到”。映射表就是防这个的。5.2 概要到详细别改接口概要设计定下的接口详细设计阶段尽量不改。如果必须改要同步更新概要设计文档并通知所有调用方。我经历过一次详细设计时开发觉得某个接口参数太多自己合并了两个字段结果前端按概要设计的文档联调直接报错。后来规定接口变更必须走变更流程更新文档版本邮件通知所有干系人。5.3 常见坑速查表坑表现后果规避方法需求没有验收条件开发做完不知道对不对返工每条需求配Given-When-Then非功能需求缺失上线后性能差、安全漏洞紧急修复强制填写非功能需求表模块边界不清改一个功能动多个模块维护成本高高内聚低耦合原则评审接口定义模糊联调时吵架进度延误接口字段、类型、错误码写全表结构没注释后来人看不懂数据混乱每个字段必须有注释异常处理没设计一错就崩用户体验差全局错误码表异常分支设计文档版本混乱开发测试对不上质量失控版本号变更记录邮件通知5.4 我个人的文档管理习惯我写这三份文档时会用同一个文档管理工具但分三个独立文件。需求文档用Word或在线文档方便产品标注概要设计和详细设计用Markdown方便版本管理和代码仓库一起存。每次变更都提交到Gitcommit message写清楚改了什么、为什么改。评审时我要求每个参会人在文档上直接批注不要口头说。口头说的东西会后没人记得批注留在文档里谁什么时候提了什么意见一目了然。评审通过后批注归档文档锁定版本。最后分享一个小技巧详细设计文档里的类名、方法名、表名、字段名直接复制到代码里用。这样文档和代码保持一致后来人看文档就能找到代码看代码也能对应到文档。我见过文档写“用户表”代码里叫“t_member”找起来费劲。统一命名省的是自己的时间。这三份文档写好了项目就成功了一半。剩下的另一半是执行——按文档写代码、按文档测试、按文档验收。文档不是写完就完了是拿来用的。用起来它才有价值。