每日一重构-方法重构篇

Introduce Parameter Object(引入参数对象)

个人理解:类似于 func_name(x1,x2,x3,x4,x5,x6,x7,x8.....x23) 这样的函数,参数位置顺序太难记忆了。
改进的方法就是用一个对象取代参数列表func_name(paramObject), 而 paramObject.id paramsObject.name paramsObject.idcard 就没有顺序问题。 这种对象参数还有一个好处,就是可以自己封装对参数校验的方法。

重构后的代码

class DataRange {
    private final Date start;
    private final DAte end;
    DataRange(Date start, Date end){
        this.start = start;
        this.end = end;
    }

    public Date getStart(){
        return start;
    }

    public Date getEnd(){
        return end;
    }

    // 判断时间段的方法提取到这里。
    boolean includes(Date date){
        if( date.equals(getStart()) || date.equals(getEnd()) 
            || (date.after(getStart()) && date.before(getEnd()))){
            return true;
        } else {
            return false;
        }
    }
}

Remove Setting Method (移除设值函数)

个人理解:有些变量只需要在构造函数中初始化后就不会再改变,比如 _id, 就没必要有SetXXX函数的存在。

Hiding Method (隐藏函数)

个人理解:有一个函数,从来没有被其他类访问过,或者有取值or设值方法外部从来不会调用,那就隐藏他们。

Replace Constructor with Factory Method (以工厂函数取代构造函数)

  • 工厂方法参数需要根据type类型创建不同的子类对象,如何避免使用switch呢? 可以使用string类名自动找到对应的类并实例化。
  • 第二种方案是为每个子类创建各自的createXXX 静态方法。 如果子类不多,这种方式也是可以考虑的。

10.14 Replace Error Code with Exception (以异常取代错误码) !important

  • 不受控制异常,调用方需要提前检测
  • 受控制异常, 抛出异常的方法需要自己定义这个异常类。
  • 何谓异常?就是程序运行时出现的异常现象,什么原因导致异常,比如用户输入数据不对程序执行异常,数据库执行突然断开,程序异常,请求3方接口超时,程序异常。 大多数异常都会导致程序需要提前终止(对于web服务更是如此)。对于有提供异常机制的OOP语言,再用像C那样的错误码方式就不太体面。C是没有办法只能以这种方式提供。
  • 抛出异常有助于事务回滚,如果用返回码方式事务回滚可能需要在所有返回码处执行,资源释放也是如此。

我经常在项目看到很多程序员在Service层,写出类似下面的代码:

    public function healthCodeBaseCheck($deviceId, $voucher, $otherData)
    {
        $sid            = $otherData['aid'] ?? 0; //预留手持机的
        $terminalConfig = new TerminalConfig();
        $deviceRes      = $terminalConfig->getDeviceInfoByCache($deviceId);
        if ($deviceRes['code'] != 200) {
            return $deviceRes;
        }
        $rule             = '';
        $deviceInfo       = $deviceRes['data']['deviceInfo'];
        $signConfigConfig = [];
        if ($deviceInfo['device_type'] == Device::TAKE_GATE) {
            //获取闸机签到码配置的供应商和是否开通了那个三码合一
            $terminalConfig = new TerminalConfig();
            $signConfigData = $terminalConfig->getDeviceSignConfig($deviceId);
            if ($signConfigData['code'] != 200) {
                return $signConfigData;
            }
            $signConfigConfig = $signConfigData['data'];
        }
        if ($deviceInfo['device_type'] != Device::TAKE_GATE) {
            return $this->returnData(204, '暂时只支持闸机渠道');
        }

        $aid  = $signConfigConfig['aid'];
        $rule = $signConfigConfig['healthCodeRule'];

        $healthCodeConfigMdl = new HealthCodeConfig();
        $healthConfig        = $healthCodeConfigMdl->getHealthConfigByApplyDid($aid);
        if (empty($healthConfig)) {
            return $this->returnData(204, '健康码配置未创建');
        }
}

在Service层内部中居然还大量使用 [code:xxx, msg:xxx, data:xxx] 这样的返回值。实在是不应该。这种Service类完全是项目中的Service对象。有错误抛出异常即可,执行正确返回想要的值,这才是正确的处理方式。而Service类调用者,有责任去捕获异常,并处理异常。而不是依靠 code 判断是否有错误, 在具备异常处理的OOP的语言中还在使用这种老旧的方法真的很low啊。

Leave a Comment

Your email address will not be published. Required fields are marked *

PHP 8.1.1 - 20.124 ms, 0 Q