Exception VS Control Flow
每當(dāng)提到Exeption就會有人跳出來說“Exception not use for flow control”,那到底是什么意思呢?什么情況下Exception就算控制流程了,什么時候就該拋出Exception了呢?首先什么是Exception?
Definition:
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.
再看什么是“流程”?如果流程是指程序的每一步執(zhí)行,那異常就是控制流程的,它就是用來區(qū)分程序的正常流程和非正常流程的,從上面異常的定義就可以看出。因此為了明確我們應(yīng)該說”不要用異常控制程序的正常流程“。如何定義正常流程和非正常流程很難,這是一個主觀的決定,沒有一個統(tǒng)一的標(biāo)準(zhǔn),只能根據(jù)實際情況。網(wǎng)上找個例子:
bool isDouble(string someString) {
try {
double d = Convert.ParseInt32(someString);
} catch(FormatException e) {
return false;
}
return true;
}
這個程序其實不是想convert數(shù)字,而是想知道一個字符串是否包含一個數(shù)字,通過判斷是不是有異常的方式來決定返回true還是false,這是個Smell,這種應(yīng)該算”異常控制了正常流程“。我們可以通過正則表達(dá)式或其他方式來判斷。try {
double d = Convert.ParseInt32(someString);
} catch(FormatException e) {
return false;
}
return true;
}
另外Clean Code上一個例子:
try {
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
MealExpensesNotFound異常影響了正常的計算m_total的業(yè)務(wù)邏輯。對于這種情況可以通過一下方式改進(jìn):MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
public class PerDiemMealExpenses implements MealExpenses {
public int getTotal() {
// return the per diem default
}
}
public int getTotal() {
// return the per diem default
}
}
以上兩個例子是比較明顯的異常控制正常流程,Smell很明顯,不會有很大爭議,但是實際情況中可能有很多例子沒有這么明顯,因為都是主觀判定的。比如一下代碼,算不算異常控制正常流程?
public int doSomething()
{
doA();
try {
doB();
} catch (MyException e) {
return ERROR;
}
doC();
return SUCCESS;
}
{
doA();
try {
doB();
} catch (MyException e) {
return ERROR;
}
doC();
return SUCCESS;
}
看到這樣一段程序,如果沒有上下文,我們無法判斷。但是如果doSomething是想讓我們回答yes or no,success or error,我們不應(yīng)該通過有無異常來判斷yes or no,success or error,應(yīng)該有個單獨的方法來判斷,這個方法就只做這一件事情。如果doSometing是執(zhí)行一個操作,那么在這個過程中我們假定是不會出現(xiàn)問題的,否則拋出異常是比較合理的。
posted @ 2012-10-30 17:03 *** 閱讀(248) | 評論 (0) | 編輯 收藏