clean code - 错误处理

错误处理
  • 当错误发生时,程序员有责任确保代码正常工作。
  • 错误处理很重要,但如果它搞乱了代码逻辑,就是错误的做法。
使用异常而非返回码

7-1

public class DeviceController{
    ...
    public void sendShuntDown(){
        DeviceHandel handle = getHandel(DEV1);
        //Check the ststus of the device
        if(handle != DeviceHandel.INVAILD){
            //Save the device status to the record field
            retrieveDeviceRecord(handle);
            //if not suspended ,shut down
            if(record.getStatus()!= DEVICE_SUSPENDED){
                pauseDevice(handle);
                clearDeviceWorkQueue(handle);
                closeDevice(handle);
            } else{
                logger.log("Device suspended .Unable to shut down");
            }
        }else{
            logger.log("Invalid handel for :"+DEV.toString());
        }
    }
    ...
}

代码7-1的问题在于,调用者在调用这段代码之后必须即刻检查错误,如果返回了不同的错误代码,调用者还要做出不同的逻辑处理,这个步骤也是我们常常忽略的。

7-2

public class DeviceController{
    ...

    public void sendShutDown(){
        try{
            tryToShutDown();
        }catch(DeviceShutDownError e){
            logger.log(e);
        }
    }
    private void tryToShutDown() throws DeviceShutDownError{
        DeviceHandle handle = getHandle(DEV1);
        DeviceRecord record = retrieveDeviceRecord(handle);
        pauseDevice(handle);
        clearDeviceWorkQueue(handle);
        closeDevice(handle);
    }

    private DeviceHandle getHandle(DeviceID id){
        ...
        throw new DeviceShutDownError("Invalid handle for:" + id.toString());
        ...
    }
}

遇到错误时,最好抛出一个异常,这会保持调用者代码的整洁度,而且其逻辑不会被错误处理搞乱。

先写Try-Catch-Finally语句
  • 某种意义上,try代码块就像是事务,catch代码块将程序维持在一种持续状态
使用不可控异常
  • 如果你在方法中抛出可控异常,而catch语句在三个层级之上,你就得在catch语句和抛出异常之间繁荣每个方法签名中声明该异常。
  • 封装被打破,因为在抛出路径中的每个函数都要去了解下一层级的异常细节。
给出异常发生的环境的说明
  • 你抛出的每个异常,都应当提供足够的环境说明,以便判断错误的来源和处所。
依调用者需要定义异常类
  • 当我们在应用程序中定义异常类时,最重要的考虑应该是他们如何被捕获。
ACMEPort port = new ACMEPort(12);
try{
    paro.open();
} catch(DeviceResponseException e){
    reportPortError(e);
    logger.log("Device response exception" ,e);
}catch(ATM1212UnlockedException e){
    reportPortError(e);
    logger.log("Unlock exception" ,e);
}catch(GMXError e){
    reportPortError(e);
    logger.log("Device response exception");
}finally{
    ...
}
LocalPort port = new LocalPort(12);
try{
    port.open();
}catch(PortDeviceFailure e){
    reportError(e);
    logger.log(e.getMessage(),e);
}finally{
    ...
}


public void LocalPort{
    private ACMEPort innerPort;
    public LocalPort(int portNumber){
        innerPort = new ACMEport(portNumber);
    }

    public void open(){
        try{
            innerPort.open();
        }catch(DeviceResponseException e){
            reportPortError(e);
            logger.log("Device response exception" ,e);
        }catch(ATM1212UnlockedException e){
            reportPortError(e);
            logger.log("Unlock exception" ,e);
            }catch(GMXError e){
            reportPortError(e);
            logger.log("Device response exception");
        }finally{
        ...
        }
    }
}
定义常规流程
  • 创建一个类或者配置一个对象,用来处理特例。
    特例模式:
try{
    MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
    m_totle += expenses.getTotal();
}catch(MealExpensesNotFound e){
    m_total += getMealPerDiem();
}
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_totle += expenses.getTotal();

public class PerDiemMealExpenses implements MealExpenses{
    public int getTotal(){
        ...
    }
}
别返回null值
  • 如果你打算在方法中返回null值,不如抛出异常,或是返回特例对象。
public List getList(){
    ...
    if(lis != null){
        return lis;
    }else {
        return Collections.emptyList();
    }
}
  • 尽量避免NullPointerException的出现,代码也就更整洁了。
别传递null值
  • 在方法中返回null值是糟糕的做法,但将null值传递给其他方法就更糟糕了。
  • 没有良好的方法能对付由调用者意外传入的null值,恰当的做法就是禁止传入null值.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值