短函數有感

前幾天在「TDD和重構練功房」中看到熊老師發了一篇文章叫作"長函數,有如王大媽的裹腳布",這篇文章認爲長函數是一個 bad smell,同時對函數長短的標準進行了量化:c++

一個常見的原則是將方法的行數控制在 5 行以內——《軟件開發沉思錄》編程

5 行以內這一標準簡直讓我感到恐怖,對,不是驚訝,真的是恐怖的感受。 5 行之內的描述空間,這怎麼可能,稍微複雜一點的函數何止幾十行...,深呼吸,冷靜一下,再想一想,這一規則背後到底還有什麼我不知道的,因而就有了如下對話:微信

lyning(我):我沒看錯吧,竟然不是 5 行左右,是 5 行以內?函數

劉光聰:@lyning 這很正常,這幾年遇到的項目(新項目,ai領域)大多都控制在5行之內。都是在@熊節 2011年洗腦以後開始實踐的。學習

lyning(我):感受控制函數行數少是一種使代碼逼近單一職責的手段。3d

熊節:單一職責和恰當的抽象層次。code

熊節:麥肯錫方法,講事情永遠是3-5個點。cdn

lyning(我):熊老師,恰當的抽象層次,怎麼理解這句話呢?對象

熊節:就…好比我跟你講一個事,我知道這個事1分鐘講不完,要講5分鐘這麼個複雜度blog

熊節:我就必定會分紅一二三點,每一點我會強調一下,再具體講裏面的內容,講完之後我會總結一下我講了三個點。

熊節:跟一個幾十行的函數是同樣的。

lyning(我):有點明白了,把大問題要拆分紅小問題,拆分出來的這幾個小問題都屬於這個大問題層面的東西。

熊節:仝老師有個套路,就是每一個問題你始終把它描述成 輸入-處理-輸出 三句話.

劉光聰:

劉光聰:一個小的c++例子,抽象井井有條。

...

從上面能夠對話中能夠獲得如下關鍵字:

  • 單一職責
  • 恰當的抽象層次

熊老師採用比喻描述了什麼是恰當的抽象層次,劉老師可視化了該概念在代碼中的體現。能夠看到一個 10 多行的代碼被重構到 5 行秒懂的函數,看來這個標準仍是可行的嘛。


其實該原則出自《軟件開發沉思錄》對象健身操一節,更「恐怖」的是,對象健身操還列出 9 個堪稱「變態」的原則:

  1. 方法只使用一級縮進(One level of indentation per method)
  2. 拒絕使用else關鍵字(Don’t use the ELSE keyword)
  3. 封裝全部的原生類型和字符串(Wrap all primitives and Strings)
  4. 一行代碼只有一個「.」運算符(One dot per line)
  5. 不要使用縮寫( Don’t abbreviate)
  6. 保持實體對象簡單清晰(Keep all entities small)
  7. 任何類中的實例變量都不要超過兩個(No classes with more than two instance variables)
  8. 使用一流的集合(First class collections)
  9. 不使用任何Getter/Setter/Property(No getters/setters/properties)

還能更短

函數的第一規則是短小。第二條原則是還要更短小

函數應該只作一件事。作好這件事。只作這件事

上面的描述出自 Bob 大叔的《代碼整潔之道》,對於函數應該多小,Bob 大叔提到了他看了 Kent Beck 寫 的一個程序,函數都是隻有三到四行,很是簡潔易懂。最終 Bob 大叔對函數應該多長下了一個定義,他給出了一個只有 3 行函數體代碼的示例,表示函數就應該這麼短。這又一次顛覆了個人價值觀!

單一職責

單一職責是 SOLID 中的首要原則,經過它能夠引出其它原則。能夠發現函數越短,那麼它能作的事情就越少,就越能作好這件事情,也就越能驅動出單一職責的函數。

恰當的抽象層次

對於 add() 這個函數而言,if (readonly)atCapacity()grow()addElement() 這 4 個邏輯體現了同一抽象層次,所以 add() 函數仍是隻作一件事,畢竟編寫函數是爲了把一些大的概念拆分紅另外一個抽象層次的一系列步驟

若是函數體現了很是多的細節,或者處於不一樣的抽象層次,這對於讀者來講簡直是災難,不只如此,亂其實還暗示了做者在當下一樣也是思惟混亂。

編程與思惟

軟件開發就像是一個口耳交替的遊戲,獲取準確的一手信息不容易,把問題描述清楚一樣也不容易。筆者如今以爲編程是一項很是重視描述技巧的活動,表達得是否清楚很大一部分源於人的思惟是否清晰(結構化),也許編程只是基本功,思惟纔是內功,畢竟把問題搞複雜,比弄清晰要簡單得多

良好的描述技巧

要把邏輯抽象化,必須知道某段邏輯在作什麼,而且對函數進行恰當的描述,這裏的難點之一在於它須要良好的描述技巧,好在描述技巧其實也有一些模式和規律可循,厲害的人已經幫咱們提煉了部分模式,能夠參考「名正則言順:聊聊「起名」這件事」

秒懂

上面談了一些模模糊糊的概念,而秒懂應該是短函數的一個最直觀的體現。不過不只僅讓本身秒懂,還要讓讀者秒懂,所以寫好了代碼,應該分(e)享(xin)給其餘的小夥伴,看看小夥伴們的反饋,在反饋中不斷改善代碼。

若是還以爲不過癮,那再看看這個函數,給本身計時看看須要多長時間讀懂:

而後再看看這個:

總結

筆者認爲,短函數的實際價值在於容易維護。處於同一抽象層次的短函數,作的事情越少,須要被理解的概念也就越少,就越不容易出現認知超載。須要強調的是,短函數、恰當的抽象層次和良好的描述,對於大部分人來講,不是一會兒就冒出來的,而是被打磨出來的,怎麼打磨呢?固然是 TDD。


歡迎關注個人微信訂閱號,我將會持續輸出更多技術文章,但願咱們能夠互相學習。

相關文章
相關標籤/搜索