重构—改善既有代码的设计100:简化函数调用(Making Method Calls Simpler)

重构—改善既有代码的设计100:简化函数调用(Making Method Calls Simpler)

    一:重新命名函数(Rename Method)
    二:添加参数(Add Parameter)
    三:移除参数(Remove Parameter)
    四:将查询函数和修改函数分离(Seperate Query from Modifier)
    五:令函数携带参数(Parameterize Method)
    六:以明确函数取代参数(Replace Parameter with Explicit Methods)
    七:保持对象完整(Preserve Whole Object)
    八:以参数取代参数(Replace Parameter with Method)
    九:引入参数对象(Introduce Parameter Object)
    十:移除设置函数(Remove Setting Method)
    十一:隐藏某个函数(Hide Method)
    十二:以工厂函数取代构造函数(Replace Constructor with Factory Method)
    十三:封装向下转型动作(Encapsulate Downcast)
    十四:以异常取代错误码(Replace Error Code with Exception)
    十五:以测试取代异常(Replace Exception with Test)

一:重新命名函数(Rename Method)
    1:如果函数的名字未能揭示函数的用途:修改函数的名字
    2:将复杂的处理过程分解成小函数,并给函数取一个好名称,利用函数名称准确表达它的用途
        代码首先是写给人读的,其次才是为机器写的。


二:添加参数(Add Parameter)
    1:某个函数需要从调用端得到更多的信息
        为此函数添加一个对象参数,让该对象带进函数所需信息。
        注:过长的参数列是不好的味道,很难记住那么多参数,而且长参数列往往会伴随着坏味道。

三:移除参数(Remove Parameter)
    1:将函数体中不再需要的某个参数去除
    2:动机
        程序员可能经常添加参数,却往往不愿意去掉它们,他们打的如意算盘是无论如何多余的参数都不会引起任何问题,而且以后还可能用上它。

四:将查询函数和修改函数分离(Seperate Query from Modifier)
    1:当某个函数既返回对象状态值,又修改对象状态
        建立两个不同的函数,其中一个负责查询,另一个负责修改
    2:动机
        如何有返回值的函数,都不应该有看得到的副作用。

五:令函数携带参数(Parameterize Method)
    1:若干函数做了类似的工作,但在函数本体中却包含了不同的值
        建立单一函数,以参数表达那些不同的值
        fivePercentRaise();
        tenPercentRaise();
        修改为:
        raise(percentage);
    2:
        protected Dollars baseCharge()
        {
            double result = Math.Min(lastUsage(),100)*0.03);
            if (lastUsage() > 100)
            {
                result += (Math.Min(lastUsage(),200)-100)*0.05;
            }
            if (lastUsage() > 200)
            {
                result += (lastUsage()-200)*0.07;
            }
            return new Dollars(result);
        }
        修改为:
        protected Dollars baseCharge()
        {
            double result = usageInRarge(0,100)*0.03;
            result += usageInRarge(100,200)*0.05;
            result += usageInRarge(100,Int32.MaxValue)*0.07;
            return new Dollars(result);
        }
        protected double usageInRarge(int start, int end)
        {
            if (lastUsage() > start)
            {
                return Math.Min(lastUsage(),end)-start;
            }
            else
                return 0;
        }

六:以明确函数取代参数(Replace Parameter with Explicit Methods)
    1:如果有一个函数,其内完全取决于参数值而采取不同反应
        针对参数的每一个可能值,建立一个独立函数
        void setValue(String name, int value)
        {
            if (name.Equals("height"))
            {
                _height = value;
                return;
            }
            if (name.Equals("width"))
            {
                _width = value;
                return;
            }
        }
        改为:
        void setHeight(int arg)
        {
            _height = arg;
        }
        void setWidth(int arg)
        {
            _width = arg;
        }

