本節書摘來自華章計算機《編寫高品質代碼:改善c程式代碼的125個建議》一書中的第3章,建議17-4,作者:馬 偉 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
在代碼中,如果某個函數的if語句嵌套太深,為了程式的可讀性、可維護性與效率,我們應該盡量想辦法進行重構,以減少if語句的嵌套層數,如下面的示例代碼所示:
在上面這個簡單的示例代碼中,我們使用了4層if嵌套。為了減少程式中if語句的嵌套層數,我們首先能夠想到的辦法就是可以通過重複檢測條件中的某一部分來簡化嵌套的if語句,如下面的示例代碼所示:
通過上面的代碼,我們可以清楚地看到通過重複檢測條件中的某一部分來簡化嵌套的if語句的辦法并不能無償地減少嵌套層數。同時,作為減少嵌套層數的代價,必須容忍使用一個更複雜的判斷。也就是說,雖然這樣減少了if語句的嵌套層數,但增加了一些複雜的判斷,讓我們有點得不償失的感覺。
既然我們對通過重複檢測條件中的某一部分來簡化嵌套的if語句的辦法不是很滿意,那麼我們還可以使用 if/break塊來簡化if語句的嵌套層數。上面的示例代碼采用if/break塊重構後如下所示:
從上面的代碼可以看出,相對于通過重複檢測條件中的某一部分來簡化嵌套的if語句的辦法,if/break塊真正地實作了邏輯的扁平化,減少了if語句的嵌套層數,進而使代碼看起來比較清晰,增加了程式的可讀性。與此同時,該方法還不會增加複雜的條件判斷,進而可以避免因為重構而導緻的if條件出錯。當然,你還可以使用它的另外兩個相似的if/return和if/goto塊來達到同樣的效果,但這種方法唯一的缺陷就是破壞了程式的内聚性。
除了上面的兩種方法之外,我們還可以通過把代碼分割開來,把深層嵌套的if語句抽取出來放進單獨的函數中。這樣,不僅減少了if語句的嵌套層數,同時,一個好的函數名對代碼也具有自我注解的作用,在一定程度上也可以提高程式的可讀性。但這種方法與前面的方法一樣,程式邏輯的複雜度依然存在,甚至更複雜。
是以,如有可能,我們應該選擇完全重新設計深層嵌套的代碼。在通常情況下,如果程式中存在着比較複雜的邏輯代碼,就說明你還沒有充分地了解程式,進而無法簡化它。是以對程式員來說,深層嵌套的if語句也是一個警告,它說明你要麼想辦法進行重構,要麼重新設計該程式。