zoukankan      html  css  js  c++  java
  • 重构技法

    入职新公司,接手已有的项目,重构技能是必须掌握的,这次从基础盘点下常用的重构方法,不深入设计模式。

    什么是重构?

    在不改变软件逻辑前提下,重新设计并组织代码的行为。

    为什么重构?

    接手旧项目的时候,以下场景一定不会陌生:

    上司交过来的任务,,

    拒绝是不可能的嘛....

    实际上,远没有答应时的轻松:

    代码看了半天还是看不懂啊,一个方法上千行,心累ing

    若干天后,终于看懂代码了,但是发现IDE一堆警告,一看提示说存在重复的代码,整个项目都是警告,那么多重复代码,不会封装一下吗!

    着优化下代码,改着改着发现好多if-else,还是多层嵌套,每个嵌套的判断还很复杂,想想还是先不改了,万一改出问题,岂不是更糟糕!

    脑壳痛...

    没办法,只好拿出重构大法,见招拆招!

    第一招:重复代码的提炼

    重复代码是重构收效最大的手法之一。

    好处:代码量大大减少,维护方便,代码条理更加清晰易读。

    重点就在于寻找代码当中完成某项子功能的重复代码,将它移动到合适的方法当中,并存放在合适的类当中。

    使用泛型提取重复逻辑

     

    第二招冗长方法的分割

      往往在我们提炼重复代码的过程中,就不知不觉的完成了对某一个超长方法的分割

     这其中有一点是值得注意的,由于我们在分割一个大方法时,大部分都是针对其中的一些子功能分割,因此我们需要给每一个子功能起一个恰到好处的方法名,方法名要说明此方法的用途,名称无法说明清楚时,才使用注释,这很重要

    class GoodExample

    {

        public void Method()

        {

            function1();

            function2();

            function3();

        }

        private void Function1()

        {//function[1]

        }

        private void Function2()

        { //function[2]

        }

        private void Function3()

        { //function[3]

        }

    }

    冗长的函数被分割,重复的逻辑被提取。也就是说函数(接口、类)要职责分明,也就是

    单一原则

    当方法较多且具有固定流程时,也就是设计模式中的模板方法

    第三招:嵌套条件分支的优化

    大量的嵌套条件分支是很容易让人望而却步的代码,应该极力避免这种代码的出现

    1)将不满足某些条件的情况放在方法前面,并及时跳出方法,以免对后面的判断造成影响。

    public void Method(Object A, Object B)

        {

            if (A != null)

            {

                if (B != null)

                {  //code[1]

                }

                else

                {  //code[3]

                }

            }

            else

            { //code[2]

            }

        }

    改成这样,好懂多了:

    public void Method(Object A, Object B)

        {

            if (A == null)

            { //code[2]

                return;

            }

            if (B == null)

            {//code[3]

                return;

            }

            //code[1]

        }

    2)合并分支条件。

            if (A != null)

            {

                if (B != null)

                { //code

                }

            }

    改成:

    if (A != null && B != null)

     {//code

     }

    3)大量分支

    当含有大量分支(条件、状态)判断的时候,可以考虑设计模式中的状态模式

    第四招:去掉一次性的临时变量

    class BadExample

    {

        private int increment;

        public void Method(int[] arr)

        {

            int n= arr.Length;

            int temp = GetIncrement();

            for (int i = 0; i < n; i++)

            {

                temp *= i;

            }

        }

    }

    class GoodExample

    {

        private int increment;

        public void Method(int[] arr)

        {

            for (int i = 0; i < arr.Length; i++)

            {

                GetIncrement() *= i;//emm,简洁明了!

            }

        }

    }

    第五招:消除过长参数列表

    将这些参数封装成一个对象传递给方法

    class BadExample

    {

        public void Method(int i, int j, int k, int l, int m, int n)

        {

            //code

        }

    }

    改成:

    class Data

    {

        private int i;

        private int j;

        private int k;

        private int l;

        private int m;

        private int n;

    }

    class GoodExample

    {

        public void Method(Data data)

        {

            //code

        }

    }

    第六招:提取类或继承体系中的常量

    一些字符串常量等,会让人对程序的意图产生迷惑

    字符串等类型的常量的消除,方便维护。因为我们只需要修改一个常量,就可以完成对程序中所有使用该常量的代码的修改。

    可以使用静态类、结构、字段、枚举...

    第七招:优化冗长的类

    (1)拆分逻辑可分离的部分

    这一步和方法一样,体现了单一原则和高内聚。

    (2)让类提供该提供的方法

        public class Data

        {

                public void DataMethod()

                {

                   //do something

                }

                public int One{get;}

                public int Two{get;}

                public int Three{get;}

        }

    上层可能是这样调用的:

    class Program

        {

            static void Main(string[] args)

            {

                GetThree(data);

            }

            public int GetThree(Data data)

            {

                return data.One * data.One * data.One;

            }

        }

    我们在上层定义一个方法操纵一个类内部的成员;

    这是不应该的,应在类的内部就提供这个方法:

       public class Data

        {

                public void DataMethod()

                {

                   //do something

                }

               public int GetThree(Data data)

             {

                return data.One * data.One * data.One;

              }

                public int One{get;}

                public int Two{get;}

                public int Three{get;}

        }

    这样在上层只需要调用这个方法即可。

    (3)提取重复的成员到父类

    这一步是自底向上的设计,当两个类出现相同的成员时,可以抽象出父类或接口,方便以后的扩展。

    其他

    1、纠正随意命名

    无规律的命名让读代码的人头大,,,

    2、删除无效注释

    精简代码,简短,漂亮

    3、约定:

            if语句中的条件表达式的逻辑运算不要超过3

    团队合作中,书写约定非常重要,可以大大提升团队开发效率!

    通过重构,我们要达到这样的目标:

    总结

    正在写的项目:重构应该随时进行

          重构通常不是一次性的,它贯穿软件的整个生命周期,只要觉得不合理都是重构的时机

    象、继承

    的项目梳理既有业务的流程和详细规则,接着梳理技术架构,然后评估方案,就可以重构了~

    重构

            让代码更容易理解

           改善内部结构,修改更容易

          提高编程速度,加快业务迭代

    经过重构之后:

          (网图侵删)

    是不是很形象?

  • 相关阅读:
    Jquery停止动画
    Jquery自定义动画与动画队列
    关系型数据库的常用概念
    三大范式审核
    数据库设计基本步骤
    'NoneType' object is not iterable
    三行神奇的代码
    url的解码方式
    [转]获取当前执行主脚本的方法
    非黑即白--谷歌OCR光学字符识别
  • 原文地址:https://www.cnblogs.com/Zdelta/p/14122343.html
Copyright © 2011-2022 走看看