本节书摘来自异步社区出版社《C++编程规范:101条规则、准则与最佳实践》一书中的第2章,第2.7节,作者:【加】Herb Sutter , 【罗】Andrei,更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.7 隐藏信息
摘要
不要泄密:不要公开提供抽象的实体的内部信息。
讨论
为了尽量减少操作抽象的调用代码和抽象的实现之间的依赖性,必须隐藏实现内部的数据。否则,调用代码就能够访问该信息,或者更糟,操作该信息,而原本应属于内部的信息就泄漏给了调用代码所依赖的抽象。应该公开抽象(如果有的话,还是公开领域抽象更好,但至少应该是get/set 抽象),而不是数据。
信息隐藏主要从下列两个方面降低了项目的成本,加快了项目的进度,减少了项目的风险。
它限制了变化的影响范围。信息隐藏缩小了变化所引起的“连锁反应”的范围,也降低了由此带来的成本。
它强化了不变式。它限制了负责维护(如果有错误的话,也可能是破坏)程序不变式的代码(见第41条)。
不要从任何提供抽象的实体中公开数据(另见第10条)。数据只是抽象、概念性状态的一种可能的具体化而已。如果将注意力集中在概念而不是其表示形式上,就能够提供富于提示性的接口,并按需要对实现进行调整——比如缓存还是实时地计算,又比如使用不同的表示方式,针对某种使用模式(如极坐标与笛卡儿坐标)进行优化。
绝对不要将类的数据成员设为public(见第41条),或者公开指向它们的指针或句柄(见第42条)而使其公开,这是一个很常见的信息隐藏的例子,但是它同样适用于更大的实体比如程序库——程序库同样不能暴露内部信息。模块和程序库同样应该提供定义抽象和其中信息流的接口,从而使与调用代码的通信比采用数据共享方式更安全,耦合度更低。
例外情况
测试代码经常需要对被测试类或者模块进行白箱访问。
值的聚合(“C语言式的struct”)只是简单地将数据绑在了一起,并没有提供任何抽象,所以它不需要隐藏数据,数据本身就是接口(见第41条)。
参考文献
[*s95] §19 ● [McConnell93] §6.2 ● [Parnas02] ● [Stroustrup00] §24.4 ● [SuttHysl04a]