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啊。