iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
1

良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。

來聊聊 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 的觀點。

在此,不考慮 ifif-else
只討論 if-else-if 這種情況,因為思考方式其實不太一樣。

  1. 要注意判斷的是不是同一系列的事
    (不要一下判斷 A 變數,一下又判斷 B 變數)
    • 判斷字串 A → Z
    • 判斷數字依大小排序
  2. 要注意接下來要執行的邏輯是不是同樣的事
  3. 要注意輸出是不是同一系列的
  4. 最後注意發生頻率是不是一樣的
    • 正常 → 例外
    • 常見 → 不常見
if () {
  //最常執行、正常情況
}
else if () {
  //次常執行,正常情況
}
else {
  //絕對不該發生的例外情況,有時拿來寫 assert
  //或記錄 log 
}

上一篇
不依照文件寫 code
下一篇
不依照語法寫 code
系列文
可不可以不要寫糙 code30

尚未有邦友留言

立即登入留言