[105] Single Exit Point...or Not

底下兩個函數功能完全一樣,皆是計算一 UI 元件(Label)在給定的範圍(Bounds)內,總共需要多少行數。本文的重點不在函數的功能,而是要討論兩種不同的寫碼風格。小細節也有大學問,不要輕忽。

① 此版本使用一個暫時變數 line_count 存放計算結果,函數回傳值即為該變數的值。特別留意這個版本的函數只有一個 return statement。

int CalcLineCountOfLabel(const Label& label)  
{
    const auto label_total_width = label.getFont().getStringWidth(label.getText());
    const auto bound_width = label.getLocalBounds().getWidth();

    int line_count = 1;
    if (label_total_width > bound_width)
        line_count += label_total_width / bound_width;

    return line_count;
}

② 此版本沒有那個暫時性變數,而且在有辦法知道結果時即將值回傳。這個版本有二個 return statement。

int CalcLineCountOfLabel(const Label& label)  
{
    const auto label_total_width = label.getFont().getStringWidth(label.getText());
    const auto bound_width = label.getLocalBounds().getWidth();

    if (label_total_width <= bound_width)
        return 1;

    return 1 + (label_total_width / bound_width);
}

我最先寫成版本 ①,然後才重構成 ② 版。除了少一個暫時變數,我也偏愛函數提前返回的風格,而不堅持函數只能有一個返回點(Exit Point)

由於此函數僅短短十行不到,容易理解。若是在較大的函數裡,有時候 ① 的寫作風格比較適合。

函數即「接收輸入,然後產生輸出」的...一塊程式碼。欲理解巨型函數,我常用的手法是先看返回值,此時若有區域變數代表返回值,則該變數可扮演「導遊」的角色,帶我走遍函數裡的風景名勝。在超巨型的函數裡,這樣的變數堪稱是希望的燈塔,民族的救星⋯⋯

在這樣的情境下,寫作風格 ① 佔有不小優勢。不過,歸根究底,最好不要寫出超過一百行的函數,否則會被打小屁屁!🔚

CTO of I³D Technology Inc. 🇹🇼 ▐ Blogging at https://samtsai.org ▐ Playing WorkFlowy at http://workflowy.tips/ ▐ Learn what I am doing: https://samtsai.org/now/