2013年10月26日 星期六

「Coding」與「創意」: 別把賣弄當創意

「創意」是很重要的一件事, 但在 coding 或軟體發展, 過度的濫用常常是適得其反. 最近看到一篇有趣的文章, 讓我想寫這篇來與大家分享一些看法.

該文提到一個面試的題目 (詳見原文), 最後一個 "台灣面談者" 的解法頗具創意, 時間複雜度"理論上"也不差. 但我的comment是: 若我是軟體部門的主管, 除非這位仁兄有分析或解釋在何種場合要如此做, 我不會雇用這位仁兄. 理由是: 縱然這解法有趣有創意, 但有overflow的問題, 且更重要的是程式比較難看懂難維護.

類似地, 以前上課時常舉的例子: 有一家公司對應徵者, 常會考一個簡單的基本問題: SWAP(x,y), 將變數值 x,y 交換. 一位面談者的答案是: x ^= y ^= x ^= y; 可以省下一個記憶空間, 很有創意吧! 但那公司後來決定不雇用他. 原因是: 這解法還是有潛在問題(e.g., SWAP(x,x)), 且這樣的軟體很難維護.

好, 這時你可能會質疑我: 我們不是都在鼓勵有創意嗎? 你是教授, 反而要抹煞創意.

我的回答是: 我同意「創意」很重要, 但更重要的是要分析這個「創意」在整個軟體是否達到特定的成效; 在程式中, 有簡明的做法, 反而用更複雜難懂的技巧且無較好的效果, 這樣的創意是沒太大意義的.

試想當一個人維護程式時, 看到 "x ^= y ^= x ^= y;" 是否要多花個上分鐘來檢視這是否正確. 你可能認為這只是幾分鐘而已, 但一個程式裡, 若有好幾個類似的寫法, 維護程式就得多了好幾倍時間, 這對軟體發展及維護都是很嚴重的情形.

當然若你清楚會有產生效果時, 那當然另當別論. 例如, 我聽說我一位學生到一家很賺錢公司面談, 面談官問了一個題目: 寫 bitcount: 將一個整數中, 含有1的位元加總起來, 這是假設CPU沒有這樣指令. 原來的面談官應該只期望回答簡單的 a loop with "shift 1 bit" and "test LSB". 但我學生就立即回答我們 computer game 常用的快速作法:

    int Bitcount(unsigned long long b)
    {
        b = ( b & 0x5555555555555555 )
            + ( ( b >> 1 ) & 0x5555555555555555 );
        b = ( b & 0x3333333333333333 ) 
            + ( ( b >> 2 ) & 0x3333333333333333 );
        return ((( b + (b >> 4) ) & 0x0f0f0f0f0f0f0f0f ) 
            * 0x0101010101010101 ) >> 56;
    }

有趣的是反而把面談官考倒, 讓面談官想了好幾分鐘.

從速度的角度, 這是很好的答案, 但更重要的是要分析在何種場合用何種做法. 若速度要求很低時, 這寫法反而不見得好, 有可能增加維護上的負擔.

因此, 我常在上課時告誡同學, 好的程式工程師, 不只是要很會寫程式及會很多演算法, 更重要的是會分析. 例如, 要建一個 data structure 做資料搜尋 (假設沒有library可用). 最簡單的是 linear search on array, 但大家都知道有很多問題, 當資料量大時很耗時, 且大小的彈性不好. 較進階的有 red-black tree, b-tree, hash table 等, 但開發時間較久. 好的軟體工程師, 就要能分析給主管, 若明天就要一個簡易測試版, 就用 linear array, 以後再來改寫更精緻的資料結構. 若他為了賣弄他在演算法學到的技巧, 一味地就用進階的做法, 很可能搞了幾天幾周都還未必好, 且影響軟體開發.

結論是: 軟體設計更重要是在於分析, 千萬不要賣弄技巧, 除非你知道你在做甚麼.