如何设计出“深模块”:尽量隐藏知识
2022-04-22 本文已影响0人
全新的饭
何谓隐藏知识?
每个模块中包含了一部分知识,这些知识用于该模块实现自身的一些功能。
相关的数据结构、算法。
可能是低级别的细节、也可能是较抽象的高级概念。
这些知识不应在模块的接口中显示(不在接口中显示意味着这些知识对于其他模块是不可见的,即被“隐藏”了)。
如果一个知识被隐藏了,那么在需要修改它时,只需修改它所属的模块就行,因为它对于其他模块是不可见的,这就是隐藏知识的好处。
在设计一个新模块时,要让它“内向”一点!
内向:在满足向外部提供所必需的功能(这也是该模块存在的意义)的前提下,尽量不暴露自身的其他知识(尽量让其他模块少了解自己一些)。
知识泄露
即:多处用到了相同的知识,这部分知识就是被泄露了的。
在接口中体现的知识就是被泄露的知识。
未体现在接口处的知识也可能被泄露(约定的未在程序语言中体现的规则),这更糟糕,因为不明显。
设计师应对知识泄露高度敏感,当发现会出现知识泄露时,可以做如下事
- 思考如何重新组织,使可能发生的改动影响的模块会更少
- 将若干联系紧密的小类合并为1个(用一个大类把它们包起来)
- 或者将被多个类共享的信息提取出来封装到一个仅封装这些信息的公共类中
但必须在新的公共类中提供尽量简洁的接口,否则这样做仅仅是把不明显的信息泄露变明显了(通过接口显现出被泄露的信息)
划分模块的依据:模块应是知识的聚集
不应粗暴地按照运行时某具体任务的发生时序来切分任务,将它划分到若干模块中。
如果两个子任务共享了非常多的知识,那么即便它们执行的时机根本不一样,也不应将它们划分到不同的模块。
在类内,也要尽量隐藏信息
尽量少的实例变量,各方法间尽量传递数据,而非直接用类的数据。
注意“过犹不及”
凡事要注意度。
可以通过恰当地分层来避免出现太多平级的类,造成认知负荷。
总结
模块是否深的一个评价标准就是它是否隐藏了足够多的知识。
在将一个系统拆分成若干模块时,不要受运行时功能执行顺序的影响(设计模块时不应过多关注这个),而应该思考,执行一项任务需要哪些知识块,设计出模块去封装前述知识块(一个模块中包含1个或多个知识块)。