知识卡片
ISP的源码级成因:接口隔离消除不必要的重新编译部署
内容
接口隔离原则得名于一种具体的软件结构:如果User1只需要调用OPS类里的op1,User2只需要op2,User3只需要op3,但三者都依赖同一个OPS类,那么在Java这类静态类型语言里,User1在源代码层面就与它根本用不到的op2、op3形成了依赖关系——这意味着即便对op2的修改完全不影响User1的功能,User1也会因为这个共享的OPS类被改动而需要重新编译和部署。解法是把不同操作隔离成独立接口(U1Ops只声明op1,U2Ops只声明op2,以此类推),让User1只依赖U1Ops和op1,不再依赖整个OPS类,这样后续对OPS实现细节的修改,只要不涉及op1,就不会牵连User1重新编译部署。这个现象很大程度上和编程语言特性相关:Java这类静态类型语言需要程序员显式import/use/include所需的源代码,这些声明语句本身就带来了源代码依赖关系,导致某些模块被迫跟着重新编译部署;而Ruby、Python这类动态类型语言里对象类型是运行时推演的,源代码里不存在这种强制声明,天生没有这层编译级依赖,因此更灵活、耦合更松。但这不代表ISP只是一个”选对编程语言就能规避”的问题——它其实是一个更普遍的架构问题,不仅限于源码层面。
参考来源
- 位置:《架构整洁之道》第10章《ISP:接口隔离原则》"ISP与编程语言"(源文件:_epub-src/text/part0012_split_004.html)
- 结论依据:原文用OPS类被User1/2/3共享调用、静态类型语言下未使用的op2/op3也会造成源码依赖并触发重新编译部署的例子,说明拆分成独立接口能消除这种不必要的依赖,并对比动态类型语言天生没有此问题的原因,直接支撑本卡片结论。
- 原始内容:User1虽然不需要调用op2、op3,但在源代码层次上也与它们形成依赖关系……我们对OPS代码中op2所做的任何修改,即使不会影响到User1的功能,也会导致它需要被重新编译和部署……User1的源代码会依赖于U1Ops和op1,但不会依赖于OPS。