用重构的思维编写代码

378 阅读5分钟

(不定期更新) 前段时间读了《重构》这本书,感觉收获颇丰,其中有些是自己已经会了的,更有些则会让自己茅塞顿开。在这里逐步将整理自己所理解的编码方式,书虽然看完了,但要完全按自己的理解整理一遍还需要点时间,所以在最终完成前,这篇文章的结构、内容可能比较凌乱,但都随时可能会越来越结构化,使其更有逻辑层次。由于是自己的编码风格,所以也有很多地方会用结论性的语言来描述。

为什么要用重构的思维编写开发代码?

    我认为这是一个好的个人习惯,在开发的时候随时心里都想着这段代码将来可能会在另一个地方被用到,在这个阶段就尽可能将业务性的代码和工具性的代码区分开,工具性的代码要做到与业务没有任何直接关系

    当然要完全做到这样是比较困难的,比如写一个费用计算引擎,这个业务本身是有一些工具的成分在里面的,但是它又脱离不了“费用”,所以它只能在一定范围内充当工具使用,这时候应该用模块或目录将代码隔离到这个业务下面,所以工具也有工具的使用场景,毕竟扳手主要还是拧螺丝,香水主要还是喷头发的。

    这种方式写前端的童鞋应该比较好理解,JS 可以将函数定义在任何一个作用域,这种做法就相当于在当前作用域定义一个工具函数,只能在当前作用域及子作用域使用。

    对于写 Java 的童鞋而言,合理运用public、protected、default、private等修饰符来限制这个类、方法或字段的有效范围,比如 AbstractStringBuilder 这个类就是用了 default 修饰符(实际上就是什么修饰符都不写)我们在使用的时候是感觉不到这个类的存在的,因为这个类只能在当前包(java.lang)使用,又或者 HashMap 里有个同样被 default 修饰的方法 afterNodeAccess 可以在 LinkedHashMap 里找到实现(不过个人认为更应该用 protected 来修饰,不然有时候想自己实现一些功能不太方便)。

什么是重构?

《重构》中分别按名词和动词做了解释:

  • 名词:对软件内部的一种调整,在不改变软件可观察行为前提下,提高可理解性,降低修改成本。
  • 动词:使用一系列手法,再不改变软件可观察行为前提下,调整其结构。

    这两句话中都有两个个重要的词 “可观察行为 和 可理解性” 。代码是交给计算机执行的,但却是由人来读。计算机是饥不择食,来者不拒,只要是认识的代码都能正确执行,这便是可观察行为——保证修改前后输入输出的效果一致。

    但是人不一样,人有人的世界观,在人的眼里“人”应该叫 people 或者 person,“执行”应该叫 run 或 execute,这便是可理解性一部分,个人认为可理解性很大程度(凭感觉 60% - 70%)就是语义化变量名。

    那么可理解性的另一部分是什么呢?这里我认为应该这样理解,一辆“保时捷911”它的牌子是 Porsche,它的型号是 911,他有 4 个轮子...这些是它的属性(字段);另外它能行驶,这是可以认为是方法;它还可以变档行驶,这可以认为是含参方法。这便是另一部分可理解性:自己的事情自己做,不越界。其实这样的体现不只是写代码,一个人、一个公司有何尝不是这样,公司小的时候,一个前台可能还兼着人事,当公司大了,部门的任务越来越多,职责也就越来明确,便有了人事部、财务部,各司其职。小时候你和你姐姐共穿一条裤子,长大了还这样就有点变态了。世界上本没有路,走的人多了,也便成了路。

public class Car {
    private String brand = "Porsche";
    private String model = "911";
    private int countOfWheel = 4;
    
    public void run(){
        // 行驶
    }
    
    public void run(int level){
        // 变档行驶
    }
}

    总的来说,可观察行为和可理解性是分别对计算机和人说的,要让计算机能理解,还要让人能理解。

为什么重构?

前面解释了什么是重构,那这里为什么重构就好理解了,简单的说就是同时能让计算机和人都能很好的理解。

《重构》中有这样一段话,我认为解释的比较好:

所谓程序设计,很大程度上级就是与计算机交谈:你编写代码告诉计算机做什么事,它的响应则是精确按照你的指示行动。你得及时填补“想要他做什么”和“告诉它做什么”之间的缝隙。这种编程模式的核心就是“准确说出我所要的”。

    最后一句话 “准确说出我所要的”, 当你和一个对象沟通时,你应该根据它的能力告诉它的我的需求。这句话怎么理解呢?

    你得抽象一点,js 有什么能力?它可以发起 ajax 请求,于是可以可以用它来访问远程资源;Java 有什么能力?它可以多线程、可以访问数据库、