zoukankan      html  css  js  c++  java
  • 阅读《重构》的一些思考

      终于在断断续续的情况下把这本经典巨作看完了。

      这本书的全名叫做《重构-改善既有代码的设计》,原有的代码设计存在不足的地方让人感到不好维护,所以才需要去改善既有代码的设计,其实听起来会不会有点亡羊补牢的感觉?这里也提醒了我们一点:从设计代码的初期就要深思熟虑,虽然后续的改动基本无法避免,但良好的初期设计将对后续维护提供帮助。重构不是最终目的,我们的目的是让代码变得更好。

    关于书的内容组织

      不得不称赞的一点是作者的写作思路是非常清晰的。整本书的开始是由一个小型案例讲起,让读者了解重构是一项什么样的工作,作者的案例设计也是挺巧妙的,值得不熟悉面向对象编程的读者反复揣摩。之后便开始讲诉重构的一些概念,包括什么是重构(在不改变软件可观察行为的前提下,调整其内部结构,整理代码的一个过程。注意与开发新功能的一个区分,开发新功能是在改变软件可观察行为)、为什么要重构(重构可以提高代码的可维护性)以及什么时候重构(添加功能、修复错误、复审代码的时候)。

      接下来就列举了一系列要点讲解不好的代码设计的一些症状。中间携带了关于测试体系的介绍,不过这一部分更多的是稍微提点一下,并没有做比较深入的分析。之后就迎来了整本书的重头戏,关于重构手法的介绍,包括如何组织函数、在对象之间搬移特性(字段、函数)、重新组织数据、简化条件表达式、简化函数调用和处理继承关系。随后也顺带介绍了大型重构的四个手法,包括梳理并分解继承体系、将过程化设计转化为对象设计、将领域与表述分离和提炼继承体系。

      本书的最后是对于重构的一个概括,作者认为真正懂得重构的一个衡量标准是”你可以自信地停止重构“,学会重构手法只是一个起点,把握何时使用、何时开始、何时停止的节奏才是使重构走向成功的关键。

    阅读重构手法的心得

      书中介绍了多种重构手法,这里也不打算将其一一列举出来,而是挑选了部分让我醍醐灌顶的重构手法,以及阅读中自己的一些思考。说实在话,自己在阅读本书的时候并没有做到非常细致,特别是对于具体重构的步骤几乎是一扫而过,读得非常”粗“,可能跟我自己没有真正地处理起大型的遗留代码有关联,思维里总是回响着一股这样的声音”这个重构手法是处理这样的问题,恩,在最开始进行开发的时候就要留意这一点“,从而让我觉得这些重构的具体步骤很繁琐无趣,对于现阶段也没有较大的实用价值。或许等我真正接触到非常多的遗留代码问题,在来重读本书会有新的体会。

      1. 把关好命名原则

      良好的命名是可读代码的基础,书中对于这个概念也是非常重视的,甚至鼓励开发者在没有找到一个合适的命名前不要继续往下开发。虽然书中并没有讨论如何把握命名方式,但是这里我就班门弄斧一回,简单地谈一下自己的一些看法。

      首先要注意的第一个环节是要把握C#开发的基本命名规范,例如私有字段用‘_’开头、函数名称的首个单词最好能是一个动词、不要将变量名称命名为“temp”等,如果我们能做好这最基本的一点,让别人来看你的代码也是那么地清晰,这是不是一件美好的事情呢?所以,假如对于C#开发的基本命名规范还没有概念的话,是时候需要去恶补一下了。

      多数情况下开发都离不开业务,所以良好的命名也要结合具体业务。在分析业务的同时也要积累业务相关的词汇,例如Order表示订单,Sku表示库存量单位等,这些词汇在命名的时候可以提供支持。

      最后提及的一点策略是借鉴设计模式的词汇。虽然有时候我们不一定会在代码中使用设计模式,但是借鉴某些词汇来表达意图也是可以的,例如Factory、Adapter、Template、Bulider、Singleton、Proxy等,前人已经将经验汇集提供给了我们,我们需要做的就是好好利用它们。

      总体而言,就连作者本人也承认的一个观点是“经验会带来更多的帮助”,所以在开发中不仅要重视名称的选择,也要注重经验的积累。

      2. 使用return跳出多条件表达式

      说实在话,这是阅读本书最让我眼前一亮的重构手法了。不知道大家有没有跟我有这样的习惯:

    public bool IsEnable()
    {
        bool result = false;
        if (条件1)
        {
            result = true;
        }
        else
        {
            if (条件2)
            {
                result = true;
            }
            else
            {
                for (int i = 0; i < length; i++)
                {
                    if (条件3)
                    {
                        result = true;
                        break;
                    }
                }
            }
        }
        return result;
    }
    多条件判断代码

      这里用伪代码模拟了一下场景,其实有可能实际的函数比这个还复杂,在函数的开头就声明一个result变量,接下来就是各种条件判断对result赋值,最后在统一返回这个result,这就是开发人员对于“统一出口”的思想。其实有时候会不会觉得这样的代码看起来很绕?来看下使用这个手法重构后的代码吧:

    public bool IsEnable()
    {
        if (条件1) return true;
    
        if (条件2) return true;
    
        for (int i = 0; i < length; i++)
        {
            if (条件3) return true;
        }
        return false;
    }
    重构后的代码

      重构后带来的最大变化是减少了else逻辑,及时地return避免引导读者去看另外一个没有用的else区域,代码变得更加清晰了。

      3. 没有一成不变的规则,具体情况具体分析

      重构手法更多地像一个工具箱,里面放满了十字螺丝刀,钳子,扳手等,处理代码遗留问题就像修理东西一样,遇到不同的问题就要使用不同的工具。其实书中有时候作者介绍的重构手法是一个对立面,例如将提炼函数和内联函数,一个主张提炼出一个独立的函数,一个提倡不使用独立的函数,所以涉及到具体情况就要具体分析,要从理解重构手法的角度出发,没有绝对的使用定律。

    我所认为的书中的不足之处

      有些讨论的话题比较泛化,例如6.9节替换算法,“将函数本体替换为另一个算法”,内容描述起来比较空洞,有点类似于告诉我们“嗯,这个函数这样写不好,换一种实现方式更好”,并不能合格地称为一种重构手法。

      对于某些重构手法我是保持着中立态度(意思是这种重构手法我不太喜欢这样做),例如6.4节的“以查询取代临时变量”,来看一段书中给出的伪代码:

    //重构前的代码
    double basePrice = _quantity * _itemPrice;
    if (basePrice > 1000)
        return basePrice * 0.95;
    else
        return basePrice * 0.85;
    
    //重构后的代码
    if (CaculateBasePrice() > 1000)
        return CaculateBasePrice() * 0.95;
    else
        return CaculateBasePrice() * 0.85;
    
    double CaculateBasePrice()
    {
        return _quantity * _itemPrice;
    }
    6.4节例子

      有时候为了重用代码,将表达式提炼到一个函数中,可以更好地提高代码复用率。但这个重构手法还有一个着重点:用提炼的函数去替代原来的变量。其实我觉得这里用一个临时变量也并没有什么问题,替换为函数反而可能会出现一些问题:如果表达式是一个复杂的计算,每个使用的地方都调用一遍会降低性能;在阅读代码的时候,如果遇到函数调用的情况,都会将关注点调到函数中去,反而会降低了代码可读的流畅性。基于前面诉说的理由,我个人是不太喜欢实践这个重构手法。

      不得不承认的一点,就是这本书的写作时间是比较早的,以至于书中介绍的重构手法的实现步骤是建立于当时开发环境下的,部分做法可以说是已经“过时”了。例如10.1节函数改名,书中介绍了较为复杂的做法,但放在当今的开发环境下,IDE基本已经集成了函数改名这一重构功能,只要输入新的函数名称就能自动替换所有引用到旧函数的地方,已经大大提高了重构效率;6.1节提炼函数也是类似的情况。

      不过,这并不阻碍这本书的历史地位。推荐给各位读者,读完后也许你也会对代码重构有新的感悟。

  • 相关阅读:
    品优购(IDEA版)-第二天
    品优购(IDEA版)-第一天
    GitHub客户端Desktop的安装和使用总结
    Android开发10:传感器器及地图相关应用
    Android开发9:网络访问&Web服务开发
    Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
    Android开发7:简单的数据存储(使用SharedPreferences)和文件操作
    Android开发6:Service的使用(简单音乐播放器的实现)
    归纳整理一些工作学习中发现的不错的网站、博客地址等(转载)
    Android Studio安装配置、环境搭建详细步骤及基本使用
  • 原文地址:https://www.cnblogs.com/teroy/p/4194346.html
Copyright © 2011-2022 走看看