代码耦合

编程绕不开的一个话题:耦合

耦合其实是个中性词,代码模块之间要相互协作完成任务,就必定要耦合。耦合即:一方对另一方的假设。你不可能对协作的对象不做任何假设,所以其实有些耦合是必须的。我们要解决的是非必要的,不良的耦合。

如无必要,不要使代码耦合,过度耦合会加速代码腐烂(比如:难加新功能,难修 bug)

对另一方做尽可能少的假设其实只是手段之一,而且这种手段势必会让代码变得更加抽象复杂。另一种手段就是:制定标准和建立知识库,大家用共同的标准和共有的知识去沟通,就会非常顺畅,反之则寸步难行。所以当你觉得你们的项目程序写得稀烂,先不要关注过度耦合的问题,先看看是不是连标准都没制定,公共知识库都没有建立,人员不知道不遵守既定标准和知识。

怎么写出低耦合的代码

  1. 模块的单向依赖关系
  2. 接口的正交性和紧凑性
  3. 提供原子化的最底层 API + 胶水层 API(根据业务,对原子 API 做一些比较常用的组合)
  4. 既要防御式编程,也要提供模块和接口的最佳实践

单向依赖

模块之间尽可能的单向依赖,做成像树状结构,而不要像网状结构。

正交性

正交性是指一个模块提供的 API 中,多个方法之间是否有重复的功能。

如果有重复功能,正交性就差。

想象一下,调节电视的声音的时候,亮度也会跟着一起变化。

通常,正交性高的模块更稳定,不会因为上层业务变化而被迫修改代码。

好的 API 内部的多个方法之间不应该有任何重复功能,只实现正交的机制。

如果感觉拆得太细使用不便,应该在底层 API 之外包装出一层 Helper、Utility 组成的胶水层。

胶水层调用底层原语 API 来实现常用模式供上层使用。

对于胶水层中的模块,对正交性的要求可以稍低一些。

注意上层代码既可以直接调用正交的底层 API,又可以调用胶水层的常用模式。

紧凑性

紧凑性是指一个模块提供的 API 中,公有方法总数必须很少,每个方法的参数也必须很少。

《Unix 编程艺术》上说一个模块不要超过 7 个方法,不然就很难理解。

总之,单向依赖、正交性、紧凑性这三个指标都很务实,有客观方法可以度量。

不同级别之间的耦合

软件是由不同级别的概念层组成,不同级别的概念层具有不同的职责,不同级别的概念层中存在不同的耦合:有方法级别、类级别、包级别、协议级别、语言级别、数据流级别、数据库级别、业务级别……

总结

耦合的本质是假设,假设越多,被打破的机率就越高,所以软件的可靠性就越低。低耦合代表的是在软件不同级别的概念上只依赖它需要依赖的,从而达到它本身的修改不至于造成其它系统的非必要影响,反之亦然。

在软件开发过程中,我们应该管理这些耦合,不论在哪个级别上。应该经常考虑如果这些假设被打破了,会给系统带来哪些风险。