知识卡片
加密程序案例:源码依赖方向应与数据流向脱钩,让低层成为高层的插件
内容
用[[层次按距离输入输出的远近定义高层策略变更应更少更重大]]分析一个简单加密程序:从输入设备读字符、用查表法转换、把转换后的字符写到输出设备——数据流向是”读→翻译→写”,而Translate组件因为距系统输入输出最远,是层次最高的组件。数据流向和源码依赖关系不总是同一方向,这正是架构设计工作的核心之一:我们希望源码依赖与数据流向脱钩、只与组件层次挂钩。如果直接把程序写成encrypt() { while(true) writeChar(translate(readChar())) },看起来简洁直白,实则是一个错误的架构——它让高层组件里的encrypt()函数直接依赖了低层组件的readChar()和writeChar()函数,违背了”低层依赖高层”的准则。更好的设计是把Encrypt类连同它需要的CharReader、CharWriter两个接口一起框进边界内,所有依赖关系都指向这个边界内部,这样Encrypt就成了系统里最高层的组件;而ConsoleReader、ConsoleWriter这些具体类因为直接对接输入输出,属于低层组件,反过来依赖Encrypt定义的接口。这样一来,高层的加密策略和低层的输入输出策略被彻底解耦——I/O部分的策略变更不太可能影响加密策略:加密算法本身发生变更的概率远小于I/O设备发生变更的概率,即便加密算法真要变,原因也往往比I/O设备的变更更重大。从组件关系上看,这就是”低层组件应该成为高层组件的插件”:Encryption组件对IODevices组件一无所知,反过来IODevices组件依赖Encryption组件——本章讨论的策略分层实践,正是SRP、OCP、CCP、DIP、SDP、SAP这些原则在具体场景下的综合应用。
结构图:
flowchart LR
subgraph 错误架构
Encrypt_bad[encrypt高层函数] -->|直接依赖,违反层次准则| ReadChar[readChar 低层]
Encrypt_bad --> WriteChar[writeChar 低层]
end
subgraph 正确架构
ConsoleReader[ConsoleReader 低层具体类] -.实现.-> CharReader[CharReader接口]
ConsoleWriter[ConsoleWriter 低层具体类] -.实现.-> CharWriter[CharWriter接口]
Encrypt[Encrypt 最高层组件] --> CharReader
Encrypt --> CharWriter
end