(4)设计模式-重构

1. 为什么要重构(why)

重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。

  • 首先,重构是时刻保证代码质量的一个极其有效的手段,不至于让代码腐化到无可救药的地步。
  • 其次,优秀的代码或架构不是一开始就能完全设计好的,就像优秀的公司和产品也都是迭代出来的。
  • 最后,重构是避免过度设计的有效手段。

重构实际上是对经典设计思想、设计原则、设计模式、编程规范的一种应用。构能力也是衡量一个工程师代码能力的有效手段。所谓“初级工程师在维护代码,高级工程师在设计代码,资深工程师在重构代码”。

2. 重构什么(what)

可以笼统地分为大规模高层次重构(简称为“大型重构”)和小规模低层次的重构(简称为“小型重构”)。

大型重构指的是对顶层代码设计的重构,包括:系统、模块、代码结构、类与类之间的关系等的重构,重构的手段有:分层、模块化、解耦、抽象可复用组件等等。

小型重构指的是对代码细节的重构,主要是针对类、函数、变量等代码级别的重构,比如规范命名、规范注释、消除超大类或函数、提取重复代码等等。小型重构更多的是利用编码规范。

3. 什么时候重构(when)

提倡的重构策略是持续重构。尽管说重构能力很重要,但持续重构意识更重要。

4. 如何重构(how)

对于大型重构来说,因为涉及的模块、代码会比较多,如果项目代码质量又比较差,耦合比较严重,往往会牵一发而动全身,在进行大型重构的时候,要提前做好完善的重构计划,有条不紊地分阶段来进行。每个阶段完成一小部分代码的重构,然后提交、测试、运行,发现没有问题之后,再继续进行下一阶段的重构,保证代码仓库中的代码一直处于可运行、逻辑正确的状态。每个阶段,都要控制好重构影响到的代码范围,考虑好如何兼容老的代码逻辑,必要的时候还需要写一些兼容过渡代码。只有这样,才能让每一阶段的重构都不至于耗时太长(最好一天就能完成),不至于与新的功能开发相冲突。

小规模低层次的重构,因为影响范围小,改动耗时短,所以,只要愿意并且有时间,随时都可以去做。实际上,除了人工去发现低层次的质量问题,还可以借助很多成熟的静态代码分析工具(比如 CheckStyle、FindBugs、PMD),来自动发现代码中的问题,然后针对性地进行重构优化。

要防止出现“破窗效应”。

5. 保证重构不出错,落地的技术手段–单元测试

5.1 什么是单元测试

单元测试相对于集成测试(Integration Testing)来说,测试的粒度更小一些。集成测试 的测试对象是整个系统或者某个功能模块,比如测试用户注册、登录功能是否正常,是一种端到端(end to end)的测试。而 单元测试 的测试对象是类或者函数,用来测试一个类和函数是否都按照预期的逻辑执行,是代码层级的测试。

5.2 为什么要写单元测试

单元测试除了能有效地为重构保驾护航之外,也是保证代码质量最有效的两个手段之一。

  1. 单元测试能有效地帮你发现代码中的 bug。
  2. 写单元测试能发现代码设计上的问题。
  3. 单元测试是对集成测试的有力补充。
  4. 单元测试的过程本身就是代码重构的过程。
  5. 阅读单元测试能帮助你快速熟悉代码。
  6. 单元测试是 TDD 可落地执行的改进方案。

JaCoCo、Cobertura、Emma、Clover可做覆盖率统计。

6. 可测试性代码

6.1 代码的可测试性

所谓代码的可测试性,就是针对代码编写单元测试的难易程度。对于一段代码,如果很难为其编写单元测试,或者单元测试写起来很费劲,需要依靠单元测试框架中很高级的特性,那往往就意味着代码设计得不够合理,代码的可测试性不好。

6.2 编写可测试性代码的最有效手段

依赖注入是编写可测试性代码的最有效手段。通过依赖注入,在编写单元测试的时候,可以通过 mock 的方法解依赖外部服务,这也是在编写单元测试的过程中最有技术挑战的地方。

6.3 常见的测试性不好的代码

  1. 未决行为。所谓的未决行为逻辑就是,代码的输出是随机或者说不确定的。
  2. 全局变量。
  3. 静态方法。
  4. 复杂继承。
  5. 高耦合代码。

7. 解耦

7.1 解耦为何很重要

过于复杂的代码往往在可读性、可维护性上都不友好。解耦保证代码松耦合、高内聚,是控制代码复杂度的有效手段。代码高内聚、松耦合,也就是意味着,代码结构清晰、分层模块化合理、依赖关系简单、模块或类之间的耦合小,那代码整体的质量就不会差。

7.2 代码是否需要解耦

间接的衡量标准有很多,比如,看修改代码是否牵一发而动全身。直接的衡量标准是把模块与模块、类与类之间的依赖关系画出来,根据依赖关系图的复杂性来判断是否需要解耦重构。

7.3 如何给代码解耦

给代码解耦的方法有:封装与抽象、中间层、模块化,以及一些其他的设计思想与原则,比如:单一职责原则、基于接口而非实现编程、依赖注入、多用组合少用继承、迪米特法则等。当然,还有一些设计模式,比如观察者模式。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值