有句著名的话叫做"All problems in computer science can be solved by another level of
indirection".
另有人(page-jones)研究过耦合(connascence)的种类,并提出
通过把某种耦合变成另一种耦合,可以减弱耦合的程度.
今天终于有机会使用这两个著名的东西了.
问题是这样的. 你的合作方比较强势,
不愿意按契约来设计. 你的系统想知道"这个流程执行完后,倒底谁拿到了标书? ", 对方告诉你, "我们不提供’谁拿到了标书’这个接口,你可以使用’竞标者是不是市委干部的儿子或女婿’这个接口,因为他们一旦竞标,合同肯定就是他们的"
而你又相信"人间或许还有点公义,现在他们能拿到,以后就未必了". 但前面说了,对方很强势,于是干脆不搭理你.
如果你按他们的意思来,那你们就没有严格地按照契约来定义接口: 他给你的东西不是你直接想要的东西,而是你想要的东西的背后的东西. 如果你直接依赖"竞标者是太子"这个接口,万一这玩意儿靠不住了,你就得改你的系统.
从Connascence的角度来说,
这里存在一个Connascence of Algorithm(算法耦合性), 你们两个系统之间的正确交互依赖于 "高干子弟必定拿标书" 这个脆弱的业务规则(算法).
那怎么解决这个问题? 既然对方不愿给真正的接口,那你就无法避免这个耦合; 但你仍要想办法减弱它对你的系统的影响; 也就是说,
算法被改变时,你的系统所做的修改要尽量小.
举例来说,如果你的系统中多处用到了这个接口,那一旦算法被改变,你的系统就有多处要改.
说到这里,解决方案已经呼之欲出了.
你要引入一个Adaptor作为indirection, 这个Adaptor在名义上提供你要的接口:"倒底是拿到了标书? ", 实现上它再依赖对方系统的"高干子弟拿标书"这个潜规则; 你的系统里要调用标书逻辑的地方都必须通过这个Adaptor, 而不能直接依赖对方的系统.如果对方改了这个逻辑,你只需要改你的Adapter这一个地方就可以了.
没错,耦合性还是存在,但你对未来的担扰至少少了些.
从Connascence的角度来说, 你是把耦合性
从"Connascence of Algorithm" 减弱为 "Connascence of name", 从依赖算法变成了依赖adaptor类的方法名.
这跟"magic number"问题的解决方案是不是有点像? 道理似乎很浅. 但我之所以写这篇文章,是想建议大家,弱耦合的思想不应局限于OOP领域(什么依赖接口,不要依赖实现之类的),而应该
深刻地从本原上去理解弱耦合思想,并把它渗透到系统分析和设计中每一处.