解耦代码
# “解耦”为何如此重要?
过于复杂的代码往往在可读性、可维护性上都不友好。
解耦保证代码松耦合、高内聚,是控制代码复杂度的有效手段。
代码高内聚、松耦合,也就是意味着,代码结构清晰、分层模块化合理、依赖关系简单、模块或类之间的耦合小,那代码整体的质量就不会差。
“高内聚、松耦合”的特性可以让我们聚焦在某一模块或类中,不需要了解太多其他模块或类的代码,让我们的焦点不至于过于发散,降低了阅读和修改代码的难度。
“高内聚、松耦合”的代码可测试性也更加好,容易 mock 或者很少需要 mock 外部依赖的模块或者类。
# 如何判定代码是否需要“解耦”?
- 看代码是否牵一发而动全身。
- 看代码是否可以很容易编写单元测试。
- 把对应的模块、类之间的依赖关系画出来,根据依赖关系图的复杂性来判断是否需要解耦重构。
# 如何给代码“解耦”?
封装与抽象
- 封装和抽象可以有效地隐藏实现的复杂性,隔离实现的易变性,给依赖的模块提供稳定且易用的抽象接口。
- 封装和抽象作为两个非常通用的设计思想,可以应用在很多设计场景中,比如系统、模块、lib、组件、接口、类等等的设计。
引入中间层
- 第一阶段:引入一个中间层,包裹老的接口,提供新的接口定义。
- 第二阶段:新开发的代码依赖中间层提供的新接口。
- 第三阶段:将依赖老接口的代码改为调用新接口。
- 第四阶段:确保所有的代码都调用新接口之后,删除掉老的接口。
模块化
- 对于大型复杂系统来说,没有人能够掌握所有的细节,模块化是构建复杂系统的常用手段。
- 我们在开发代码的时候,要有模块化意识,将每个模块当做单独的 lib 来开发,只提供封装了内部实现细节的接口给其他模块使用,减少不同模块之间的耦合。
其他设计思想和原则
- “高内聚,低耦合” 设计思想
- 能够有效提高代码的可读性和可维护性,缩小功能改动导致的代码改动范围。
- 单一职责原则
- 模块或者类的职责设计得单一,而不是大而全,那依赖它的类和它依赖的类就会比较少,代码耦合也就相应的降低了。
- 基于接口而非实现编程
- 通过接口这样一个中间层,隔离变化和具体的实现。
- 在有依赖关系的两个模块或类之间,一个模块或者类的改动,不会影响到另一个模块或类。
- 依赖注入
- 尽管依赖注入无法将本应该有依赖关系的两个类,解耦为没有依赖关系,但可以让耦合关系没那么紧密,容易做到插拔替换。
- 多用组合少用继承
- 继承是一种强依赖关系,父类与子类高度耦合,且这种耦合关系非常脆弱,牵一发而动全身,父类的每一次改动都会影响所有的子类。
- 组合关系是一种弱依赖关系,这种关系更加灵活,所以,对于继承结构比较复杂的代码,利用组合来替换继承,也是一种解耦的有效手段。
- 迪米特法则
- 不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。
上次更新: 2020/08/24, 10:08:00