重构读书笔记七——搬移特性

重构 Jan 8, 2021

概述

本章作者介绍了种新的重构手法,搬移代码。([me]:我理解这种重构手法主要解决的是代码出现在不恰当的位置,什么是不恰当的位置——一段代码和他的左邻右舍没有业务和逻辑上的关系。用ddd的话说,就是不在一个上下文里面)

7.1 搬移函数

描述

直观上理解就是将函数从原来的类里面搬到另一个类里面。但是什么时候决定搬移,搬到哪里去是问题的关键。

动机

模块化是软件设计的核心所在,好的模块化能够让我们在修改程序时只需理解程序的一部分。为了设计出高度模块化的程序,我们需要保证关联的代码都能集中到一块,并确保块与块之间的联系易于查找,易懂。同时随着业务的发展和对业务的深入理解,我们对于代码的组织也是会改变的。这时候就需要搬移代码。
任何函数都需要上下文才能存活。搬移函数直接的一个动机是,它频繁引用其他上下文中国中的元素,而对自身上下文的元素交互甚少。此时应该让它和更紧密的元素聚合,通常能够取得更好的封装效果。

7.2 搬移字段

描述

把字段放到他应该在的地方

吐槽

我曾经遇到过一个bean类,里面有十几个字段,通过这个类来传递数据。如果这十几个字段是有关系,一起使用还能接受,问题在于——十几个字段里面三三两两是一起使用的,并且还是一个组合的模式。在一函数里面可能是用了这几个字段,到了另一个函数里面就用了另外几个字段。最可恶的是只有一个无参构造函数,数据的使用都是通过set/get方法,我追溯数据的走向就变得很困难,再加上字段之间的排列组合使用,整理业务逻辑就像破译密码。

动机

编程活动中需要编写很多代码,为系统支持特定的行为,但往往数据结构才是一个健壮程序的根基。一个适应于问题域的良好数据结构,可以让行为代码变得简单明了,而一个糟糕的数据结构则将招致许多无用代码,这些代码更多的是在差劲的数据结构中间纠缠不清,而非实现有用的行为。这时候有领域驱动设计方面的经验和知识,往往有助于更好地设计数据结构。如果发现某个数据结构已经不适应需求,就马上改善它。

7.3 搬移语句到函数

描述

把单独或部分语句和相关的函数进行合并,或者直接搬到函数中。

动机

要维护代码库的健康发展,需要遵守几条黄金规则,其中最重要的一条当属于:消除重复。如果发现调用某个函数时候,总有一些相同的代码需要执行,可以考虑将此段代码合并到函数里面。如果某些语句与一个函数更像一个整体,并且有助于理解,那么没什么犹豫的把语句搬移到函数里面吧。

7.4 搬移语句到调用者

描述

把语句从函数里面搬到调用处。

动机

作为程序员,我们的职责就是设计出结构一致,抽象合理的程序,而程序抽象能力的源泉正式来自函数。与其他抽象机制一样,我们并非总能平衡好抽象的边界。随着系统能力发生演进,原本设定的抽象边界会悄无声息的发生偏移。对于函数来说这样的边界偏移意味着以前的一个整体,现在分化出了两个甚至多个关注点。于是我们要把表现不同的行为从函数里面挪出来,并搬到调用处。

7.5 以函数调用取代内联代码

描述

把一个整体逻辑封装到一个函数里面调用。

动机

善用函数可以帮助我们将相关的行为打包,这对于提升代码的表达力大有帮助。一个命名良好的函数,本身就能极好地解释代码的用途,使读者不用了解其细节。函数也有助于消除重复

7.6 移动语句

描述

把类似的代码写在一块区域也可以让代码更整洁。例如:声明的变量放在一起。变量的校验在一处处理完成等等

描述

让存在关联的代码一起出现,可以使代码更加容易理解。如果几行代码使用了相同的数据结构,那么最好让他们一起出现。

7.7 拆分循环

描述

我们经常能见到一个循环内堆积了大量代码,这时候我们可以把每一个逻辑上的操作放到不同的循环里面。这样虽然循环了多次,但是逻辑上清晰了很多。另外一种方法是在一次循环内将不同的操作用函数封装起来。

动机

在一次循环里面做了两件不同的事,那么每当要修改循环的时候,就得同时理解两件事情。

7.8 以管道替代循环

描述

今天大部分编程语言都提供了管道(流,算子等等),可以用这种操作来替代循环。

动机

代码的可读性会更强,因为管道操作具有语义。

7.9 移除死代码

动机

删除项目中已经不使用的代码,而不是仅仅注视掉它。

吐槽

互联网项目中往往会有非常多的实验代码,通过传入不同的参数来控制程序的逻辑。很多时候即使推全的实验也没人把实验的代码下掉,可能是害怕反复,更多是懒得去删,导致阅读代码的时候不熟悉的人一定要阅读完实验的配置才能知道现在代码的逻辑。

描述

一旦代码不使用应该马上删除掉,即使注视掉也会占用我们的代码空间,看起来非常不整洁。即便以后想要恢复对应的代码,只要到版本控制里面恢复就可以了。