當前位置:
首頁 > 最新 > 高質量代碼的特徵

高質量代碼的特徵

回想起來,我覺得我們似乎在誤讀Uncle Bob的Clean Code,至少我們錯誤地將所謂Clean與可讀性代碼簡單地划上了等號。尤為不幸的是,在Clean Code一書中,從第二章到第五章都圍繞著可讀性代碼做文章,於是加深了這種錯誤的印象。

許多具有代碼潔癖的程序員將代碼可讀性視為神聖不可侵犯的真理,並奉其為高質量代碼的最重要特徵,封上了「神壇」。殊不知,Uncle Bob在Clean Code的第一章就通過別人之口對所謂「Clean Code」進行了正名:所謂整潔代碼並非僅僅是「清晰」這麼簡單。

按照Kent Beck的簡單設計規則,排在第一位的其實不是可讀性,而是「通過所有測試」。其中潛藏的含義是滿足用戶正確的需求,因為測試可以看做是用戶提出的需求。這個需求不僅僅是業務上的,還包括質量屬性的需求,例如性能、安全等屬性。

消除重複和提高表達力這兩點,有時候會互相促進,去除了冗餘的代碼,會讓代碼變得更加清晰;然而,有時候卻又互相衝突,消除重複的成本可能會比較高,導致提取了太多細碎微小的實體,反而增加了閱讀障礙。

故而我常常將Uncle Bob提出的「函數的第一規則是要短小。第二條規則是還要更短小。」看做是一種矯枉過正的強迫。對於那種喜歡編寫大函數的程序員而言,確實需要時刻銘記這一原則,但切記不要將其視為最高準則。保證函數短小是有前提的,仔細閱讀Kent Beck的簡單設計原則,依其重要順序:

能通過所有測試;

沒有重複代碼;

體現設計者的意圖;

若無必要,勿增實體(方法、函數、類等)。

如果程序滿足了客戶需求,沒有重複代碼,函數的表達已經足夠清晰地體現設計者意圖,為何還要不斷地提取函數,使得函數變得極為短小呢?真正有意義的原則是「讓函數只做一件事情」。

正因為此,在Clean Code書中,Uncle Bob展示的對FitNesse中HtmlUtil.java的第二次重構並無必要。在經過第一次重構後,代碼如下所示:

public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite ) throws Exception { boolean isTestPage = pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage = pageData.getWikiPage(); StringBuffer newPageContent = new StringBuffer(); includeSetupPages(testPage, newPageContent, isSuite); newPageContent.append(pageData.getContent()); includeTeardownPages(testPage, newPageContent, isSuite); pageData.setContent(newPageContent.toString()); } return pageData.getHtml(); }

這段代碼的結構與層次已經非常清晰,也對實現細節做了足夠合理的封裝與隱藏。若要說不足之處,就是可以將如下代碼再做一次方法提取,以滿足SLAP原則(單一抽象層次原則):

newPageContent.append(pageData.getContent()); //提取為: includeTestContents(testPage, newPageContent)

而Uncle Bob做的第二次重構,除了將方法變得更加短小,隱藏了太多細節從而引入更多層次之外,究竟給代碼的清晰帶來了什麼呢?

public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); }

過猶不及啊!

有時候,為了去除重複,就必須要從相似代碼中尋找到一種模式或者某種抽象,進而對其進行提取。過分的提取反而會讓代碼變得很難閱讀,這是因為提取的手段常常會引入「間接」。正如Martin Fowler所說:「間接性可能帶來幫助,但非必要的間接性總是讓人不舒服」。不必要的間接常常妨礙代碼的直截了當和乾淨利落。倘若去除重複帶來的唯一好處僅僅是避免一個類中少許的私有重複,去除這樣的重複其實意義真的不大。

我喜歡清晰的代碼,但在同時我認為保持代碼的正確、健壯與高效同樣重要。因為代碼潔癖的緣故,我曾經將大量的非空判斷、非法檢查與異常處理視為干擾清晰代碼的洪水猛獸,但如果不做這些「臟活累活」,代碼就可能變得不健壯。在Java中,若真要避免這些判斷,可以考慮轉移職責,通過定義Checked Exception,將異常處理的職責轉移給方法的調用者。然而,職責的盲目轉移始終是不負責任的。實現每個方法和每個類的程序員應該保證自己的代碼是自治的。

如下代碼:

@Override public void run() { if (isFromFile) { if (hasQuery) { throw new RuntimeException("both --execute and --file specified"); } try { query = Files.toString(new File(clientOptions.file), UTF_8); hasQuery = true; } catch (IOException e) { throw new RuntimeException(format("Error reading from file %s: %s", clientOptions.file, e.getMessage())); } } }

這樣的代碼確實談不上優雅,然而足夠充分的判斷保證了代碼的正確性與健壯性。我只能說,在滿足了這兩點的前提下,可以聰明地利用諸如防禦式編程、Optional來規避多餘的嵌套或分支,從而提高代碼的可讀性。

Effective Java總結了高質量代碼的幾個特徵:清晰、正確、可用、健壯、靈活和可維護。我認為這個總結非常中肯。寫代碼真的不要太偏執,不分任何場景一味地追求代碼的可讀(清晰),一味地重申DRY,我覺得都是不負責任的態度。

或許是我老了的緣故,我變得不再理想主義;但更多的原因是因為我看到太多追求所謂「整潔代碼」的程序,不去考慮複雜繁瑣的異外情況帶來程序的不健壯;因為去除重複帶來的不必要間接影響了代碼的簡潔與乾淨,甚至影響了代碼運行的性能。

整潔代碼是必須的,但不是衡量代碼質量的唯一標準!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

曾估值30億美元的智能硬體廠商Jawbone遭清算,創始人成立新公司跑路
Go語言中 select和switch 的比較
掌上維度推出共享充電寶產品「電猿」,這個風口還有戲嗎?
为什么做了这么多,种子用户就是不买帐?
開源雲計算領域 EasyStack一直在拼積木的路上

TAG:推酷 |

您可能感興趣

如何提高代碼質量?
代碼質量-代碼的歷史是代碼未來的預言
高質量發展呼喚高質量職教
栽培技術:怎樣種出高產量高質量的夏枯草
經濟時評:保障高質量數據要有高質量設計
高質量的材料,優良的切割質量,時尚的設計
高質量發展新時代怎麼干?
寫高質量的代碼,永不言晚!
加強管理能提高程序代碼質量嗎?
用高質量教育支撐高質量發展
王一鳴:高質量發展特徵顯現
掃地機器人好用嗎?高顏值高質量高性價比的「三高產品」
天文學家發現超大質量黑洞附近的神秘特徵的實質
智能商業時代的高質量發展
低質量的婚姻,還不如高質量的單身
低質量的合群不如高質量的獨處
加快構建支撐高質量發展的現代產業體系
跑步=高質量的生活
寧可高質量的單身,也不要低質量的婚姻
衣服質量是否優質的4個主要特徵