# 5.1 信息隐藏

实现深模块的最重要技术是信息隐藏（*information hiding*）。这种技术最早是由David Parnas（见注解）描述的。其基本思想是，每个模块应该封装一些知识，这些知识体现了设计决策。这些知识被嵌入到模块的实现中，但不出现在其接口中，所以它对其他模块是不可见的。

隐藏在模块中的信息通常包含有关如何实现某种机制的详细信息。 以下是一些可能隐藏在模块中的信息示例：

* 如何在B树中存储信息，以及如何有效地访问它。
* 如何识别文件中每个逻辑块对应的物理磁盘块。
* 如何实现 TCP 网络协议。
* 如何在多核处理器上调度线程。
* 如何解析 JSON 文档。

隐藏的信息包括与机制有关的数据结构和算法。它也可以包括更低层次的细节，如页的大小，还可以包括更抽象的更高层次概念，如大多数文件是小文件这一假设。

信息隐藏以两种方式降低复杂性。首先，它简化了一个模块的接口。接口反映了一个更简单、更抽象的模块功能视图，并隐藏了细节；这减少了使用该模块的开发人员的认知负荷。例如，使用B树类的开发者不需要担心树中节点的理想扇出或如何保持树的平衡。第二，信息隐藏使得系统的发展更加容易。如果某条信息被隐藏起来，那么在包含该信息的模块之外，就不存在对该信息的依赖性，所以与该信息相关的设计变更将只影响该模块。例如，如果TCP协议改变了（例如引入新的拥塞控制机制），协议的实现就必须修改，但使用TCP发送和接收数据的高层代码不应当需要改变。

当设计一个新的模块时，你应该仔细考虑哪些信息可以隐藏在该模块中。如果你能隐藏更多的信息，你也应该能简化模块的接口，这样就能使模块变得更深。

注意：在一个类中通过声明为`private`来隐藏变量和方法与信息隐藏不是一回事。私有元素可以帮助信息隐藏，因为它们使得这些项目无法从类外直接访问。然而，关于私有项目的信息仍然可以通过公共方法（如getter和setter方法）暴露出来。当这种情况发生时，变量的性质和用法就像变量是公共的一样被暴露出来。

最好的信息隐藏方式是当信息被完全隐藏在一个模块中时，这样对于模块的用户来说是不相关的，也是不可见的。然而，部分信息隐藏也有价值。例如，如果一个特定的功能或信息只被一个类的少数用户所需要，并且通过单独的方法来访问它，这样它在最常见的用例中是不可见的，那么这个信息多数情况下是隐藏的。比起对类的每个用户都可见的信息，这样的信息将会产生更少的依赖。

{% hint style="info" %}
注解：David Parnas, “On the Criteria to be Used in Decomposing Systems into Modules,” Communications of the ACM, December 1972.
{% endhint %}
