📄 一句话概括
面对大系统无从下手?设计的本质是把大问题逐层拆小——系统拆成子系统、子系统拆成模块、模块拆成函数,拆到每块都能独立完成。
📝 本节和前面几节的关系
内部设计阶段的核心动作只有两个字:拆解。本节看这一招怎么把庞然大物变成可施工的小块。
一、为什么必须拆
【图书管理系统】一句话说不清也做不完——大问题的复杂度超出任何人的脑容量; 拆解后每块都小得能独立完成、独立测试——复杂度被切成可管理的小片; 分而治之是人类对付复杂性的通用武器,第五章的算法、第六章的数据结构都是它的具体形态。
二、拆的三层
第一层:系统 → 子系统(按业务职能切,如借阅/检索); 第二层:子系统 → 模块(按功能切,如借书/还书); 第三层:模块 → 函数/类(按动作切,如校验读者、扣减库存); 拆到什么程度算到位?——每个叶子都能一个人在几天内独立做完并测好。
三、拆解的两条纪律
高内聚:一块只干一件事,相关的都聚在一起; 低耦合:块与块之间接口清清楚楚,改动互不牵连; 这两条纪律直通下一节的面向对象——类与组件就是【拆解结果】的最佳容器。
四、动手 Demo:把系统拆到函数级
用一棵拆解树把【图书管理系统】逐层拆到函数级,数一数叶子任务有几块。
tree = {"图书管理系统": {
"借阅子系统": {"借书模块": ["校验读者", "扣减库存"],
"还书模块": ["计算罚金", "恢复库存"]},
"检索子系统": {"搜索模块": ["按书名", "按作者"]}}}
def count_leaves(node):
if isinstance(node, list):
return len(node)
if isinstance(node, dict):
return sum(count_leaves(v) for v in node.values())
return 1
print("叶子任务:", count_leaves(tree))
实跑输出:
--------------------------------------------------------------------
所谓设计,就是拆解
--------------------------------------------------------------------
面对【图书管理系统】这种大题目, 设计师做的第一件事是【拆】:
拆成子系统, 子系统拆成模块, 模块拆成函数——拆到每块都小得能独立做完:
[拆解树]
图书管理系统
借阅子系统
借书模块
- 校验读者
- 扣减库存
还书模块
- 计算罚金
- 恢复库存
检索子系统
搜索模块
- 按书名
- 按作者
拆到底的叶子(函数级任务)有 6 个——每个都能一个人几天做完。
大问题拆小 + 分块落实 + 拼回整体 = 设计的本质。第七章的面向对象
组件化, 正是【拆解】思想在编程层面的落地。
递归计数得 6——四个借阅动作加两个检索维度,每块都是【一人几天】的粒度。 拆解树的每一层都该能回答【这块归谁、接口是什么】——答不出就是拆得不到位。
30 秒实验
- 把【亮化工程图纸管理系统】拆到函数级,画出自己的拆解树。
- 用高内聚低耦合各检查一条自己拆出的边界,说明合不合格。
常见误区
- 以为设计是【画界面】——画界面只是外部设计一角,设计的主体是拆解。
- 以为拆得越细越好——过细会让接口数爆炸,耦合反而升高,拆到【一人几天】即止。
自测三问(点开对答案)
1. 设计的本质动作? —— 拆解——系统→子系统→模块→函数,拆到可独立完成。 2. 拆到什么粒度算到位? —— 每个叶子能一个人几天内做完并测好。 3. 拆解的两条纪律? —— 高内聚(块内相关)、低耦合(块间清晰)。- ☐ 下一节(12.6 面向对象法简化了系统维护工作)
相关笔记
- 要点7:先在纸上考虑算法 — 算法层面的【先想清楚再动手】
- 观点1:面向对象编程通过把组件拼装到一起构建程序 — 拆解结果的编程容器
- 💻 计算机是怎样跑起来的 · 索引