《Clean Code》总结 异常

[size=large][b]1.使用异常而不是错误码[/b][/size]
如果使用错误码,调用者,必须在方法调用后立即检查结果,如果多次调用都放回错误码,就会造成复杂的多层嵌套结构。
if (deletePage(page) == E_OK) {
if (registry.deleteReference(page.name) == E_OK) {
if (configKeys.deleteKey(page.name.makeKey()) == E_OK){
logger.log("page deleted");
} else {
logger.log("configKey not deleted");
}
} else {
logger.log("deleteReference from registry failed");
}
} else {
logger.log("delete failed");
return E_ERROR;
}

[size=large][b]2.使用uncheck异常[/b][/size]
java世界就checked exception的优劣争论了很久。没有checked异常的也能构建robust的程序。为了robust而使用checked异常的代价太高了。checked异常最大的问题在于它是的程序违反了 开放/封闭原则 调用者不得不捕捉异常或者声明抛出异常。如果底层的异常修改了,高层代码也要修改。如果异常在较高层次处理,就会造成一串的修改。

[size=large][b]3.为了调用者的方便,封装异常调用代码[/b][/size]
很多标准库或者第三方库的方法调用会抛出多个checked异常,对一长串异常处理的代码显得太冗长,而直接捕捉Exception又会丢失很多细节。一个解决方法就是,使用单独的类或方法封装抛出异常的方法调用,做一些处理后抛出unchecked异常,方便上层调用。
ACMEPort port = new ACMEPort(12);
try {
port.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 {

}
做如下封装
public class LocalPort {
private ACMEPort innerPort;

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

public void open() {
try {
innerPort.open();
} catch (DeviceResponseException e) {
throw new PortDeviceFailure(e);
} catch (ATM1212UnlockedException e) {
throw new PortDeviceFailure(e);
} catch (GMXError e) {
throw new PortDeviceFailure(e);
}
}
}

高层代码只需要处理DeviceResponseException。这样做也使得第三方代码的传播度更小,也更方便mock方法调用。

[size=large][b]4.不使用异常处理正常逻辑,比如下面的代码[/b][/size]
try {
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}

异常弄乱了正常的逻辑。解决方法是让ExpenseReportDAO始终返回MealExpenses,如果MealExpenses not found,可是返回一个特殊的MealExpenses
public class PerDiemMealExpenses implements MealExpenses {
public int getTotal() {
// return the per diem default
}
}

这叫着SPECIAL CASE PATTERN [Fowler],You create a class or configure an object so that it handles a special case for you.

[size=large][b]5.不要返回Null。[/b][/size]
方法调用如果允许放回null,会大大增加调用者的复杂度。可以考虑抛出异常,或者使用Null Object或者特殊的对象。例如
List employees = getEmployees();
if (employees != null) {
for (Employee e : employees) {
totalPay += e.getPay();
}
}
------
public List getEmployees() {
if (.. there are no employees ..)
return Collections.emptyList();
}

如果没有Employee,就返回一个空的List,这样调用者可以不用做特殊的处理。

[size=large][b]6.不要传递null到方法。[/b][/size]
如果参数可为null,方法不得不做必要的检查,代码会很冗余,而且没有很好解决方案。

你可能感兴趣的:(Java)