良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。
來聊聊 if-else-if
太長的問題。
故事是虛構的,如有雷同,也許真的只是碰巧!!
故事是這樣的,前輩要教新人公司自幹的後端的架構,好讓新人可以接手一個後端的開發案。教著教著,就說「哦!這裡有個問題,(描述問題),然後就只能這樣解決」。
其中一個問題,就是 if-else-if
太長的問題。
這一切都只是傳說而已。(新人也沒碰到,也不確定這個前輩有沒有碰到)
「當初使用的 compiler 是 Borland C++ Builder ,因為公司的技術使用 C++ 寫後端,當 API 開到一定的數量時,就造成 route 非常多,由於這個系統使用 if-else-if
實作 route ,有一天就出錯了,那時測試的結論是說 if-else-if
的長度不可以超過 128 個...」
聽到這裡都傻眼了,這個問題難道沒有被解決嗎?
if-else-if
太長要如何處理呢?先不要討論巢狀 if-else-if
的問題。
故事中的前輩拿出來的 code ,是長這樣的 (程式碼已用 JavaScript 重新實作!)
附上行號,表示「真的很多行」
while( true ) // 150 行
{
try
{
//....
if( URI === `MODIFY_WORK_CENTER` ) {
try{
ModifyWorkCenter(req, res);
SendResponse(`${URI}_RESPONSE`, req, res);
}
catch (...){}
break;
}
if( URI === `DEL_WORK_CENTER` ) {
try {
DelWorkCenter(req, res);
SendResponse(`${URI}_RESPONSE`, req, res);
}
catch (...){}
break;
}
//....
// 7240 行, 你沒看錯,是逼近五位數的四位數
}
catch (...){}
break;
} //7246 行
看出來這個「特殊的技巧」了嗎?
while(true){
if (URI === `URI1`) {
doSomething1();
break;
}
if (URI === `URI2`) {
doSomething2();
break;
}
break;
}
這樣一來,就可以讓 if-else-if
超過 7000 行了呢?!
使用 break;
跳脫 while(true)
並且用 if
選擇是否要執行。
天才!太天才了!而且超用心。
打破了我僵化的思考
對不起我失態了。
if-else-if
都是 ==
時switch-case
可以視為 if-else-if
的一種特例狀況。當 if-else-if
裡的判斷都是相同變數,都是判斷 ==
就可以用 switch-case
switch(URI) {
case `URI1`: doSomething1(); break;
case `URI2`: doSomething2(); break;
//....
}
facroty
const URIs = {}
URIs[`URI1`] = doSomething1
URIs[`URI2`] = doSomething2
function factory(URI) {
if (URIs.includes(URI)) {
return URIs[URI]
}
}
main.js
const doSomething = factory(URI)
doSomething(req, res);
如果語言可以用物件導向,也許可以學一下 Design Pattern!!
工廠模式,可以解決這種問題。
if-else-if
怎麼使用呢?在此分享《Code Complete 2/e》Ch15 的觀點。
在此,不考慮
if
或if-else
只討論if-else-if
這種情況,因為思考方式其實不太一樣。
if () {
//最常執行、正常情況
}
else if () {
//次常執行,正常情況
}
else {
//絕對不該發生的例外情況,有時拿來寫 assert
//或記錄 log
}