范围限定:拿到业务需求之后,正式写代码之前的全部技术流程 ;编码、CI、测试、上线不在本范围。
简化链路:业务需求输入 → 技术方案/架构设计 → 详细设计 → 评审 → 输出编码输入物,才进入代码实现。
0. 总体介绍
- 是什么:编码开工前,把业务需求翻译成技术侧可落地的设计输出,给开发明确"怎么写"的一套技术工作。包含架构、模块、接口、数据、边界、异常。
- 主要解决:避免拿到需求直接开写,写到一半发现方案错误、模块耦合、数据库不合理、边界没考虑,后期大量返工。
- 不解决:代码具体怎么写、单元测试、bug修复;不负责产品业务对错。
- 需要掌握的核心:需求拆解、方案选型、模块划分、数据库设计、接口定义、风险点识别、评审。
1. 核心原理
核心名词概念
| 概念 | 含义 |
|---|---|
| 需求拆解(技术拆解) | 把PRD翻译为技术视角,梳理输入输出、主流程、分支场景、异常、外部依赖,筛出模糊需求 |
| 概要架构设计 | 确定模块拆分、服务边界、外部依赖组件(缓存/MQ/DB),高层数据流,不抠接口字段 |
| 模块设计 | 系统内部拆分为哪些模块,模块职责、模块之间怎么交互 |
| 数据库设计 | 表结构、字段、索引、约束、分库分表、数据流转,历史数据兼容 |
| 接口设计 | RPC/HTTP接口,入参、出参、错误码、分页、鉴权、超时 |
| 详细方案设计 | 把主流程、异常流程、并发、幂等、限流、事务、缓存策略全部写清 |
| 技术方案评审 | 架构、后端、DBA、相关开发一起过方案,提前揪漏洞 |
| 前置风险识别 | 并发热点、数据一致性、兼容性、降级、第三方依赖不可用场景 |
编码前完整技术工作流
#mermaid-svg-xnlvzfEC8kgtpFFO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xnlvzfEC8kgtpFFO .error-icon{fill:#552222;}#mermaid-svg-xnlvzfEC8kgtpFFO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xnlvzfEC8kgtpFFO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xnlvzfEC8kgtpFFO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xnlvzfEC8kgtpFFO .marker.cross{stroke:#333333;}#mermaid-svg-xnlvzfEC8kgtpFFO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xnlvzfEC8kgtpFFO p{margin:0;}#mermaid-svg-xnlvzfEC8kgtpFFO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster-label text{fill:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster-label span{color:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster-label span p{background-color:transparent;}#mermaid-svg-xnlvzfEC8kgtpFFO .label text,#mermaid-svg-xnlvzfEC8kgtpFFO span{fill:#333;color:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO .node rect,#mermaid-svg-xnlvzfEC8kgtpFFO .node circle,#mermaid-svg-xnlvzfEC8kgtpFFO .node ellipse,#mermaid-svg-xnlvzfEC8kgtpFFO .node polygon,#mermaid-svg-xnlvzfEC8kgtpFFO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xnlvzfEC8kgtpFFO .rough-node .label text,#mermaid-svg-xnlvzfEC8kgtpFFO .node .label text,#mermaid-svg-xnlvzfEC8kgtpFFO .image-shape .label,#mermaid-svg-xnlvzfEC8kgtpFFO .icon-shape .label{text-anchor:middle;}#mermaid-svg-xnlvzfEC8kgtpFFO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xnlvzfEC8kgtpFFO .rough-node .label,#mermaid-svg-xnlvzfEC8kgtpFFO .node .label,#mermaid-svg-xnlvzfEC8kgtpFFO .image-shape .label,#mermaid-svg-xnlvzfEC8kgtpFFO .icon-shape .label{text-align:center;}#mermaid-svg-xnlvzfEC8kgtpFFO .node.clickable{cursor:pointer;}#mermaid-svg-xnlvzfEC8kgtpFFO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xnlvzfEC8kgtpFFO .arrowheadPath{fill:#333333;}#mermaid-svg-xnlvzfEC8kgtpFFO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xnlvzfEC8kgtpFFO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xnlvzfEC8kgtpFFO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xnlvzfEC8kgtpFFO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xnlvzfEC8kgtpFFO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xnlvzfEC8kgtpFFO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster text{fill:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO .cluster span{color:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xnlvzfEC8kgtpFFO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xnlvzfEC8kgtpFFO rect.text{fill:none;stroke-width:0;}#mermaid-svg-xnlvzfEC8kgtpFFO .icon-shape,#mermaid-svg-xnlvzfEC8kgtpFFO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xnlvzfEC8kgtpFFO .icon-shape p,#mermaid-svg-xnlvzfEC8kgtpFFO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xnlvzfEC8kgtpFFO .icon-shape .label rect,#mermaid-svg-xnlvzfEC8kgtpFFO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xnlvzfEC8kgtpFFO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xnlvzfEC8kgtpFFO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xnlvzfEC8kgtpFFO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 模糊、缺失
需求完备
评审不通过
评审通过
业务PRD需求
技术需求拆解
梳理正常/异常场景、外部依赖
需求是否清晰?
退回产品补全需求
概要架构&模块划分
高层数据流、技术组件选型
详细设计
数据库+接口+流程+并发异常处理
输出完整技术方案文档
方案评审
正式进入代码实现
底层原理文字说明:
- 这一阶段核心目标:把风险前置。设计阶段修改方案成本很低;代码写完再改,成本成倍上涨。
- 分层设计逻辑:先高层架构模块,再落到库表、接口,不要一上来直接设计表或者写接口。
- 不能只设计"正常流程",大部分线上故障来自异常场景:第三方超时、并发、重复请求、数据旧版本兼容。
- 方案评审不是走形式,重点查:模块边界是否混乱、数据库索引/约束是否合理、并发下是否有数据不一致、依赖故障如何处理。
2. 不同规模项目,编码前设计对比
| 项目规模 | 概要架构 | 详细设计 | 数据库 | 接口设计 | 评审 |
|---|---|---|---|---|---|
| 小需求/单模块内部迭代 | 简单,口头梳理模块 | 简短文档,重点写异常 | 直接设计表结构 | 简单接口,注释写清 | 小范围评审甚至同伴沟通 |
| 中大型业务模块 | 输出高层模块图、依赖组件 | 完整方案:主流程+异常+并发 | 完整表、索引、迁移脚本 | 完整接口文档、错误码 | 后端小组评审 |
| 跨服务大版本改造 | 完整架构、服务边界、数据流图 | 全量方案,含降级、限流、回滚预案 | DBA参与评审,考虑分表、数据迁移 | 跨服务RPC契约,版本兼容 | 架构+DBA+依赖方共同评审 |
3. Pros & Cons
| ✅优点 | ❌缺点 |
|---|---|
| 提前发现架构、数据库、并发逻辑漏洞 | 写方案、评审需要消耗开发时间,拉长开工时间 |
| 明确模块职责,避免多人开发互相冲突 | 过度设计:把简单需求做复杂架构,增加无用复杂度 |
| 统一团队认知,所有人按同一套方案编码 | 文档写完没人维护,后续和代码脱节 |
| 提前识别第三方依赖风险、数据兼容风险 | 如果需求频繁变更,设计文档需要同步修改,否则失效 |
4. 核心工程权衡 Trade‑off
- 概要设计 vs 过度详细设计
- 概要设计:只定模块、组件、高层流程;好处速度快;代价:很多细节需要编码时临时思考,容易遗漏边界case。适合小迭代。
- 完整详细设计:把表、接口、异常、并发全部写完整;好处编码几乎只需要翻译方案;代价写文档耗时久。适合核心、高风险业务。>
取舍:风险越高,详细设计越要完备;简单内部工具,减少文档,重点口头梳理清楚边界。
- 先定架构模块 vs 先设计数据库
反模式:上来直接设计表,再反过来套业务流程,容易造成表职责混乱。
正确顺序:先模块划分,再根据模块职责推导表结构。
代价:多一步抽象思考;收益:表和模块职责对齐,减少后期大改表。
- 方案评审:全员大评审 vs 小范围沟通
大评审:多人参与,漏洞更容易暴露;代价时间成本高,会议冗长。
小范围沟通:效率高;容易漏掉视角,隐藏架构问题。
取舍:跨服务、核心交易走正式评审;普通模块,2‑3个相关开发评审即可。 - 兼容旧数据 vs 直接改动表结构
新需求要改表:直接改字段简单快速;但线上存量数据、老版本服务会出错。
编码前就需要决定:是做兼容改造,还是数据迁移。不能编码时才考虑存量。 - 是否要把异常全部写进方案
只写主流程文档写的快;但大部分bug出现在异常:第三方超时、并发、重复请求。
取舍:高风险业务,异常场景必须写入技术方案;简单内部工具可以简化。
5.适用 / 不适用场景
| ✅适合场景 | ❌不适合场景 |
|---|---|
| 多人协作开发业务模块 | 个人Demo、临时验证POC原型 |
| 核心链路、交易、资金、鉴权模块 | 一次性用完丢弃的简单脚本 |
| 跨多个服务协同开发的需求 | 极简单需求,仅改动1‑2个接口,无库表变更 |
| 涉及数据库大改、分表迁移需求 | 学习练习,不需要上线维护 |
6.选型决策流程(编码前设计做到什么程度)
#mermaid-svg-15oGPTFx7e6pv0Ex{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-15oGPTFx7e6pv0Ex .error-icon{fill:#552222;}#mermaid-svg-15oGPTFx7e6pv0Ex .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-15oGPTFx7e6pv0Ex .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-15oGPTFx7e6pv0Ex .marker{fill:#333333;stroke:#333333;}#mermaid-svg-15oGPTFx7e6pv0Ex .marker.cross{stroke:#333333;}#mermaid-svg-15oGPTFx7e6pv0Ex svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-15oGPTFx7e6pv0Ex p{margin:0;}#mermaid-svg-15oGPTFx7e6pv0Ex .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster-label text{fill:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster-label span{color:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster-label span p{background-color:transparent;}#mermaid-svg-15oGPTFx7e6pv0Ex .label text,#mermaid-svg-15oGPTFx7e6pv0Ex span{fill:#333;color:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex .node rect,#mermaid-svg-15oGPTFx7e6pv0Ex .node circle,#mermaid-svg-15oGPTFx7e6pv0Ex .node ellipse,#mermaid-svg-15oGPTFx7e6pv0Ex .node polygon,#mermaid-svg-15oGPTFx7e6pv0Ex .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-15oGPTFx7e6pv0Ex .rough-node .label text,#mermaid-svg-15oGPTFx7e6pv0Ex .node .label text,#mermaid-svg-15oGPTFx7e6pv0Ex .image-shape .label,#mermaid-svg-15oGPTFx7e6pv0Ex .icon-shape .label{text-anchor:middle;}#mermaid-svg-15oGPTFx7e6pv0Ex .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-15oGPTFx7e6pv0Ex .rough-node .label,#mermaid-svg-15oGPTFx7e6pv0Ex .node .label,#mermaid-svg-15oGPTFx7e6pv0Ex .image-shape .label,#mermaid-svg-15oGPTFx7e6pv0Ex .icon-shape .label{text-align:center;}#mermaid-svg-15oGPTFx7e6pv0Ex .node.clickable{cursor:pointer;}#mermaid-svg-15oGPTFx7e6pv0Ex .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-15oGPTFx7e6pv0Ex .arrowheadPath{fill:#333333;}#mermaid-svg-15oGPTFx7e6pv0Ex .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-15oGPTFx7e6pv0Ex .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-15oGPTFx7e6pv0Ex .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-15oGPTFx7e6pv0Ex .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-15oGPTFx7e6pv0Ex .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-15oGPTFx7e6pv0Ex .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster text{fill:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex .cluster span{color:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-15oGPTFx7e6pv0Ex .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-15oGPTFx7e6pv0Ex rect.text{fill:none;stroke-width:0;}#mermaid-svg-15oGPTFx7e6pv0Ex .icon-shape,#mermaid-svg-15oGPTFx7e6pv0Ex .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-15oGPTFx7e6pv0Ex .icon-shape p,#mermaid-svg-15oGPTFx7e6pv0Ex .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-15oGPTFx7e6pv0Ex .icon-shape .label rect,#mermaid-svg-15oGPTFx7e6pv0Ex .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-15oGPTFx7e6pv0Ex .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-15oGPTFx7e6pv0Ex .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-15oGPTFx7e6pv0Ex :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 高风险:交易/资金/跨服务
普通业务,单服务内迭代
极低风险,简单小改动
有模糊
需求完备
需求输入,编码前
业务风险?
完整流程:架构模块 → 详细方案 → DB+接口 → 正式评审
简化方案:模块梳理,DB+接口,2‑3人评审
口头梳理场景,核心点确认,不需要长篇文档
需求是否存在模糊点
退回澄清需求,不允许直接编码
进入代码实现
7.编码前阶段高频踩坑点
| 坑 | 最佳实践 |
|---|---|
| 拿到PRD直接上手写代码,跳过设计 | 强制:库表改动、新增接口必须经过技术拆解,再编码 |
| 方案只写正常流程,完全忽略异常、并发、第三方失败 | 方案必须覆盖:超时、重试、幂等、降级、并发冲突 |
| 架构模块边界模糊,模块职责混乱 | 模块明确单一职责,提前定义模块之间交互方式 |
| 数据库设计拍脑袋,不考虑索引、存量数据兼容 | 新增/修改表,编码前确认索引、字段约束、历史数据迁移方案 |
| 接口只考虑成功返回,不定义错误码、异常返回 | 接口设计同时定义失败场景返回,不能编码时临时补 |
| 需求有歧义,开发自己脑补业务逻辑 | 有疑问必须找产品确认,不要自行脑补需求 |
| 评审走过场,只看格式,不抠逻辑和风险 | 评审重点提问:并发怎么办?第三方挂了怎么办?旧数据怎么兼容? |
| 过度设计,小需求套重型架构 | 需求规模匹配设计粒度,拒绝为"未来可能"做未到来的功能 |
| 跨服务需求,没有和依赖方对齐接口契约就开始设计 | 跨服务变更编码前就要和依赖方确认接口、版本、上线顺序 |
补充:编码前产出物一般是:技术方案文档、ER图、接口契约、迁移脚本、风险预案。全部确认完毕,才开始写业务代码。