iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Mobile Development

我的怨念齊天高 之「為什麼我的專案死掉了!」系列 第 17

豆技巧到底實用不實用呢?

豆知識是指各種很瑣碎、不成系統、缺乏邏輯連貫性的零碎條目知識。
像「隨便在自己啟動的Thread中更新UI內容會導致AndroidAPP當機喔!」這就是種豆知識。

那...豆技巧呢?
最知名的豆技巧:請計算連續數字M~N的總和。
菜鳥會乖乖用矩陣計算答案,(如果這是場考試,這題就會拿零分。)

int sum = 0
for(int i = M ; i <= N ;i++){
  sum += i;
}

但正確答案是用梯形面積的數學公式去計算。

int sum = (M + N)(N - M)/2;

明明需要計算「連續數字M~N的總和」的情境,在現實中幾乎是可遇不可求,但某些(還算常見的)程式設計教育(藉由這種考題)會讓工程師以為「正確使用矩陣、習慣使用矩陣、堅定使用矩陣,是徒勞無益且多餘的行為。」

一件很明確的事情有個很明確的答案,這個答案就是豆技巧。既然都是種「豆」,豆技巧一樣也是各種很瑣碎、不成系統、缺乏邏輯連貫性的零碎條目程序。

一個物件的「建構式」是種豆知識,但很多物件的「建構式」擺在一起卻可能有種「系統」與「邏輯連貫性」。用建構式做例子會有點狹隘,在禮拜五的晚上,我一時也想不到(也沒那個力氣尋找)更好的例子了。

但有些豆技巧還真的挺重要,而且變化起來很方便,就不會「只能用在考試中」。

像「把十進位轉換成十六進位」。


String hex(int n){
  String hexString = "0123456789ABCDEF";
  return hextString.getCharAt(n);
}

上面這個函數還需要補足一些「大於16」的邏輯判斷和遞迴應用。
hexString其實就是個「0~F」的字元符號矩陣,字元在矩陣中的位置剛好對應了「0~15」。
如果可以從中看出「不需要判斷」「直接用參數決定要取用哪些東西」的設計概念,那可以應用在很多地方。

像下面這樣的例子...


void test(int index){
   if(index == 0){
    ...
   }
   else if(index == 1){
    ...
   }
   else if(index == 2){
    ...
   }
}

範例中已經很「體貼」的使用了0/1/2...作為index的判斷值,但現實中這樣寫程式是作死!
首先,為了方便使用這個test函數,(假設它是個library/module,寫它的人未必是用它的人,)就需要讓使用者知道可以傳入哪些數值,所以會有一排精準定義過名稱(看了就知道幹嘛)的參數在物件中。
例如.......

final int Test_Index_0 = 0;
final int Test_Index_1 = 1;
final int Test_Index_2 = 2;

這樣,使用者就知道可以帶這些參數進test中。(名字當然可以取的更好懂,例如直接表達這個參數的目的,例如「Test_Index_Init」「Test_Index_Loop」這種形式。)

接著,這樣寫出來的程式很冗長,很難擴充跟維護。

像「如果要新增幾個Test_Index_3/Test_Index_4/Test_Index_6(跳過Test_Index_5)
」呢?

將if..else改成switch?這野心太小。

首先要擴充參數...

final int Test_Index_0 = 0;
final int Test_Index_1 = 1;
final int Test_Index_2 = 2;
final int Test_Index_3 = 3;
final int Test_Index_4 = 4;
final int Test_Index_6 = 6;

我們導入設計模式中的策略模式吧!先定義一個策略模式...

interface TestFunction{
  void func(int v);
}

class Test0 implements TestFunction{...}
class Test1 implements TestFunction{...}
class Test2 implements TestFunction{...}
class Test3 implements TestFunction{...}
class Test4 implements TestFunction{...}
class Test6 implements TestFunction{...}

然後來重新修改剛剛的test函數...


TestFunction[] funcs = {
   new Test0(), new Test1(), new Test2(), new Test3(), new Test4(), null, new Test6()
}

void test(int index, int v){
   if(funcs[index] != null)
     funcs[index].func(v);
}

這樣,程式就會變得很好擴充。未來即使要再新增更多對應功能,也只需要將新功能用物件實作後,在funcs中新增該物件的實體即可讓新功能被test函數使用。

(看過專案起始的工程師不懂這個技巧,就只使用switch,然後接手的工程師就把擴充維護給搞砸搞爛了......)


上一篇
關於除錯這件事
下一篇
恐怖的全端工程師
系列文
我的怨念齊天高 之「為什麼我的專案死掉了!」20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言