资讯动态

软件工程设计图全解:总体设计、概要设计与详细设计实战指南

发布时间:2026/9/17 12:40:09 来源:尧图企业网站定制
说实话我每次在课程设计或毕业设计答辩现场看到有人拿着画得密密麻麻的软件工程设计图走上讲台被老师一句这张图是怎么从需求一步步推出来的问懵的时候都觉得特别可惜。老师看的不是图画得漂不漂亮而是你脑子里有没有完整的设计过程。软件工程设计图通常被分成总体设计、概要设计、详细设计三个层次。很多同学把这三个词理解成三种不同的图纸然后去学了一堆UML画法结果画出来一堆方框和箭头自己都不知道在表达什么。这篇文章我想换一个角度聊——不背教材定义而是站在设计说明书要能通过评审、要能真正指导编码这个实际目标出发把总体设计、概要设计、详细设计分别要解决什么问题、要产出什么图、有哪些常见的坑一次讲透。适合谁看软件工程课程设计、毕业设计需要写设计说明书的同学刚入行没多久、被要求补设计文档的程序员还有想系统理一遍软件设计流程的开发者。文章里我会用一个贯穿始终的图书管理系统案例你可以直接照着这个思路套到自己的项目上。1. 先搞清楚软件工程设计图到底是什么1.1 设计图的核心是决策不是画图先说一个最常见的误区。很多人一听到设计图三个字第一反应是去学绘图工具、去背各种图元的画法。工具当然要学但软件工程设计图的核心从来不是图而是决策。一张图之所以有价值是因为它记录了你对系统某个层面的关键决策总体设计图记录的是系统级别的决策系统分几个部分、每个部分的职责是什么、部署在哪里、之间怎么通信。概要设计图记录的是模块级别的决策系统拆成多少个模块、每个模块的边界在哪、模块之间通过什么接口交互。详细设计图记录的是代码级别的决策某个模块内部用哪个数据结构、算法流程是什么、异常怎么处理。你画图的过程本质上是把这些决策可视化。如果脑子里没有决策对着Visio或draw.io拖半天方块箭头画出来的图经不起一句追问。这一点在评审时特别明显。老师在课程设计答辩现场最喜欢问的就是为什么为什么系统要分成这三层为什么这个模块要有这个接口为什么这个算法选这种数据结构设计图是拿来支撑这些回答的不是拿来撑场面的。你图里画了什么就要能解释为什么那么画这才叫设计。1.2 三个设计阶段对应软件的三种粒度把软件开发比作盖房子这三个设计阶段的区别特别直观总体设计 确定这块地盖几栋楼、楼和楼之间的间距怎么摆、整片区域的水电怎么接入。对应到软件里就是系统架构系统由哪些子系统或服务组成、数据怎么存储、前后端怎么连、部署在什么环境。概要设计 确定其中一栋楼分几层、每层几个房间、每个房间是卧室还是客厅、走廊和公共楼梯怎么安排。对应到软件里就是模块设计系统拆成哪些模块、模块的职责是什么、模块间的接口怎么定义、核心数据结构长什么样。详细设计 确定某个房间内部的电路怎么走、开关装在什么高度、插座用几孔的。对应到软件里就是类与函数的设计每个函数的具体逻辑流程、用哪个数据结构组织数据、边界条件与错误处理怎么做。三种粒度对应三类读者。总体设计主要给项目经理、架构师、客户看用来对齐系统长什么样概要设计给模块负责人看用来拆分任务和组织开发详细设计给具体写代码的工程师看拿到手就能直接编码。你在写设计文档时先想清楚这份文档是给谁看的再决定写到什么粒度就不会出现把详细设计的内容写到总体设计里这种层次混乱的问题。1.3 结构化方法与面向对象方法怎么选这里想多说一句因为不少同学在写设计文档时会纠结到底用结构化方法数据流图、SC图还是用面向对象方法UML类图、时序图我的经验是课程设计、毕业设计通常两者可以结合但主线只能有一条。如果项目主体逻辑清晰、以数据流为线索比如典型的管理信息系统可以以结构化方法为主线总体设计画系统架构图概要设计画模块结构图详细设计用流程图或伪代码描述处理逻辑。如果项目天然适合面向对象建模比如有复杂的对象关系像电商系统、社交系统可以用UML为主线总体设计画组件图或包图概要设计画类图和时序图详细设计细化类的属性和方法。最忌讳的是两者混成四不像。文档里一会儿SC图一会儿UML图一会儿数据流图一会儿类图前后没有呼应评审老师看两遍也理不清你的设计思路。选定一条主线另一种方法作为局部补充这样文档整体统一也更容易讲清楚。2. 总体设计从需求到系统的大骨架2.1 总体设计要回答的五个问题总体设计阶段的输入是需求分析的结果——需求规格说明书、用例图、数据流图等。它的任务是把用户要什么翻译成系统怎么搭。具体来说就五个问题系统由哪几个部分组成每个部分的职责边界在哪部分之间如何交互数据存在哪里、怎么流动系统跑在什么环境里、性能和安全性怎么保证很多人把总体设计直接等同于画架构图其实架构图只是结果之一。在画图之前你得先确定架构风格。常见的风格有分层架构、事件驱动架构、微服务架构、管道-过滤器架构、仓库架构。对大多数课程设计和中小型项目来说分层架构是最稳妥的选择。分层架构的核心理念是上层依赖下层同层之间不互相调用表现层只调用业务层业务层只调用数据访问层数据访问层负责操作数据库。这样做的优点是模块边界清晰、依赖方向明确、容易分工也容易测试。你如果在课程设计里一上来就搞微服务老师不会觉得你厉害只会觉得你分不清场合——微服务的核心驱动是独立部署和弹性伸缩一个单机就能跑完的管理系统根本不需要那些复杂的治理组件。2.2 架构图怎么画才经得起追问先说说画架构图的工具。Visio、draw.io、ProcessOn都行我个人建议用draw.io或ProcessOn免费且模板够用支持协作导出的图片精度也不错。关键不在工具而在图里的内容。一张合格的总体架构图至少要包含这些元素清晰的层次或分区一眼能看出系统分几层每层有哪些组件。明确的调用方向箭头表示调用或依赖关系时方向不能画反。外部系统的标注比如第三方支付接口、短信服务要用不同颜色或形状标出来。数据存储的体现数据库、缓存、文件存储不能缺。我见过太多学生画的伪架构图框里写着用户管理图书管理借阅管理全部并排摆着外面套一个大方块箭头乱指。这张图暴露的问题就是没有做架构设计只是在画功能清单。功能不等于组件模块也不等于架构。/br/br正确的做法是先按职责分层。比如图书管理系统总体设计是这样的逻辑表现层Web页面登录、图书检索、借阅操作、后台管理界面业务层用户管理、图书管理、借阅管理、统计报表数据层MySQL核心业务数据、Redis可选缓存用于热门图书和登录会话基础设施应用服务器、Nginx反向代理、文件存储图书封面图层之间用箭头表示依赖浏览器发起请求到Nginx再到表现层表现层调用业务层接口业务层通过数据访问层操作数据库。这样一张图出来老师一眼就能看出你有没有架构的思维。2.3 总体设计说明书必备的板块清单评审老师或项目经理看总体设计说明书一般重点看几个板块。我整理了一个最小可用清单板块内容要点引言编写目的、项目背景、术语定义、参考资料总体描述系统目标、运行环境、设计约束、假设与依赖架构设计架构风格选择理由、总体结构图、各组件职责说明接口概述外部接口用户、第三方系统、内部接口概览数据存储设计核心数据表、存储方案、数据量预估部署设计物理部署方案、网络环境、软硬件要求安全与性能权限控制方式、日志策略、并发量预估与性能指标不是每个项目都要写全但至少架构设计接口概述数据存储设计这三块不能缺。尤其要写清楚设计理由——为什么用MySQL不用Oracle为什么做缓存为什么用分层架构这些理由比图本身更能体现你的设计能力。你每写下一个决定后面最好跟一句因为……既帮自己理清思路也让评审看到你不是在抄模板。3. 概要设计把大系统拆成能分工的模块3.1 模块划分的三条黄金原则总体设计定了大骨架概要设计开始细化把业务层拆成一个一个模块把模块间的接口定义清楚把每个模块的输入输出、处理逻辑用较粗略的方式描述出来。模块划分是概要设计最核心的工作。划得好团队各写各的互不干扰划得不好就是改一处牵全身。我判断模块划分是否合理的标准总结起来就是三条高内聚一个模块只做一类事职责单一内部元素之间联系紧密。低耦合模块之间尽量只通过接口通信少共享全局数据不直接操作对方的内部细节。接口最小化暴露给其他模块的接口越少越好只在必要时提供对外调用能力。拿图书管理系统来说业务层拆成用户管理、图书管理、借阅管理、统计报表四个模块就是常见且合理的划分。注意这里的用户管理不是一个功能按钮而是一个模块——它包含用户注册、登录、权限分配、信息维护等一组相关联的功能。每个模块再往下拆才进入详细设计。模块划分的粒度要适中太小会导致接口爆炸、管理成本高太大会导致模块内部过重、分工不明确。课程设计一般每个模块代码量控制在几百到两千行之间比较合适。3.2 模块结构图怎么画才清楚概要设计最经典的表达工具是模块结构图Structure ChartSC图。它和架构图不一样架构图强调系统分层和组件的关系SC图强调模块之间的调用层次和数据传递。画SC图的几个要点顶层是主控模块下面按调用关系逐层展开子模块。模块之间用箭头连接箭头上的小箭头标清传递的数据比如借阅请求借阅结果。模块命名用动词名词比如查询图书生成报表不要用数据处理这种含糊的名字。我之前带过一个小组做图书管理系统他们的SC图第一次画出来就吃了亏四个模块画成一排互相之间箭头上什么都没标。后来按调用层次数据传递重新画每个模块之间的箭头都标了用户信息图书信息借阅记录这些数据老师看了就说这下清楚了。顺带说一句SC图的数据传递要区分数据偶合和控制偶合传递数据如用户ID是好的传递控制信息如成功标志要少用。如果在SC图上频繁出现控制标志传递说明模块划分可能有问题可以考虑把判断逻辑上提或重构模块边界。3.3 接口设计模块之间怎么说话概要设计里接口设计最容易写空。我见过太多设计文档接口部分就一句话各模块之间通过函数调用交互然后没了这等于没写。接口设计至少要写清楚五件事接口名称和用途、输入参数名字、类型、取值范围、是否必填、输出结果返回类型、成功失败的表示、异常处理出错时抛什么、上层怎么处理、权限说明谁可以调用这个接口。举个例子图书管理模块和借阅管理模块之间有个核心接口借阅图书。概要设计阶段不写代码但要写清楚接口borrowBook(userId, bookId, borrowDays) 用途执行一次图书借阅操作 输入 userId 整型必填用户ID bookId 整型必填图书ID borrowDays 整型可选默认30范围1~60 输出 成功返回借阅记录ID整型 失败返回错误码 101 用户不存在 102 图书不存在 103 图书库存不足 104 用户存在逾期未还记录 异常 borrowDays小于1或大于60抛出参数异常这种粒度编码同学拿到就能直接开工不用再猜。很多团队协作摩擦本质上就是接口定义不清楚导致的信息不对称。概要设计这一步做扎实后面开发能省大量沟通成本。3.4 数据库设计的概要层级也要在这里定数据库设计放在概要设计还是详细设计不同团队的习惯不太一样。我的建议是概念模型实体关系放概要设计物理表结构放详细设计这样分工明确。概要设计阶段画出ER图实体关系图或者至少用表格描述核心实体和它们的关系就够了。比如图书管理系统实体主要属性与其他实体的关系用户id、用户名、密码、角色、状态与借阅记录是一对多图书id、书名、作者、ISBN、库存与借阅记录是一对多借阅记录id、用户ID、图书ID、借出时间、应还时间关联用户和图书图书分类id、分类名与图书一对多到了详细设计阶段再细化到具体字段类型、索引、外键约束。这样做的好处是概要设计阶段你先不陷入字段细节重点思考系统的核心业务实体和关系等到详细设计时字段怎么取名、索引怎么加心里已经有数了。4. 详细设计把模块做到拿来就能写代码4.1 详细设计到底管到哪一层如果说概要设计是规定模块的外部行为那么详细设计就是规定模块的内部实现。详细设计阶段每个模块要细化到模块内部有哪些类或函数各自职责是什么每个函数是做什么的、输入输出是什么选择什么数据结构来组织数据算法步骤怎么走、边界条件怎么处理错误处理、日志记录怎么安排很多同学的课程设计做到这一步就直接放弃了用代码代替设计文档。代码确实是最精确的设计但在工程评审中详细设计文档的价值在于不用写代码也能判断设计是否合理。评审者通过文档检查你的逻辑有没有漏洞、性能能不能达标、异常处理完不完善。这也是为什么很多公司虽然已经在敏捷开发核心模块仍然要求先写设计再编码——不是官僚主义是为了在编码前把问题消灭掉避免代码写完了再大改。你可以把详细设计看作编码前的最后一次预演。4.2 算法与数据结构设计谁说管理系统就没算法我发现不少同学不重视详细设计中的算法设计理由是我这个系统就是增删改查没啥算法。这个判断对一半确实不需要像算法竞赛那样复杂的逻辑但有几种场景必须认真设计算法否则代码写出来早晚出问题。以图书管理系统为例至少有这几个算法点图书查重添加图书时同名同作者算重复吗模糊匹配怎么做借阅超期计算借了30天中间跨了假期或闭馆日超期天数怎么算热门图书排行按借阅次数排序数据量大了怎么保证查询性能库存扣减多用户同时借书时怎么避免超卖这些算法不一定用到什么高深技巧但你要用流程图或伪代码把它表达清楚。比如库存扣减可以这样写函数handleBorrowRequest(userId, bookId, borrowDays) 1. 参数校验userId、bookId必须大于0borrowDays在1~60之间否则返回参数错误码 2. 查询用户信息 如果用户不存在或状态为禁用返回用户不可借阅 如果用户存在逾期未还记录提示存在逾期请先处理再借阅 3. 查询图书信息 如果图书不存在或库存stock0返回图书库存不足 4. 开启数据库事务 5. 条件更新库存 UPDATE book SET stock stock - 1 WHERE id ? AND stock 0 如果受影响行数为0回滚事务返回图书库存不足 6. 插入借阅记录 INSERT INTO borrow_record(user_id, book_id, borrow_time, due_time, status) 借出时间当前时间应还时间当前时间borrowDays天 7. 提交事务返回借阅记录ID注意第5步的写法用条件更新stock 0而不是先查后改这是防止并发超卖的关键。如果你只是写判断库存大于0然后扣减漏掉了条件更新这一层说明你没考虑并发场景。把这些细节写进详细设计里含金量立刻就不一样了。再提一下热词里出现的floyed算法类似的算法。Floyd算法是图论里求多源最短路径的经典算法动态规划思想三层循环时间复杂度O(n^3)。在详细设计阶段遇到类似课程依赖关系分析这类图论问题时你就需要在文档里写清楚算法选型的权衡数据规模小几十门课用邻接矩阵Floyd完全够用如果课程数量上千就要考虑DFSBFS或稀疏图优化。详细设计文档的价值就在于把这个为什么选这个算法的思考过程留下来而不是只在代码里写个函数名。4.3 详细设计用什么工具表达流程图、N-S图还是伪代码详细设计阶段的表达工具常用的有这几种程序流程图、N-S图盒图、PAD图、PDL伪代码。我按实际使用频率说下体会。程序流程图最通用任何编程背景的人都能看懂。但复杂的判断逻辑画出来容易乱改起来更麻烦。适合流程分支不多、循环不嵌套太深的场景。N-S图把所有逻辑限制在一个大方框里结构性强特别适合表达嵌套层次多的逻辑。缺点是画起来麻烦一旦逻辑改一点整个盒子都要重画。PDL伪代码我最推荐在课程设计里用因为它写起来快、改起来容易而且和真实代码几乎一一对应编码时可以翻译过去。用伪代码有个重要原则不要直接用某种编程语言的真实语法。你写遍历借阅记录列表对每条记录执行以下操作而不是for i in range(len(list)):。伪代码是给人看的不是给机器跑的它表达的是思路不用拘泥语法。太像代码的伪代码既没有设计文档该有的抽象层级也会因为语法细节干扰阅读。此外如果项目用了面向对象方法详细设计阶段最好画出关键类的类图。类的属性和方法签名这时候已经能定下来了。类图要标清楚属性类型、方法签名、类之间的关系聚合、组合、继承、依赖。只画一个框写个类名等于没画。5. 完整案例图书管理系统从总体到详细的设计过程5.1 案例背景与需求用一个贯穿始终的例子把三个设计阶段串起来。假设这是某高校软件工程课程设计题目实现一个图书管理系统管理员可以管理图书和用户用户可以检索图书、借书、还书系统能统计借阅排行逾期需要提醒。技术栈自选开发周期约4~6周小组3~4人。拿到题目第一步并不是画图而是先做需求分析。既然这里讲设计我默认需求分析已完成——用例图、数据流图都画好了。设计阶段怎么走5.2 总体设计怎么落地先定架构风格。这个系统用户量不会太大课程设计规模没必要搞分布式我选择分层架构表现层Web前端页面用Vue或服务端渲染模板都行业务层用户管理、图书管理、借阅管理、统计报表数据层MySQL存储核心数据Redis做可选缓存登录会话、热门图书部署应用服务器 数据库服务器课程设计可以合在一台机器文档里注明为节省成本合并部署总体架构图按浏览器 → 表现层 → 业务层 → 数据层的方向画每层框里列出主要组件图下方标注运行环境。特别要写一段架构选择理由这在答辩时非常有用系统规模小、并发量低、团队4人分层架构在开发难度、测试维护成本上最优微服务引入了服务发现、配置中心、链路追踪等复杂度对本项目是负担而非价值。这段话说出来老师就知道你不是随便抄了个三层架构而是真的做过选择。5.3 概要设计怎么落地把业务层四个模块分别拆开。以借阅管理模块为例它的职责包括借书、还书、续借、查询借阅记录、处理逾期。模块内部再拆成子功能同时先定义与外部模块的接口与用户模块的接口getUserById(userId)、checkUserStatus(userId)与图书模块的接口getBookInfo(bookId)、reduceStock(bookId)、increaseStock(bookId)与统计模块的接口dailyBorrowStats(date)然后画出借阅管理模块的SC图主模块借阅管理下面是处理借书请求处理还书请求处理续借请求逾期检查查询借阅记录几个子模块箭头上标清传递的数据。数据库设计在概要设计阶段做到ER图级别列出核心实体和关系。关键点是外键关系怎么表达用户和借阅记录一对多、图书和借阅记录一对多、分类和图书一对多。同时可以考虑逻辑外键和物理外键的取舍——我的建议是逻辑外键优先保证代码层的完整性校验物理外键在数据量不大时可以加数据量大时再加会影响插入性能。这个细节也写进文档又能加一分。5.4 详细设计怎么落地以处理借书请求为例详细设计做到什么程度。先用伪代码描述完整流程参考4.2节的库存扣减流程再补充异常场景用户被禁用怎么办图书状态异常怎么办同一个用户并发借同一本书怎么办然后是类图设计。BorrowService类的方法签名写清楚class BorrowService { BorrowResult borrow(int userId, int bookId, int borrowDays); BorrowResult renew(int borrowRecordId, int extraDays); BorrowResult returnBook(int borrowRecordId); ListBorrowRecordVO queryByUser(int userId, int page, int size); ListOverdueRecord checkOverdue(); }BorrowRepository类负责数据库操作BorrowRecord是实体类。类与类之间的关系在类图上标注清楚。还要设计一个细节还书时怎么判断是否逾期。可以在还书函数里判断return_time due_time如果逾期计算逾期天数并生成一条逾期记录。这个逻辑虽然简单你也要在详细设计里写出来不能留到编码时到时候再说。把边界条件和实现方案都定好编码就是纯粹的翻译工作而且每个人都按同一份设计写风格一致联调不打架。6. 常见问题与排查技巧实录6.1 高频问题速查表这些年评审和指导学生设计文档我总结了一些高频问题做成一张速查表方便你写完文档后自己检查问题现象原因解决方法设计图画成了功能菜单架构图上并列一堆XX管理把功能当模块没做抽象分层先分层再列模块按职责划分三个设计层次内容重叠总体设计和概要设计写得差不多没理解各阶段服务对象按给谁看控制内容粒度接口只有名字没有签名接口部分写了用户接口三个字不知道接口要做到多细至少写输入、输出、异常详细设计贴代码文档里直接贴大段真实代码不明白文档和代码的边界用伪代码关键类图表达看不到设计理由只写采用三层架构没有下文缺乏设计决策论证意识每个关键选择后加一段因为数据库只有表字段没有关系列了表结构没提表怎么关联忽略数据建模的整体性画ER图或在文档中标注关系图图不一致架构图模块名和SC图对不上反复修改但没同步更新文档改设计时先改图再改文字6.2 几个没人明说但很实用的经验第一文档里留设计演进记录。有些同学设计文档写得四平八稳但答辩时被问到你中途改过什么设计为什么改就哑了。实际上开发过程中发现原来的模块划分不合理、表结构要加字段这些都是很正常的事。把这些演进过程记在文档里比如在文档末尾加一节设计变更记录反而比一个完美的设计更能体现工程素养。设计从来不是一次到位的记录变更就是记录你的思考。第二技术栈要和你写进文档的东西匹配。你如果用Python写项目总体设计里就不要写基于Java Spring Boot。否则要么代码和文档对不上要么老师一眼看出来是抄的。Python完全可以用分层架构、模块化设计来完成课程设计伪代码和类图同样适用于Python项目。第三画图之前先画草图。先在纸上或者白板上把模块、接口、流程用草图画一遍确认逻辑通顺再用工具做成正式图。直接开着绘图软件边想边画很容易画出一堆废图改来改去还浪费时间。草图阶段改成本最低正式图阶段每改一次都要重新对齐图例和排版。第四找个同学帮你干读测试。把设计文档给对方让他只看文档不讨论在脑内把整个系统模拟实现一遍。如果他在某个模块的接口处卡住了说明你的接口设计还有歧义如果他在某个流程上问传一个负数会怎样说明你的异常设计还不完整。这个测试不需要对方懂全部技术细节反而是不熟悉的人更容易发现逻辑漏洞。第五设计文档写完不等于设计完。编码过程中遇到设计不合理的地方要及时回改文档。很多团队的文档最后和代码脱节就是因为改代码容易改文档麻烦。你在课程设计里养成改代码就同步改文档的习惯对以后进企业做工程非常有帮助这也是一种职业素养。我个人的体会是软件工程设计图的三个层次说到底是在回答三个问题系统被切成了几块块和块之间怎么配合每一块内部是怎么工作的抓住这条主线设计文档就不会写成流水账画出来的图也经得起追问。很多同学低估了设计阶段的价值觉得反正代码都要写为什么不直接写。但你要是亲手把从总体到详细的设计流程完整走一遍会发现对项目的理解层次完全不一样——你不再是写代码的人而是做设计的人。这个转变恰恰是软件工程这门课真正想教给你的东西。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价