函數最初的用處 大家剛學編程的時候,一定還記得為什麼要用函數。那就是把重覆的代碼歸納到一個函數中多次利用。這點毋庸置疑,大家也用的很熟了,但是除了這個還有什麼改進空間嗎?答案肯定是有的! PS.本文不討論面向對象、不討論設計模式,只是把視線聚焦在 Class 內部的函數上。 出現什麼問題了? 大家都 ...
函數最初的用處
大家剛學編程的時候,一定還記得為什麼要用函數。那就是把重覆的代碼歸納到一個函數中多次利用。這點毋庸置疑,大家也用的很熟了,但是除了這個還有什麼改進空間嗎?答案肯定是有的!
PS.本文不討論面向對象、不討論設計模式,只是把視線聚焦在 Class 內部的函數上。
出現什麼問題了?
大家都知道當一個函數很長的時候,就會造成閱讀困難,那以前我們都是怎麼解決的呢?
- 寫註釋:這個大家都知道怎麼用,也是一種有效的方法。
- 用 #region 代碼塊:這個也是一個行之有效的方法。
還有什麼別的方法嗎?其實還有一個方法就是文章的標題:使用短函數。
在討論短函數有點之前,我想先用一點篇幅來講述一下什麼時候改寫註釋。
路人甲:納尼?不是說任何時候都要寫註釋嗎?
什麼時候該寫註釋
函數主要就有兩個用途:
- 在 Class 和 別的函數、欄位、屬性前打三個 / ,就會自動生成供 VS 使用的智能提示內容。
- 解釋代碼意圖。
第一點大家都會用,而且就這麼用,沒有什麼替代的辦法。
但是關於第二點,註釋未必是最好的解決辦法。
因為如果一段代碼讓人看不懂,要麼就是“英文看不懂”,要麼就是“邏輯複雜”。
註釋是為了彌補它們帶來的缺點,但是為什麼不從根本解決呢?
“英文看不懂”:每個程式員都應該有一定的英文基礎吧?另外註意命名規範,就可以解決了。
“邏輯複雜”:如果一段程式邏輯複雜,讓人看不懂,你覺得你應該費力地去給別人解釋呢?還是自己好好整理整理,把代碼梳理一下呢?
那怎麼梳理你的代碼呢?短函數?
短函數的優點——有助於梳理代碼
我想廢話不多說了,都是程式員,大家一看代碼就明白了。
這裡貼上另外一篇文章:《代碼才是最好的註釋》
文章的題目是代碼才是最好的註釋,其實寫的就是短函數的優點。
已經有了文章,我就不重覆工作了。
順便提一下 region ,其實 region 在 VS 下的收縮功能可以達到差不多的效果,你可以選用這個,但是不是很推薦。
下麵,我還要和大家探討一下另一個優點。
短函數的優點——在 .Net 下可優化性能
關於這點,我是在《More Effective C#》中看到的,覺得非常好,所以推薦給大家。
把一個大函數拆分成很多小函數可以優化性能?這點看上去很可笑。是的,其實這點性能的提升微不足道,但是如果可以,為什麼不做呢?更何況這樣做還有上面說的另一個優點。
為什麼長函數分割成短函數的時候可以優化 .Net 下的性能呢?
你首先要明白:
.Net 下的語言編譯的時候只是編譯成了中間語言。運行的時候,它會再一次編譯成機器碼。
這個中間語言編譯成機器碼是以一個函數為基本代為的。也就是說,每次調用函數的時候,這個函數才會被編譯。
那長函數分割成了短函數有優勢嗎?代碼量不還是一樣的?純粹的分割反而會產生更多的代碼呢!
的確如此,所以說,這裡還有另一個條件:當這個長函數中有很多分支的時候。
1 2 3 4 5 6 7 8 9 10 11 |
public void Func1()
{
if (xxxx)
{
//代碼段1,幾百行
}
else
{
//代碼段2,幾百行
}
}
|
上面這段代碼,有兩大段代碼,每次調用這個函數其實只會執行一部分。
所以,如果把這兩塊代碼段提取出來,編譯的過程中就會少編譯一半的代碼。
現在明白在什麼時候把長函數分割成短函數能優化性能了吧。
雖然這點性能提升並不明顯,但是,如果你一個函數中,有一個很大的分支。
你在看代碼的過程中,一定會看花眼,滾屏的過程中,都不知道自己現在身處在哪個部分。
隨意就算不考慮性能,也推薦把這樣的代碼分割成短函數!
總結
上文說了短函數的優點,說了下註釋的缺陷,還有一個沒怎麼提到的 region …
我在寫代碼的時候一般遵循一下原則:
- 函數內部一般不寫註釋,如果“邏輯複雜”,我會優化邏輯並分割成短函數。
- 在一些演算法中,包含很奇特的公式,這個一定要寫註釋了,沒辦法分割和優化。
- 寫完函數後查看是否有大段的分支,有的話再分割成短函數。
最後,希望本文能對大家有用!