03 · 软件设计(Software Design)

📅 预计 45 分钟 | ⭐ = 核心概念 | 📌 中英术语见文末
✍️ 配套练习:课程中心「软件工程」模块在线测验


3.1 设计是"画图纸",不是"砌墙"

先有蓝图,再施工

盖楼时,没人直接拎着砖头开工。得先有建筑方案(几层、几间、什么风格),再有施工图(每堵墙多厚、每根钢筋怎么放),工人才照图施工。软件设计就是软件工程的"画图纸"阶段:把需求(要什么)翻译成方案(怎么做),让编码阶段有据可依。

设计得不好,后果是灾难性的:结构像一坨纠缠的毛线,加一个功能要改十个文件,测试无从下手,维护的人想哭。

设计要回答的两个层次问题 ⭐:

层次 关心什么 类比
概要设计(architecture) 系统由哪些模块组成、模块之间如何联系 小区规划:几栋楼、在哪、怎么连通
详细设计(detail) 每个模块内部怎么实现、算法与数据结构 每户装修:插座在哪、水管怎么走

💡 记忆口诀:概要 = 系统骨架(分模块、画接口),详细 = 血肉(写算法、定结构)。

⚠️ 常见错误

  1. 跳过设计直接编码:需求一清楚就上手敲代码,等于边盖边画图,后期必返工。
  2. 把"设计"理解成"画流程图":设计涵盖架构、模块划分、接口、数据结构、算法等多个层面。

3.2 概要设计与详细设计:从骨架到血肉

概要设计:决定系统的"器官"和"血管"

概要设计(也叫体系结构设计/architectural design)把系统拆成若干模块,并定义模块之间的接口关系。核心任务是:

  • 体系结构设计:选择架构风格(分层架构、MVC、客户端-服务器、微服务等),画出系统的顶层结构。
  • 模块划分:把大系统分解为高内聚、低耦合的模块集合。
  • 接口设计:明确模块之间传递什么数据、调用什么方法。

以图书管理系统为例,概要设计会把系统分成:界面模块、借还书模块、图书查询模块、数据库访问模块、权限管理模块,并约定各模块的调用关系。

常见的体系结构风格 ⭐:

风格 结构 典型例子
分层架构 自上而下分层,每层只调用下一层 界面层 → 业务层 → 数据访问层
MVC 模型(数据)/ 视图(界面)/ 控制器(逻辑)分离 Web 应用、桌面应用
客户端-服务器 客户端请求、服务器响应 浏览器 + Web 服务器
微服务 系统拆成独立部署的小服务,通过接口通信 大型互联网平台

MVC 最值得记住:Model 管数据和业务规则,View 管界面显示,Controller 接收用户操作并协调 M 与 V。三者分离的好处是改动界面不影响业务逻辑,改动数据模型不影响界面——这是"高内聚、低耦合"在架构层的体现。

详细设计:把每个模块"写明白"

详细设计针对每个模块内部,确定:

  • 数据结构:用什么结构存数据(数组、链表、哈希表、对象等)。
  • 算法:关键功能的处理流程(排序、查找、状态转换逻辑)。
  • 模块内部流程:通常用流程图伪代码表达,可直接翻译成代码。

比如"借书模块"的详细设计会写清楚:校验读者身份 → 检查借阅上限 → 登记借阅记录 → 更新库存的完整流程与异常处理。

通俗理解:概要设计决定"房子分几间、门开在哪",详细设计决定"每间屋的家具怎么摆"。

⚠️ 常见错误

  1. 把详细设计的流程图画成需求阶段的业务流程图:需求图描述"业务的步骤",设计图描述"软件的流程",视角不同。
  2. 只做概要不做详细:模块接口定了,内部怎么做不写,编码时各自为政,接口必然对不上。

3.3 模块化设计:搭积木的艺术 ⭐

模块 = 可以独立开发、测试、替换的"积木"

模块化(modularity)是把软件分割成若干相对独立、职责单一的模块,像搭积木一样组合成完整系统。模块化带来的三大好处:可维护(改一处不影响全局)、可复用(一个模块多处用)、可并行开发(多人各搭各的积木)。

模块化设计的三条基本原则 ⭐:

原则 含义 类比
分解(decomposition) 大问题拆成小问题,逐层细化 整栋楼拆成楼层→房间→家具
抽象(abstraction) 只暴露"做什么"的接口,隐藏"怎么做"的细节 微波炉只有几个按键,内部电路你不用懂
信息隐藏(information hiding) 模块的内部实现对外保密,只通过接口交互 银行 ATM 只给取款入口,不给你看金库

接口(interface)是模块对外开放的唯一窗口。只要接口不变,模块内部怎么改都不影响外部调用者——这就是信息隐藏带来的可维护性

⚠️ 常见错误

  1. 模块划分越细越好:模块太小会接口泛滥、通信成本飙升;目标是"内聚高 + 耦合低",不是数量多。
  2. 把信息隐藏理解成"封装成类就行":信息隐藏强调内部细节对外不可见,仅通过接口通信,否则改内部实现会牵连调用方。

