首页 > 其他分享 >重构 - 10 简化条件逻辑

重构 - 10 简化条件逻辑

时间:2022-10-23 00:00:58浏览次数:45  
标签:重构 anInstrument return 10 double 条件逻辑 public 表达式

10 简化条件逻辑

目录

分解条件表达式

对条件判断和每个条件分支分别运用提炼函数手法。

将大块头代码分解为多个独立的函数,并根据每个小块代码的用途,为分解得到的新函数命名。

重构前:

if (!aData.isBefore(plan.summerStart) && !aData.isAfter(plan.summerEnd)) {
    // 计算夏季总价
    charge = quantity * plan.summerRate;
} else {
    // 计算平时总价
    charge = quantity * plan.regularRate + plan.regularServiceCharge;
}

重构后:

if (summer()) {
    charge = summerCharge();
} else {
    charge = regularCharge();
}
charge = summer() ? summerCharge() : regularCharge();

合并条件表达式

当检查条件各不相同,但最终行为却一致时,应该使用 “逻辑或” 和 “逻辑与” 将它们合并为一个条件表达式。

做法:

  • 使用适当的逻辑运算符,将条件表达式合并为一个(顺序执行的条件表达式使用逻辑或;嵌套的 if 语句使用逻辑与)
  • 对合并后的条件表达式实施提炼函数

使用逻辑或合并条件表达式

重构前:

public double disabilityAmount(anEmployee) {
    if (anEmployee.seniority < 2) {
        return 0;
    }
    if (anEmployee.monthsDisabled > 12) {
        return 0;
    }
    if (anEmployee.isPartTime) {
        return 0
    }
    // 计算伤残金
}

重构后:

public double disabilityAmount(anEmployee) {
    if (isNotEligableForDisability()) {
        return 0;
    }
    // 计算伤残金
}

// 没有资格获得伤残金的
private boolean isNotEligableForDisability() {
    return anEmployee.seniority < 2 
    || anEmployee.monthsDisabled > 12
    || anEmployee.isPartTime;
}

使用逻辑与合并条件表达式

重构前:

if (anEmployee.onVacation) {
    if (anEmployee.seniority > 10) {
        return 1;
    } 
}
return 0.5;

重构后:

if (anEmployee.onVacatopm && anEmployee.seniority > 10) {
    return 1;
}
return 0.5;

以卫语句取代嵌套条件表达式

条件表达式通常有两种风格:

  • 如果两条分支都是正常行为,则应该使用 if...else... 条件表达式
  • 如果某个条件极其罕见,旧应该单独检查该条件,并且在条件为真时立刻从函数中返回(卫语句)

范例1

重构前:

public double getPayAmount() {
    double result;
    if (isDead) {
        result = deadAmount();
    } else {
        if (isSeparated) {
            result = separatedAmount();
        } else {
            if (isRetired) {
                result = retiredAmount();
            } else {
                result = normalPayAmount();
            }
        }
    }
    return result;
}

重构后:

public double getPayAmount() {
    if (isDead) {
        return deadAmount();
    }
    if (isSeparated) {
        return separatedAmount();
    }
    if (isRetired) {
        return retiredAmount();
    }
    return normalPayAmount();
}

范例2 将条件反转

重构前:

public double adjustedCapital(anInstrument) {
    double result = 0;
    if (anInstrument.capitail > 0) {
        if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
            result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
        }
    }
    return result;
}

重构后:

