3A Philosophy of Software Design

信息隐藏

信息泄漏

信息隐藏信息泄漏时间分解分层设计

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第3章:信息隐藏(Information Hiding)

一、导读

1.1 本章学习目标

第3章讲解信息隐藏——深模块的实现策略。每个模块应该封装一些知识,不让其他模块知道。

本章的核心学习目标包括:

  • 理解信息隐藏的核心思想
  • 掌握信息泄漏的识别
  • 学会时间分解(Temporal Decomposition)
  • 理解分层设计的本质

1.2 为什么本章如此重要

信息隐藏是模块化的基础。如果所有模块都知道所有事情,修改一个地方就需要修改所有地方。信息隐藏让变更局部化。

1.3 核心问题引导

信息隐藏的核心思想是什么?

什么是信息泄漏?如何识别?

时间分解如何帮助信息隐藏?

分层设计和信息隐藏有什么关系?


二、核心概念详解

2.1 信息隐藏

信息隐藏:
每个模块封装一些知识,对外隐藏实现细节

例:一个类封装了"如何解析日期"的知识
- 用户只需要传入字符串
- 不需要知道内部使用什么格式
- 不需要知道如何处理时区

信息隐藏的好处:
1. 变更局部化:修改实现不影响用户
2. 降低认知负荷:用户不需要知道细节
3. 消除未知未知:接口明确定义了边界

2.2 信息泄漏

信息泄漏:
模块的实现细节泄漏到了接口中

例1:暴露内部数据结构
public class Stack {
    public List<Object> items;    // 泄漏了内部用 List 实现
}

// 应该隐藏实现
public class Stack {
    public void push(Object item) { ... }
    public Object pop() { ... }
    // 用户不知道内部用什么数据结构
}

例2:泄漏性能特征
public void process(List<Item> items) {
    // 如果文档说"这个方法会修改传入的列表"
    // 就泄漏了实现细节
}

信息泄漏的信号:
- 接口注释提到了实现细节
- 用户需要知道内部工作方式
- 修改实现需要修改用户代码

2.3 时间分解

时间分解:
将操作按时间顺序分解为独立的步骤

例:HTTP 请求处理
// 不好的设计:一个方法做所有事
public void handleRequest(Request req, Response res) {
    // 解析请求
    // 验证权限
    // 路由到处理器
    // 执行业务逻辑
    // 序列化响应
    // 发送响应
}

// 好的设计:按时间分解
public void handleRequest(Request req, Response res) {
    ParsedRequest parsed = parse(req);
    AuthResult auth = authenticate(parsed);
    Handler handler = route(parsed);
    Object result = handler.handle(parsed, auth);
    send(res, serialize(result));
}

// 每个方法封装一个时间步骤的知识

2.4 分层设计

分层:
每一层为上层提供抽象,隐藏下层的细节

    应用层(业务逻辑)
        ↓ 使用
    服务层(领域服务)
        ↓ 使用
    数据层(持久化)
        ↓ 使用
    基础设施层(数据库驱动)

每层只与相邻层交互
每层隐藏下层的细节
上层不需要知道下层如何实现

分层 vs 信息隐藏:
- 信息隐藏是目标
- 分层是实现信息隐藏的手段

三、实战案例

3.1 案例一:修复信息泄漏

java
// 信息泄漏的版本
public class OrderService {
    private JdbcTemplate jdbc;    // 泄漏了使用 JDBC
    
    public Order findById(long id) {
        // 用户知道用了 JDBC
        return jdbc.queryForObject(
            "SELECT * FROM orders WHERE id = ?",
            new Object[]{id},
            new OrderMapper()
        );
    }
}

// 修复:隐藏实现
public class OrderRepository {
    // 接口不暴露实现
    public Order findById(OrderId id) {
        // 内部可以使用 JDBC、JPA、MongoDB...
        // 用户不需要知道
    }
}

// 用户代码
Order order = orderRepository.findById(orderId);
// 不需要知道底层用了什么

四、本章小结

信息隐藏:封装知识,隐藏实现细节。

信息泄漏:实现细节泄漏到接口中。

时间分解:按时间步骤分解操作。

分层设计:每层隐藏下层细节。


五、思考与练习

在你的代码中找出一个信息泄漏的例子。

如何用时间分解改善一个过长的方法?

信息隐藏和封装有什么区别?


3/7信息隐藏
0%