3.4 耦合与内聚:设计的"体检指标" ⭐⭐

内聚要高,耦合要低——软件设计最重要的两句话

内聚(cohesion)衡量一个模块内部各成分联系得有多紧密——模块内元素是不是都围绕同一个职责。

耦合(coupling)衡量模块与模块之间的联系程度——两个模块依赖得多深。

设计目标就一句话:高内聚、低耦合(high cohesion, low coupling)。

内聚从低到高的几种类型(记几种典型的即可):

类型 特点 评价
偶然内聚 元素只是恰好放在一起,无关联 最低,应避免
逻辑内聚 按"类别"聚在一起(一堆输入操作) 较低
时间内聚 因为"同一时间执行"聚在一起
过程内聚 按处理顺序组合
通信内聚 操作同一数据而聚在一起 较高
功能内聚 所有元素共同完成一个明确功能 最高,最优

耦合从低到高的常见类型:

类型 特点 评价
数据耦合 只通过参数传数据 最理想
标记耦合 传递数据结构(如整个对象)
控制耦合 传递控制信号控制对方逻辑 中,需谨慎
公共耦合 共享全局数据区 高,应避免
内容耦合 直接访问/修改对方内部 最高,坚决避免

💡 记忆口诀:内聚像"拧成一股绳"(越高越好),耦合像"互相拉扯"(越低越好)。功能内聚最优,数据耦合最理想;内容耦合最差。

⚠️ 常见错误

  1. 把"高内聚"和"低耦合"对应反了:内聚看模块内部紧不紧,耦合看模块之间缠不缠。内聚要,耦合要
  2. 记混耦合类型:数据耦合(传值)最低最优,内容耦合(动别人内部)最高最差;控制耦合传的是"控制信号",公共耦合共享全局。
  3. 以为只有"低内聚"才错:内聚过高也可能导致模块太大难维护,但考试与工程首要原则仍是"高内聚低耦合"。

设计评审:写代码前的"图纸会审"

设计完成不等于可以直接编码。工程上要开设计评审(design review),由同行和干系人检查:设计是否覆盖全部需求、模块划分是否合理、接口是否清晰、是否便于测试与维护。评审的目的不是找茬,而是把设计阶段的错误拦在编码之前——设计错了返工成本是编码阶段的数倍。评审通过后,设计文档被冻结为基线,后续改动走变更控制流程。


3.5 常用 UML 图:设计的"通用语言"

UML 是画设计图的"普通话"

UML(Unified Modeling Language,统一建模语言)是软件工程用来描述系统结构、行为的标准化图形语言。需求阶段用用例图(见第 2 讲),设计阶段最常用下面几种 ⭐:

静态/动态 描述什么 关键要素
类图 class diagram 静态 类的属性、方法及类之间关系 类、关联/聚合/组合/继承/依赖
时序图 sequence diagram 动态 对象间按时间的消息传递顺序 生命线、激活条、消息箭头
状态图 state diagram 动态 单个对象的生命周期状态转换 状态、事件、迁移
活动图 activity diagram 动态 业务流程/算法的控制流 动作节点、判断、泳道

类图是设计阶段最重要的图:一个类画成三格矩形(类名 / 属性 / 方法),类间关系有——关联(实线,一类知道另一类)、聚合(菱形空心,整体与部分可分离,如"班级—学生")、组合(菱形实心,部分随整体存亡,如"订单—订单项")、继承(空心箭头,父子类)、依赖(虚线箭头,临时使用)。

时序图重点表达"谁先调用谁、按什么顺序",适合描述一个用例内部对象间的交互过程。

状态图适合表达有明确状态变化的对象,比如订单(待付款→已付款→已发货→已完成)的状态机。

一句话记忆:类图管结构,时序图管顺序,状态图管状态,活动图管流程

⚠️ 常见错误

  1. 混淆聚合与组合:聚合 = 部分可独立存在(空心菱形);组合 = 部分与整体同生共死(实心菱形)。
  2. 把时序图当类图画:时序图强调的是"时间顺序 + 消息",不是结构关系。
  3. 状态图里乱画分支:状态图强调"状态 + 事件触发迁移",分支流程应交给活动图。

📌 双语术语表(本讲)

中文 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 流程

⭐ 本讲考点清单

  1. 概要设计定"骨架"(模块划分 + 接口),详细设计定"血肉"(数据结构 + 算法)。
  2. 模块化三原则:分解、抽象、信息隐藏。
  3. 设计最高原则:高内聚、低耦合
  4. 内聚从低到高,功能内聚最优;耦合从低到高,数据耦合最优、内容耦合最差。
  5. 聚合(空心菱形,可分离)vs 组合(实心菱形,同生共死)。
  6. 四张图各管一事:类图结构、时序图顺序、状态图状态、活动图流程。