public double adjustedCapital(anInstrument) {
    if (anInstrument.capitail <= 0) {
        return 0;
    }
    if (anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
        return 0;
    }
    return (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
public double adjustedCapital(anInstrument) {
    if (anInstrument.capitail <=> 0 
    || anInstrument.interestRate <>= 0 
    || anInstrument.duration <= 0) {
        return 0;
    }
    return (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}

以多态取代条件表达式

以多态取代条件表达式的场景:

  • 有多处地方出现 swtich 基于不同类型做出不同的处理
  • 有一个基础的逻辑(超类),在其上又有一些变体(子类)

重构前:

// 不同鸟类的速度
switch (bird.type) {
    case "EuropeanSwallow":
        return 35;
    case "AricanSwallow":
        return 40 - 2 * bird.numberOfCoconuts;
    case "NorwegianBlueParrot":
        return bird.isNailed ? 0 : (10 + bird.voltage / 10);
    default:
        return null;
}

重构之后:

BirdFactory.createBird(birdType).getSpeed();
class BirdFactory() {
    public static createBird(String birdType) {
        switch (birdType) {
            case "EuropeanSwallow":
                return new EuropeanSwallow();
            case "AricanSwallow":
                return new AricanSwallow();
            case "NorwegianBlueParrot":
                return new NorwegianBlueParrot();
            default:
                return new Bird();
        }
    }
}

class Bird {
    public double getSpeed() {
        return null;
    }
}

class EuropeanSwallow extends Bird {
    @Override
    public double getSpeed() {
        return 35;
    }
}

class AricanSwallow extends Bird {
    @Override
    public double getSpeed() {
        return 40 - 2 * bird.numberOfCoconuts;
    }
}

class NorwegianBlueParrot extends Bird {
    @Override
    public double getSpeed() {
        return bird.isNailed ? 0 : (10 + bird.voltage / 10);
    }
}

引入特例

当一个数据结构的使用者都在检查某个特殊的值,就可以使用特例模式。

特例模式(Special Case):创建一个特例元素,用以表达对这种特例的共用行为的处理。
通常需要特例处理的值就是 null 值,这个也是这个模式常被叫做 “Null 对象” 模式的原因。

重构前:

// 第一处地方
String customerName;
if (customer == null) {
    customerName = "occupant";
} else {
    customerName = customer.getName();
}

// 第二处地方
double plan;
if (customer == null) {
    plan = registry.getBillingPlans().getBasic();
} else {
    customer.getBillingPlan();
}

// ...

重构后:

class Customer {
    // ...
}

// 引入特例
class UnknownCustomer extends Customer {
    @Override
    public String getName() {
        return "occupant";
    }

    @Override
    public String getPlan() {
        return registry.getBillingPlans().getBasic();;
    }
}
// 第一处地方
String customerName = customer.getName();

// 第二处地方
double plan = customer.getBillingPlan();

// ...

引入断言

使用断言来对明确地表达某种假设。

断言用于预防程序员的错误,对于输入外部数据都应该执行检查而不能用断言实现。

// 折扣应该不小于 0
assert this.discountRate >= 0;
if (this.discountRate > 0) {
    base = base - (this.discountRate * base);
}

参阅

  • 《重构:改善既有代码的设计(第2版)》

标签:重构,anInstrument,return,10,double,条件逻辑,public,表达式
From: https://www.cnblogs.com/liaozibo/p/simplifying-conditional-logic.html

相关文章

  • 10.22-10.23图论总结
    虽然刷的大部分都是水题,但也是花费时间了的。所以还是总结一下吧。3239:最短路求\(1\)到\(n\)的最短路。思路:直接单源最短路模板。点击查看代码#include<iostream>#i......
  • 【闲话】2022.10.22
    闲话今天到了酒店后的第一场考试完全不会,寄了而且这个VSCode比考试题还寄键盘手感还凑合着毕竟之前打了两把雀食磨合了一下打了三发搜,润了。骗分的事嘛,要分,不磕碜(((......
  • 10、CPU 如何读写数据的?
    先来认识CPU的架构,只有理解了CPU的架构,才能更好地理解CPU是如何读写数据的,对于现代CPU的架构图如下:可以看到,一个CPU里通常会有多个CPU核心,比如上图中的1号和......
  • 1022总结
    本周内容异常处理生成器相关两种异常 1.语法异常 2.逻辑异常异常结构 异常为位置 异常类型 异常详情try句式可能有问题代码 except预测错误类型(可连续......
  • 2022/10/22 CSP赛前隔离时的模拟赛 1/3
    T1T2使用一种类似于摩尔投票法的东西(Keven_He说像,我不太觉得):将所有人分为两队,设第一队的总攻击力为\(a\),第二队的总攻击力为\(b\)。不妨设\(a\leb\),求\(\min(b-......
  • vue笔记 10 webpack 安装命令npm install [email protected] -g
             ......
  • 10月22号:学习日记(函数)
    C语言中函数的分类1.库函数(在使用过程中频繁使用)2.自定义函数#include<stdio.h>#include<stdlib.h>#include<time.h>#include<string.h>intmain(){//strcpy-stringc......
  • 20221022学习笔记-爬虫基础
    爬虫概述爬虫的概念:网络爬虫(又称为网络蜘蛛,网络机器人)就是模拟客户端(主要指浏览器)发送网络请求,接收请求响应,一种按照一定的规则,自动抓取互联网信息的程序。原则上,客......
  • 工业智能物联网网关BL110对接亚马逊AWS
    BL110是一款各种PLC协议、ModbusRTU、ModbusTCP、DL/T645、IEC101、IEC104、BACnetIP、BACnetMS/TP等多种协议转换为ModbusTCP、OPCUA、MQTT、BACnetIP、华为云IoT......
  • 周六1900C++班级20221022-for循环
    for语法:for(initialization;test-condition;increment){statement-list;}for构造一个由4部分组成的循环:初始化,可以由0个或更多的由逗号......