您希望您的代码由可以单独测试和理解的小块组成。
每个小块都应该做一件事并做好,无论那块是函数、方法还是类。
您希望能够从这些小块中组合出更大的功能块,这样每个组合物,无论内部多么复杂,在该功能的抽象级别上都保持简单。
换句话说,即使在高层次上,我们仍然应该能够用简单的外部来描述复杂的内部。
这就是 Andrew Koenig 所说的“抽象是选择性无知”的意思。通过有意放弃某事物内部如何工作的知识,我们可以考虑的不是它是如何工作的,而是它做了什么。
让我们举一个简短的例子。在高端,我们可能会说,“这个类在某些数据结构中找到最小的 int”。这告诉我们它做了什么,而不是它是如何做的,在这个抽象层次上,这就是我们所关心的。
我们有一个做某事的东西,它是模块化的,我们可以用任何做同样事情的东西来代替它,不管它是怎么做的。那是有一个公共接口。
现在在较低级别上,它的工作方式可能是在内部它是一个堆,或一个优先级队列,或其他任何东西。
这些东西可以用树、自平衡树,甚至(次优)链表来实现。链表将是次优实现,但只要它做同样的事情,我们就不会真正咖啡馆,因为如果次优恢复到足以减慢我们的程序,我们可以将其换成更好的实现具有相同的界面。
这些东西是根据树遍历来实现的(预购:总是按照左、父、右的顺序)。这些东西都是通过节点上的简单操作来实现的。
这是重要的部分:因为应用程序的其余部分不依赖于该模块的内部或副作用,所以将较差的实现换成更好的实现不会改变我们的其他代码,它只会加快整体速度。
每一层只与它上面和下面的层通信,因此每一层都可以被替换。从视觉上看,它看起来像圆圈中的圆圈,而不是维恩图的重叠。
如果你不得不依赖直觉,这表明你的代码有副作用,或者它与其他模块的接口过于宽泛,或者根本没有接口,而不是由自包含构建的代码,不相交,模块,你有重叠和交叉点和脆弱的代码。你没有把它分解成足够简单的片段来理解。
(废话,已经晚了,我担心我可以更好地分解这个解释。我会回来编辑这个。)