SE-03 软件设计
03 · 软件设计(Software Design)
📅 预计 45 分钟 | ⭐ = 核心概念 | 📌 中英术语见文末
✍️ 配套练习:课程中心「软件工程」模块在线测验
3.1 设计是"画图纸",不是"砌墙"
先有蓝图,再施工
盖楼时,没人直接拎着砖头开工。得先有建筑方案(几层、几间、什么风格),再有施工图(每堵墙多厚、每根钢筋怎么放),工人才照图施工。软件设计就是软件工程的"画图纸"阶段:把需求(要什么)翻译成方案(怎么做),让编码阶段有据可依。
设计得不好,后果是灾难性的:结构像一坨纠缠的毛线,加一个功能要改十个文件,测试无从下手,维护的人想哭。
设计要回答的两个层次问题 ⭐:
| 层次 | 关心什么 | 类比 |
|---|---|---|
| 概要设计(architecture) | 系统由哪些模块组成、模块之间如何联系 | 小区规划:几栋楼、在哪、怎么连通 |
| 详细设计(detail) | 每个模块内部怎么实现、算法与数据结构 | 每户装修:插座在哪、水管怎么走 |
💡 记忆口诀:概要 = 系统骨架(分模块、画接口),详细 = 血肉(写算法、定结构)。
⚠️ 常见错误
- 跳过设计直接编码:需求一清楚就上手敲代码,等于边盖边画图,后期必返工。
- 把"设计"理解成"画流程图":设计涵盖架构、模块划分、接口、数据结构、算法等多个层面。
3.2 概要设计与详细设计:从骨架到血肉
概要设计:决定系统的"器官"和"血管"
概要设计(也叫体系结构设计/architectural design)把系统拆成若干模块,并定义模块之间的接口关系。核心任务是:
- 体系结构设计:选择架构风格(分层架构、MVC、客户端-服务器、微服务等),画出系统的顶层结构。
- 模块划分:把大系统分解为高内聚、低耦合的模块集合。
- 接口设计:明确模块之间传递什么数据、调用什么方法。
以图书管理系统为例,概要设计会把系统分成:界面模块、借还书模块、图书查询模块、数据库访问模块、权限管理模块,并约定各模块的调用关系。
常见的体系结构风格 ⭐:
| 风格 | 结构 | 典型例子 |
|---|---|---|
| 分层架构 | 自上而下分层,每层只调用下一层 | 界面层 → 业务层 → 数据访问层 |
| MVC | 模型(数据)/ 视图(界面)/ 控制器(逻辑)分离 | Web 应用、桌面应用 |
| 客户端-服务器 | 客户端请求、服务器响应 | 浏览器 + Web 服务器 |
| 微服务 | 系统拆成独立部署的小服务,通过接口通信 | 大型互联网平台 |
MVC 最值得记住:Model 管数据和业务规则,View 管界面显示,Controller 接收用户操作并协调 M 与 V。三者分离的好处是改动界面不影响业务逻辑,改动数据模型不影响界面——这是"高内聚、低耦合"在架构层的体现。
详细设计:把每个模块"写明白"
详细设计针对每个模块内部,确定:
- 数据结构:用什么结构存数据(数组、链表、哈希表、对象等)。
- 算法:关键功能的处理流程(排序、查找、状态转换逻辑)。
- 模块内部流程:通常用流程图或伪代码表达,可直接翻译成代码。
比如"借书模块"的详细设计会写清楚:校验读者身份 → 检查借阅上限 → 登记借阅记录 → 更新库存的完整流程与异常处理。
通俗理解:概要设计决定"房子分几间、门开在哪",详细设计决定"每间屋的家具怎么摆"。
⚠️ 常见错误
- 把详细设计的流程图画成需求阶段的业务流程图:需求图描述"业务的步骤",设计图描述"软件的流程",视角不同。
- 只做概要不做详细:模块接口定了,内部怎么做不写,编码时各自为政,接口必然对不上。
3.3 模块化设计:搭积木的艺术 ⭐
模块 = 可以独立开发、测试、替换的"积木"
模块化(modularity)是把软件分割成若干相对独立、职责单一的模块,像搭积木一样组合成完整系统。模块化带来的三大好处:可维护(改一处不影响全局)、可复用(一个模块多处用)、可并行开发(多人各搭各的积木)。
模块化设计的三条基本原则 ⭐:
| 原则 | 含义 | 类比 |
|---|---|---|
| 分解(decomposition) | 大问题拆成小问题,逐层细化 | 整栋楼拆成楼层→房间→家具 |
| 抽象(abstraction) | 只暴露"做什么"的接口,隐藏"怎么做"的细节 | 微波炉只有几个按键,内部电路你不用懂 |
| 信息隐藏(information hiding) | 模块的内部实现对外保密,只通过接口交互 | 银行 ATM 只给取款入口,不给你看金库 |
接口(interface)是模块对外开放的唯一窗口。只要接口不变,模块内部怎么改都不影响外部调用者——这就是信息隐藏带来的可维护性。
⚠️ 常见错误
- 模块划分越细越好:模块太小会接口泛滥、通信成本飙升;目标是"内聚高 + 耦合低",不是数量多。
- 把信息隐藏理解成"封装成类就行":信息隐藏强调内部细节对外不可见,仅通过接口通信,否则改内部实现会牵连调用方。
3.4 耦合与内聚:设计的"体检指标" ⭐⭐
内聚要高,耦合要低——软件设计最重要的两句话
内聚(cohesion)衡量一个模块内部各成分联系得有多紧密——模块内元素是不是都围绕同一个职责。
耦合(coupling)衡量模块与模块之间的联系程度——两个模块依赖得多深。
设计目标就一句话:高内聚、低耦合(high cohesion, low coupling)。
内聚从低到高的几种类型(记几种典型的即可):
| 类型 | 特点 | 评价 |
|---|---|---|
| 偶然内聚 | 元素只是恰好放在一起,无关联 | 最低,应避免 |
| 逻辑内聚 | 按"类别"聚在一起(一堆输入操作) | 较低 |
| 时间内聚 | 因为"同一时间执行"聚在一起 | 中 |
| 过程内聚 | 按处理顺序组合 | 中 |
| 通信内聚 | 操作同一数据而聚在一起 | 较高 |
| 功能内聚 | 所有元素共同完成一个明确功能 | 最高,最优 |
耦合从低到高的常见类型:
| 类型 | 特点 | 评价 |
|---|---|---|
| 数据耦合 | 只通过参数传数据 | 最理想 |
| 标记耦合 | 传递数据结构(如整个对象) | 中 |
| 控制耦合 | 传递控制信号控制对方逻辑 | 中,需谨慎 |
| 公共耦合 | 共享全局数据区 | 高,应避免 |
| 内容耦合 | 直接访问/修改对方内部 | 最高,坚决避免 |
💡 记忆口诀:内聚像"拧成一股绳"(越高越好),耦合像"互相拉扯"(越低越好)。功能内聚最优,数据耦合最理想;内容耦合最差。
⚠️ 常见错误
- 把"高内聚"和"低耦合"对应反了:内聚看模块内部紧不紧,耦合看模块之间缠不缠。内聚要高,耦合要低。
- 记混耦合类型:数据耦合(传值)最低最优,内容耦合(动别人内部)最高最差;控制耦合传的是"控制信号",公共耦合共享全局。
- 以为只有"低内聚"才错:内聚过高也可能导致模块太大难维护,但考试与工程首要原则仍是"高内聚低耦合"。
设计评审:写代码前的"图纸会审"
设计完成不等于可以直接编码。工程上要开设计评审(design review),由同行和干系人检查:设计是否覆盖全部需求、模块划分是否合理、接口是否清晰、是否便于测试与维护。评审的目的不是找茬,而是把设计阶段的错误拦在编码之前——设计错了返工成本是编码阶段的数倍。评审通过后,设计文档被冻结为基线,后续改动走变更控制流程。
3.5 常用 UML 图:设计的"通用语言"
UML 是画设计图的"普通话"
UML(Unified Modeling Language,统一建模语言)是软件工程用来描述系统结构、行为的标准化图形语言。需求阶段用用例图(见第 2 讲),设计阶段最常用下面几种 ⭐:
| 图 | 静态/动态 | 描述什么 | 关键要素 |
|---|---|---|---|
| 类图 class diagram | 静态 | 类的属性、方法及类之间关系 | 类、关联/聚合/组合/继承/依赖 |
| 时序图 sequence diagram | 动态 | 对象间按时间的消息传递顺序 | 生命线、激活条、消息箭头 |
| 状态图 state diagram | 动态 | 单个对象的生命周期状态转换 | 状态、事件、迁移 |
| 活动图 activity diagram | 动态 | 业务流程/算法的控制流 | 动作节点、判断、泳道 |
类图是设计阶段最重要的图:一个类画成三格矩形(类名 / 属性 / 方法),类间关系有——关联(实线,一类知道另一类)、聚合(菱形空心,整体与部分可分离,如"班级—学生")、组合(菱形实心,部分随整体存亡,如"订单—订单项")、继承(空心箭头,父子类)、依赖(虚线箭头,临时使用)。
时序图重点表达"谁先调用谁、按什么顺序",适合描述一个用例内部对象间的交互过程。
状态图适合表达有明确状态变化的对象,比如订单(待付款→已付款→已发货→已完成)的状态机。
一句话记忆:类图管结构,时序图管顺序,状态图管状态,活动图管流程。
⚠️ 常见错误
- 混淆聚合与组合:聚合 = 部分可独立存在(空心菱形);组合 = 部分与整体同生共死(实心菱形)。
- 把时序图当类图画:时序图强调的是"时间顺序 + 消息",不是结构关系。
- 状态图里乱画分支:状态图强调"状态 + 事件触发迁移",分支流程应交给活动图。
📌 双语术语表(本讲)
| 中文 | English | 记忆点 |
|---|---|---|
| 概要设计 | architectural design | 系统骨架/模块划分 |
| 详细设计 | detailed design | 模块内部实现 |
| 模块化 | modularity | 拆成积木 |
| 分解 | decomposition | 大拆小 |
| 抽象 | abstraction | 隐藏细节 |
| 信息隐藏 | information hiding | 只暴露接口 |
| 内聚 | cohesion | 模块内部紧不紧 |
| 耦合 | coupling | 模块之间缠不缠 |
| 数据耦合 | data coupling | 传值,最优 |
| 内容耦合 | content coupling | 动内部,最差 |
| 统一建模语言 | UML | 标准图形语言 |
| 类图 | class diagram | 结构 |
| 时序图 | sequence diagram | 顺序/消息 |
| 状态图 | state diagram | 状态迁移 |
| 活动图 | activity diagram | 流程 |
⭐ 本讲考点清单
- 概要设计定"骨架"(模块划分 + 接口),详细设计定"血肉"(数据结构 + 算法)。
- 模块化三原则:分解、抽象、信息隐藏。
- 设计最高原则:高内聚、低耦合。
- 内聚从低到高,功能内聚最优;耦合从低到高,数据耦合最优、内容耦合最差。
- 聚合(空心菱形,可分离)vs 组合(实心菱形,同生共死)。
- 四张图各管一事:类图结构、时序图顺序、状态图状态、活动图流程。