iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 4
0
自我挑戰組

再戰軟體工程系列 第 3

『波動拳消除了,然後呢?』 -- 談Code Smell 辨識與消除

在前文中,我們消除了惱人的波動拳,藉由邏輯抽象化的方法,同時提高了程式可讀性與易擴展性。我們先來複習一下,看看上次的結果如下:

public boolean isOK(boolean isRich, int facePoint,
                        boolean hasHouse, boolean hasCar,
                        boolean isPhD, long income,
                        boolean isPlayBoy, boolean isFunny,
                        boolean hasHumor, boolean isGentle) {

        return isGoodLooking(facePoint) &&
                isGoodMaterialLife(isRich, hasHouse, hasCar) &&
                isGoodWork(isPhD, income) &&
                isGoodMind(isPlayBoy, isFunny, hasHumor, isGentle);

    }

    private boolean isGoodLooking(int facePoint) {
        return 90 < facePoint;
    }

    private boolean isGoodMaterialLife(boolean isRich, boolean hasHouse, boolean hasCar) {
        return isRich && hasHouse && hasCar;
    }

    private boolean isGoodWork(boolean isPhD, long income) {
        return isPhD && 3000000 < income;
    }

    private boolean isGoodMind(boolean isPlayboy, boolean isFunny, boolean hasHumor, boolean isGentle) {
        return !isPlayboy && isFunny && hasHumor && isGentle;
    }

再讀一次程式碼後,嗅覺靈敏的您,肯定這個時候已經發現了:Code Smell!!!對的。在解決了波動拳以後,我們馬上讓另一個問題顯現出來了 -- Data Clump。Data clump指的是一個函式需要引入的參數太多(本例中有10個)。要呼叫一個函示需要準備10個變數實在是太多了,他也是會造成可讀性下降的問題,他同時也讓呼叫他的程式片段難以精簡化。

怎麼辦?改嚕!

一般來說,對付Data Clump最標準的作法就是把參數分組,然後物件化。譬如,我們來看看這樣如何:

public boolean isOK(Man man) {

        return isGoodLooking(man.getFacePoint) &&
                isGoodMaterialLife(man.getMaterialCriteria()) &&
                isGoodWork(man.getWorkCriteria()) &&
                isGoodMind(man.getMindCriteria());

    }

    // ...Skipping the rest.

我們把參賽男仕轉化成一個Man類別的物件,這樣一來isOK這個函式就只剩一個變數了。好處是(除了易讀以外),外面的程式片段只要想辦法湊出一個『Man物件』,就可以直接丟給isOK來判斷了。而且,因為Man類別已經被另外定義出來,所以再為了Man物件而另寫Utility類別或定義各種Constructor都會清楚且容易得多。

以此類推,Man類別也把這10種member variable再進行分類,所以顏值、物質條件、工作能力、與心腸好壞都被有系統地分門別類了,這樣一來,前文所說的Interface化與製造靜態工廠也變得更容易了。你看,是不是一舉多得?


這樣就沒有問題了嗎?有啊!當然還有。這樣改完了以後,另一個Code Smell馬上浮現出來了:Feature Envy。這個函式倚賴Man的成員函式太多了。這樣一來,也許可以考慮把控制權反過來,讓Man這個Interface去控制通不通過這件事。當然,你也可以就此打住,原因是你研判這樣一來程式邏輯與思考邏輯顛倒過來了,反而看不懂,而且說不定會很難寫。

可以不改嗎?當然可以。設計程式架構其實很怕Over Design。設計的架構只要做到『能清楚表達意圖,並兼顧可擴展性』,其實就很棒了。過度追求完美的設計,有時會造成RD花費太多時間在很少的收益上,那就划不來了。

身為工程師,我們只要隨時保持一個想要**『持續改善』**的心,在看到不易讀且擴展不易的程式碼時,想辦法為後人鋪個好路,就很有功德了。至於要做到什麼程度,就要看付出與收益的比例如何嚕!


上一篇
『DoD』 -- 論定義完成的重要性
下一篇
『等價類劃分法』 -- 談測試的基本:快速建立所有可能案例
系列文
再戰軟體工程30

尚未有邦友留言

立即登入留言