第2章:深模块(Deep Modules)
一、导读
1.1 本章学习目标
第2章讲解 Ousterhout 最核心的概念——深模块。模块的深度是接口简单性与功能强大性的比值。
本章的核心学习目标包括:
- 理解深模块和浅模块的概念
- 掌握接口与实现的分离
- 学会评估模块的深度
- 理解抽象层次的重要性
1.2 为什么本章如此重要
模块是软件设计的基本单位。深模块用最简单的接口提供最大的功能——这是软件设计的核心目标。Unix 的设计哲学就是深模块的典范。
1.3 核心问题引导
什么是深模块?什么是浅模块?
如何衡量一个模块的深度?
接口和实现应该如何分离?
为什么 Unix 是深模块的典范?
二、核心概念详解
2.1 深模块 vs 浅模块
模块的深度 = 功能 / 接口复杂度
深模块:
- 接口简单
- 功能强大
- 例:Unix 文件 I/O
open(), read(), write(), close()
4个方法,可以操作任何设备
浅模块:
- 接口复杂
- 功能有限
- 例:一个类有20个方法,每个方法只做一件简单的事
功能
↑
深 │ ████████
模 │ ████████
块 │ ████████
│ ████████
├──────────→ 接口
浅 │ ██
模 │ ██
块 │ ██2.2 接口与实现
接口(Interface):
- 模块对外暴露的部分
- 用户需要知道的
- 应该尽可能简单
实现(Implementation):
- 模块内部的逻辑
- 用户不需要知道的
- 可以很复杂
好的设计:
- 简单的接口
- 复杂的实现
- 接口和实现之间有巨大的信息鸿沟
例:Java 的 HashMap
- 接口:put(), get(), remove(), size()
- 实现:哈希函数、冲突解决、动态扩容
- 用户不需要知道内部如何工作2.3 抽象层次
每个模块应该在一个抽象层次上工作
不好的设计:
public void processOrder(Order order) {
// 混合了不同抽象层次
validateEmail(order.getEmail()); // 低层
order.setStatus(CONFIRMED); // 高层
byte[] data = order.toBytes(); // 低层
socket.write(data); // 低层
}
好的设计:
public void processOrder(Order order) {
validate(order); // 一个抽象层次
confirm(order); // 一个抽象层次
ship(order); // 一个抽象层次
}
// 低层细节在各自的方法中2.4 Unix 的深模块
Unix 的设计哲学:
1. 文件 I/O
- 接口:open, read, write, close
- 功能:操作任何设备(文件、管道、socket、终端)
- 深度:极大
2. 进程管理
- 接口:fork, exec, wait, exit
- 功能:创建和管理任何进程
- 深度:极大
3. 文本处理
- 接口:管道 + 标准输入输出
- 功能:组合任意文本处理工具
- 深度:极大
Unix 的教训:
- 少量深模块 > 大量浅模块
- 简单的接口 + 强大的功能
- 模块可以组合使用三、实战案例
3.1 案例一:设计深模块
java
// 浅模块:接口复杂,功能有限
public class UserValidator {
public boolean isValidEmail(String email) { ... }
public boolean isValidName(String name) { ... }
public boolean isValidAge(int age) { ... }
public boolean isValidPhone(String phone) { ... }
// 20 个验证方法...
}
// 深模块:接口简单,功能强大
public class Validator {
// 一个方法,验证整个对象
public ValidationResult validate(Object obj) {
// 内部使用反射、注解等复杂机制
// 用户不需要知道细节
}
}
// 使用
ValidationResult result = validator.validate(user);
if (!result.isValid()) {
result.getErrors().forEach(System.out::println);
}四、本章小结
深模块:简单接口 + 强大功能。
浅模块:复杂接口 + 有限功能。
接口与实现:简单接口,复杂实现,信息鸿沟。
抽象层次:每个模块在一个抽象层次上工作。
五、思考与练习
在你的代码中找出一个浅模块,如何让它变深?
Unix 的哪些设计体现了深模块的思想?
如何衡量一个模块的深度?