七:保持对象完整(Preserve Whole Object)
    1:从某个对象中取出若干值,将它们作为某一次函数调用的参数:改使用传递整个对象
        int low = daysTempRange().getLow();
        int high = daysTempRange().getHigh();
        withinPlan = plan.withinRange(low, high);
        改为:
        withinPlan = plan.withinRange(daysTempRange());
    2:动机
        有时候,会将来自同一对象的若干项数据作为参数,传递给某个函数。
        这样做的问题在于万一将来被调用的函数需要新的数据项,你就必须查找并修改次函数的左右调用。
        如果吧这些数据所属的整个对象传给函数,就可以避免这种尴尬的处境。
        注意:如果所传参数之间没有依存关系,就不能再传递对象了,否则会使依存结构恶化

八:以参数取代参数(Replace Parameter with Method)
    1:对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数也可以调用前一个函数。
        让参数接受者去除该项参数,并直接调用前一个函数
        int basePrice = _quantity * _itemPrice;
        discountLevel = getDiscountLevel();
        double finalPrice = discountedPrice(basePrice, discountLevel);
        改为:
        int basePrice = _quantity * _itemPrice;
        double finalPrice = discountedPrice(basePrice);
    2:可以通过其他途径而非参数列表获得参数值,就不应该通过参数取得该值。通常长的参数列表会增加程序的理解难度。


九:引入参数对象(Introduce Parameter Object)
    1:某些参数总是很自然的同时出现,以一个对象取代这些参数
        amountInvoicedIn(start:Date, end:Date);
        amountReceivedIn(start:Date, end:Date);
        amountOverdueIn(start:Date, end:Date);
        改为:
        amountInvoicedIn(DateRange);
        amountReceivedIn(DateRange);
        amountOverdueIn(DateRange);
    2:动机
        常常会看到特定的一组参数总是一起被传递,且可能好几个函数都使用这一组参数。

十:移除设置函数(Remove Setting Method)
    1:如果类中某个值域在对象初始时被设值,然后就不再改变:去掉该值域的所有设值函数
        如果你为某个值提供了设值函数,这就暗示这个值值域可以被改变。
        如果你不希望在对象初创之后此值域还有机会被改变,那就不要为它提供设值函数。

十一:隐藏某个函数(Hide Method)
    1:有个函数,从来没有被其他任何类用到,将这个函数修改为PRIVATE

十二:以工厂函数取代构造函数(Replace Constructor with Factory Method)
    1:希望在创建对象时不仅仅是对它做简单的构建动作,将CONSTRUCTOR替换为FACTORY METHOD
        Employee(int type)
        {
            _type = type;
        }
        改为:
        static Employee create(int type)
        {
            return new Employee(type);
        }

十三:封装向下转型动作(Encapsulate Downcast)
    1:如果某个函数返回的对象,需要由函数调用者执行向下转型动作:将向下转型动作移到函数中
        Object lastReading()
        {
            return readings.lastElement();
        }
        改为:
        Reading lastReading()
        {
            return (Reading)readings.lastElement();
        }

十四:以异常取代错误码(Replace Error Code with Exception)
    1:某个函数返回一个特定的代码,用以表示某种错误情况:改用异常
    2:可以清楚的将普通程序和错误处理分开,使得程序更容易理解
        这条需要比较认真的方式来处理

十五:以测试取代异常(Replace Exception with Test)
    1:面对一个调用者可预先加以检查的条件,你就抛出一个异常,修改调用者,使它在调用函数之前先做检查。
        double getValueForPeriod(int periodNumber)
        {
            try
            {
                return _values[periodNumber];
            }
            catch (ArrayIndexOutOfBoundsException e)
            {
                return 0;
            }
        }
        改为:
        double getValueForPeriod(int periodNumber)
        {
            if (periodNumber >= _values.Length)
            {
                return 0;
            }
            return _values[periodNumber];
        }
    2:避免异常被滥用
        异常只应该用于异常的,罕见的行为,就是那些长生意料外的错误的行为,而不应该成为条件检查的替代品。

你可能感兴趣的:(设计模式)