ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

概要设计与详细设计:从定骨架到填血肉的完整指南

2026/9/18 19:58:13 拓冰建站 浏览量
概要设计与详细设计:从定骨架到填血肉的完整指南 1. 概要设计和详细设计先分清“定骨架”和“填血肉”不少刚入行的工程师容易把概要设计和详细设计混为一谈甚至觉得“设计嘛就是画几张图写几个文档差不多就行了”。真等到项目进入开发、测试、验收阶段才发现设计文档里全是槽点接口字段对不上、模块边界含糊、数据库表结构漏了关键约束最后只能一边写代码一边改设计项目延期不说返工成本高得吓人。我做了这么多年软件项目最大的体会就是概要设计和详细设计是两件完全不同的事前者回答“系统长什么样、分成几块、块与块之间怎么说话”后者回答“每一块内部到底怎么实现、每个类怎么写、每个表怎么建”。说得更直白一点概要设计是给系统搭骨架详细设计是往骨架里填血肉。骨架搭歪了后面填什么都别扭血肉没填到位骨架再合理也跑不起来。这篇内容适合谁看呢一是刚入行的开发工程师想搞明白设计文档到底怎么落地二是带项目、做评审的团队骨干想梳理出一套能真正指导开发的设计方法三是准备软考或者走技术晋升的同行需要把“概要设计”“详细设计”的概念和实操彻底吃透。下面我会结合一个常见的业务系统案例把两份设计的核心思路、具体做法、踩坑点一次说清。1.1 概要设计完成的标志系统边界、模块划分、接口契约都定了很多人写概要设计说明书喜欢堆一堆高大上的架构图、流程图但问起“系统有哪几个模块”“每个模块对外提供哪些服务”“模块之间是同步调用还是异步消息”“数据存在哪里、怎么流转”反而答不上来。这说明概要设计根本没做到位。概要设计阶段核心产出物是系统架构设计、模块划分、接口定义、数据结构设计、部署方案。它的验收标准不是“图够不够漂亮”而是“任何一名开发拿到这份文档都能清楚知道自己的模块从哪来、往哪去、跟谁对接、数据怎么存”。换句话说概要设计做完技术选型和整体结构就不能再大改了后续开发应该是在这个框架里细化而不是推翻重来。我在实际项目中通常会做一件事在概要设计评审会上让每个模块的负责人用自己的话复述一遍整体架构、自己模块的职责、上下游依赖关系。如果复述不出来说明设计没吃透评审不予通过。这个方法看起来很土但比看文档有效得多。1.2 详细设计完成的标志每个类、每个接口、每个表结构都有明确实现方案详细设计阶段关注点从“系统级”下沉到“模块级”“类级”。它要回答的问题是某个功能点由哪几个类协同完成每个类有哪些属性和方法方法内部的关键流程是什么数据库表有哪些字段、字段类型是什么、索引怎么建接口的请求参数、返回结果、异常码各是什么界面元素与逻辑层的交互怎么走详细设计的粒度要细到“开发人员拿到后不需要再拍脑袋做决策直接翻译成代码即可”。我见过很多团队的详细设计文档写得跟概要设计差不多全是空泛的“模块负责某某功能”没有任何类图、序列图、字段说明、异常流程。这种文档本质上是一堆废话对开发毫无帮助评审时应该直接打回。1.3 用建房子的思路理解两份设计把软件开发比作盖楼会更直观。概要设计相当于建筑方案设计楼盖多高、分几层、每层是什么功能、承重墙在哪、水电暖通的管井走哪、电梯和楼梯怎么布置。这些定了施工队才能进场。详细设计则相当于施工图每一堵墙的厚度、每一根钢筋的规格、每一处水电管线的精确位置、每个装修材料的品牌型号。没有施工图工人根本没法干活。“盖到一半再改方案”是建筑行业的大忌软件项目同理。概要设计阶段多花一周时间把整体结构想清楚后面省下的是几周甚至几个月的返工时间。这个道理很多人懂但一到实际项目里就因为“进度紧”“先跑起来再说”把设计环节压缩得可怜最后反而更慢。2. 概要设计实操五件事决定系统走向这部分我结合一个实际做过的客户管理系统来拆解。当时的需求是管理客户信息、跟进记录、订单数据、统计报表支持多角色登录和权限控制。看上去不复杂但如果不做概要设计直接写代码很快会发现客户、订单、跟进记录之间的数据关系理不清权限逻辑散落各处报表查询慢到没法用。2.1 架构风格选型别上来就微服务听到“微服务”三个字很多团队就兴奋觉得不用微服务就显得不够先进。但微服务是有代价的分布式事务、服务治理、链路追踪、部署复杂度都是实打实的成本。一个客户管理系统用户量几百人日均请求量几千次单体应用加个缓存就绰绰有余强行拆微服务只会让开发效率直线下降。我在概要设计阶段首先问自己三个问题系统预期的并发量是多少数据量级到多少团队规模和维护能力怎么样这三个问题想清楚了架构选型自然就有答案。小型业务系统用单体分层架构加关系型数据库就好真正需要水平扩展、独立部署、分团队并行开发的时候才考虑微服务。具体到那个客户管理系统我选的是经典的分层架构表现层、业务逻辑层、数据访问层加一个MySQL做主存储Redis做热点数据缓存。简单、可靠、团队里人人都熟。2.2 模块划分高内聚低耦合不是口号模块划分是概要设计的核心工作也是很多团队做得最敷衍的部分。常见错误有两种一种是把模块划分等同于按功能页面划分客户管理、订单管理、统计报表各算一个模块结果订单模块要查客户信息、统计模块要读订单数据模块之间交叉调用严重另一种是模块粒度太大“公共模块”这种大筐什么都往里装最后公共模块成了垃圾堆。我采用的划分方法是“按业务能力划分”。客户管理模块负责客户信息和标签跟进模块负责跟进记录的增删改查交易模块负责订单、合同和付款报表模块负责统计查询系统管理模块负责用户、角色、权限。每个模块只关心自己领域内的逻辑对外暴露清晰的接口模块之间通过接口交互不允许跨层直连数据库。这样做的好处是每个模块都能独立分配、独立测试、独立维护改一个模块的内部实现不影响其他模块。这里有一个实操细节模块划分的时候建议先把核心业务对象找出来比如客户、订单、跟进记录、用户。然后围绕这些对象圈定各自的行为和关系再按照“行为聚集”的原则合并成模块。如果两个对象之间的操作总是成对出现比如“下单”必然要“改客户状态”就要考虑是不是同一个模块更合适。2.3 接口设计先定契约再写实现概要设计阶段必须把模块间的接口契约大致定下来。注意这里“大致”不是说可以模糊而是指接口的请求方、响应方、主要出入参、同步还是异步要明确但具体字段的细节可以放到详细设计阶段补充。举例来说跟进模块需要通知交易模块“客户已被重点跟进”概要设计阶段就要定义这个事件的名称、触发时机、关键载荷比如客户ID、跟进状态码。至于这个事件是走HTTP回调还是MQ消息数据格式是JSON还是对象序列化可以在详细设计阶段再定。但事件本身是否存在、由谁发起、谁消费必须在概要设计里说清楚。我习惯在概要设计阶段画一张模块依赖矩阵横轴和纵轴都是各个模块交叉点标注依赖关系和数据流向。这样做有两点好处一是能直观发现循环依赖比如A模块调B模块、B模块又调A模块这种必须调整二是评审的时候大家对着矩阵挨个过谁也说不出“我没看到依赖”这种话。2.4 数据设计概要阶段就要把数据流理顺数据设计不是数据库设计师一个人的事。概要设计阶段我们需要梳理系统的核心数据实体、实体之间的关系、数据在哪产生、在哪消费、在哪存储。关系型数据库还是NoSQL、要不要分库分表、数据要不要归档这些问题在概要设计阶段就要有倾向性方案。客户管理系统里核心实体是客户、联系人、跟进记录、订单、订单明细。实体关系上一个客户有多个联系人和多条跟进记录一个订单属于一个客户、包含多个明细。单据关系其实比较清晰。真正需要花心思的是数据量评估如果客户量预计百万级跟进记录按每年每条客户几十条算几年下来就是千万级甚至亿级。这时候就要考虑历史数据归档策略或者初期就按时间分区建表否则报表查询会成为灾难。注意数据量评估宁可高估一点也不要低估。我在另一个项目里就吃过亏初期觉得数据量小没考虑分区结果上线半年后单表数据过千万一条统计查询跑十几秒最后只能停服迁移。这个代价比一开始多做一版数据设计要大得多。2.5 概要设计说明书写文档不是写作文很多团队写概要设计说明书追求长篇大论动辄上百页。其实好的概要设计说明书应该是结构清晰、图文结合、点到要害。我的写法是背景与目标、名词解释、架构设计含架构图、模块划分与职责、核心接口清单、数据结构概览、部署架构、风险与对策、附录。架构图这里要注意不要画那种花哨的、每层塞满十几个小方块的图。好的架构图让人一眼看懂系统分几层、每层的关键组件是什么、数据流向是什么。画完之后拿给一个没参与需求讨论的同事看如果他能在三分钟内说出系统的大致结构和主要模块这张图才算合格。部署架构容易被忽略但它是概要设计里跟运维强相关的重要部分。应用部署在几台机器、数据库独立还是与应用同机、是否需要负载均衡、备份策略是什么这些都要写清楚。项目进入验收阶段“部署方式是否与设计一致”常常是验收组重点检查的内容提前设计好能省掉很多麻烦。3. 详细设计实操把每个模块彻底钉死概要设计完成后进入详细设计阶段。这个阶段的工作量往往比概要设计大得多因为它要把每个模块的内部实现方案一个个落定。很多团队在概要设计上花了大力气到了详细设计就松懈结果代码里各种临时设计、乱七八糟。3.1 类设计从模块职责推导类和职责以客户管理模块为例概要设计明确了它负责客户信息的全生命周期管理。到了详细设计阶段就要落地到类级别。我会列出这些类Customer实体类、CustomerRepository数据访问类、CustomerService业务逻辑类、CustomerController接口层类以及CustomerValidator校验类。每个类的职责必须单一比如CustomerService只做业务逻辑编排不直接写SQLSQL封装在CustomerRepository里。这里有个特别实用的原则如果一个类的private方法超过七八个或者方法行数普遍超过50行大概率是职责过重了要考虑拆分。类设计不是一次到位的等代码写起来发现不对劲及时调整类结构比硬撑着写完要好得多。对于类之间的关联关系我习惯用UML类图表达标注好继承、实现、聚合、依赖关系。类图不必精确到每个getter/setter但关键的业务方法必须标明因为这决定了类与外部协作的方式。3.2 时序图与状态机动态行为不能靠想象静态的类图还不够详细设计要能描述对象之间的动态协作。比如“用户新增一条跟进记录”这个操作涉及Controller、Service、Repository、数据库四层交互。用文字描述又长又容易歧义画一张时序图谁先调用谁、谁返回什么、异常在哪一层抛出一目了然。状态机是详细设计里容易被忽视但又极其重要的内容。典型场景是订单状态流转待付款、已付款、处理中、已完成、已取消、已退款。每个状态之间哪些迁移是允许的哪些是禁止的状态迁移需要满足什么条件触发后要执行哪些动作。把这张状态机图理清楚代码里的if/else会少很多很多非法操作在入口处就能拦截。我在实际编码中体会特别深很多线上BUG比如“支付回调重复处理导致订单状态错乱”“取消订单后还能继续发货”根源都是详细设计阶段状态机没画清楚开发者凭感觉写判断条件状态之间出现漏洞。所以状态机设计必须覆盖到每一个核心业务对象的状态变化尤其是异常路径支付超时、回调失败、人工介入修改状态都要考虑进来。3.3 数据库表结构设计字段级精确到类型约束详细设计阶段的数据库设计必须精确到字段级别。以客户表为例要列出每个字段的名称、类型、长度、是否允许为空、默认值、索引类型、备注。客户姓名用varchar(50)还是varchar(100)手机号存字符串还是数字性别字段用tinyint还是char(1)这些细节不决定清楚开发的时候每个人按自己习惯建表整个系统的数据风格就会非常混乱。索引设计上外键字段一般要加索引高频查询条件的字段要建联合索引查询很慢但又不适合建索引的字段要考虑是否用冗余字段或缓存解决。这里有一个常见坑开发初期数据量小索引有没有都无所谓等项目上线半年数据量上来慢查询一个个冒出来才追悔莫及。详细设计的时候就把索引规划好后面能省很多事。对于枚举状态字段我强烈建议使用整数类型加状态字典表或者用字符串字面量但必须统一编码比如订单状态用0/1/2/3还是“PENDING/PAID/DONE”必须全项目统一。否则A服务返回1表示已支付B服务把1当作待支付联调排查起来非常崩溃。为了避免这种问题我会在详细设计文档里附带一份“码表说明”把所有业务状态码集中列出来。3.4 核心算法与异常处理全局兜底比不停地加if重要详细设计里还要覆盖关键算法流程和异常处理策略。客户管理系统里有个典型算法根据跟进频率和最近跟进时间计算客户活跃度并给出“高/中/低”三档标签。这个计算的公式、权重、更新时机要在详细设计里写明否则开发自己发挥不同人的计算结果不一致产品验收时必然出问题。异常处理上要定一个统一方案。我个人推荐全局异常处理器加统一错误码体系Controller层不捕获业务异常由全局处理器统一处理并返回标准化错误JSON每类业务异常对应一个自定义异常类和一个错误码例如客户端参数错误编码10001、权限不足10003、数据不存在10004。千万不要每个Controller自己try/catch后随便返回一个“出错了”的字符串那样前端没法根据错误码做差异化提示排查问题也难。注意异常处理是详细设计里最容易被“忽略”但又最影响体验的部分。文档里最好列出常见异常场景及处理方式至少要覆盖参数校验失败、业务条件不满足、外部依赖超时、数据库操作失败这四类。3.5 详细设计说明书的写作节奏详细设计说明书该怎么组织我会按照模块分章每一章先描述模块职责然后是类图、核心时序图、状态机、接口定义表含请求参数、返回参数、异常码、数据库表结构、关键算法、涉及的外呼接口和中间件配置。这样开发一个模块只看对应的那一章就够了不用去翻整本厚文档。还有一个节奏上的建议详细设计不必一次性全部做完再评审可以按模块分批评审。比如先把客户管理模块详细设计做完评审通过后这个模块就进入编码阶段边做后续模块的详细设计。这样既能保证质量又能加速项目推进团队人员也不会闲着等待。4. 从概要设计到详细设计落地过程中的真实经验设计和编码之间的鸿沟往往是项目延期和返工的高发区。下面说几个我自己摸爬滚打总结出来的经验希望能帮你少走弯路。4.1 设计评审的节点和怎么准备概要设计和详细设计都需要正式评审但评审的重点完全不同。概要设计评审重点看架构合理性、模块划分是否清晰、接口契约是否完备、技术选型是否匹配需求详细设计评审重点看类设计是否合理、时序图是否覆盖关键路径、表结构是否完备、异常处理是否到位。评审组织方面我建议提前两天把设计文档发给所有参会人员要求先看再评。会上按模块过设计每个模块负责人先讲其他成员提问题。为了让评审不流于形式我会在文档末尾附一个“设计自查清单”让作者在提交评审前先逐条自查。清单包括模块职责是否一句话能讲清是否存在循环依赖接口是否有版本控制表结构是否有索引缺失异常路径是否全部处理关键算法是否有伪代码或公式。4.2 需求变更怎么影响两份设计需求变更是软件项目永恒的主题。最怕的是变更来了代码直接改文档不更新半个月后文档跟代码彻底对不上。我的经验是小变更直接修改详细设计文档对应章节并记录变更日志中等变更涉及接口调整或表结构变化要评估影响范围更新详细设计后通知相关模块负责人重大变更影响系统架构或核心模块拆分必须重新评审概要设计。这里有个实操技巧设计文档里每次修改建议在文末附一张变更记录表写明变更日期、变更人、变更内容、影响模块。这张表非常有用不光是追溯历史更重要的是评审新一轮设计时大家能快速看到和上一版的差异不用整份重新看。4.3 文档和代码同步不维护等于没写说到文档和代码的同步老实讲大部分团队做不到。原因很现实项目赶进度时写代码的时间都不够谁还顾得上更新设计文档。但真相是当一个项目进入维护期、交接期、验收期设计文档的作用才真正体现出来。我自己的做法是把设计文档放在代码仓库里和源码一起管理。模块设计文档放在对应模块的docs目录下修改代码的同时如果涉及设计的调整顺手改掉文档。代码评审的时候如果设计文档没有同步更新评审不予通过。这个制度刚推行时会觉得麻烦但坚持几次之后大家就习惯了维护成本并没有想象中高。项目验收时验收组经常要检查“概要设计说明书”“详细设计说明书”这些文档是否与实际系统一致。很多项目在验收前临时补文档补出来的东西跟实际代码脱节这时候不仅评分难看还可能暴露管理上的混乱。所以平时把文档维护好到验收时能省下大把临时加班的时间。5. 常见问题与排查思路实录最后这部分我整理了一些在设计和开发衔接过程中反复出现过的问题供你参考对照。5.1 接口讨论不清导致联调返工这是出现频率最高的问题。两个模块各自写接口A模块的开发者认为“状态”传数字1/2/3B模块的开发者觉得应该传“PAID/UNPAID”联调时才发现不一致只能改代码。根源就是详细设计阶段接口定义没做到字段级精确。排查思路很简单详细设计评审时重点核对接口出入参的每一个字段——字段名、类型、长度、取值范围、是否必填、默认值。最好把接口定义直接写进文档甚至用JSON Schema片段表述返回结构。这样开发时照着字段定义做联调时问题会大幅减少。5.2 过度设计把简单系统搞复杂过度设计和没设计是一对极端但过度设计更隐蔽。比如客户管理系统非要上事件驱动架构每个操作都发一条消息或者为了“将来可能用到”给每个表都加五六个冗余字段和一整套复杂的状态机。这些设计表面上很完整实际上增加了大量开发和维护成本却换不来实际价值。我的判断标准很简单当前明确的需求如果都不需要某项设计就不要引入。架构上保持“最小可行”原则预留扩展点可以但不要提前实现。真到了需要的时候基于合理的设计扩展并不难但被过度设计拖累的团队往往连重构的信心都没有。5.3 表结构与业务状态脱节数据库表设计和业务逻辑“各说各话”也是一种常见病。比如业务模块里定义了“已取消”状态但表设计时没有区分取消原因或者业务上允许“客户被标记为无效”但表结构里没有无效标记字段只能靠删除或者用备注字段硬塞。这类问题在详细设计评审时最值得花时间。我会对照核心业务流程图逐步验证每一个业务状态和数据操作都能找到对应的表结构和字段。走完一遍流程缺字段、多状态、字段含义矛盾的问题很快就会暴露出来。5.4 团队协作中“文档没人看”设计文档写得很全但开发时没人翻每个人按自己的想法写最后系统变得四不像。这种情况在规则松散、不重视设计评审的团队里尤其明显。要解决这个问题除了前面说的“文档放仓库、修改代码同步更新文档”外还需要一个强制动作开发任务估算时把“阅读并理解对应设计文档”作为任务的一部分写入排期编码完成后的自测清单里加一项“实现与设计文档逐条对照”。这两件事看起来是流程性的但能强制团队成员养成看文档的习惯。项目验收是设计工作的最好检验场。我经历过一个项目因为概要设计时对接口契约定义清楚验收测试阶段对接外部系统几乎没出问题也经历过另一个项目因为详细设计时状态机没画完整验收时测出十几个边界场景异常最后只能加班连夜修。设计工作是否扎实平时看着无关紧要一到验收就能原形毕露。如果让我给一条最实用的建议那就是概要设计的时候把架构和模块边界当成最大的事来审详细设计的时候把接口字段和状态流转当成最大的事来抠。这两件事做好了哪怕其他文档写得一般项目的可开发性、可维护性、可验收性都不会差。写代码重要但把设计写清楚这件事在我眼里比代码本身更决定一个项目的成败因为代码能被重构架构和模块边界的债往往是整个项目周期都在还。