這是寫給初學者看的,雖然有點吹牛,但高人面前不敢班門弄斧,我寫的都是來自我的切身經驗。)
初學者學習設計模式之類的東西之前,如果能打好基礎,將來必能事半功倍。
初學者不太講究的一個地方,就是不考慮將來要修改代碼的可能性。一個計算機寫出來,就覺得“好,我會了”,馬上丟到一邊。
高水平的程式員,寫出來的代碼都是易於修改的。但是初學者很難有這種機會要修改自己的程式,怎麼辦呢?
就我個人經驗,我覺得鍛煉這種思維的一個好辦法,就是反反覆複的寫同樣功能的程式。第一個版本寫出來之後,稍微總結一下,然後重新寫過,並添加一點功能。
反覆幾次,你就會看到最後寫出來的比起第一次寫的真是賞心悅目得多。當你對自己的代碼了如指掌的時候,不管要你添加什麼功能,你馬上就能想到要在什麼地方添加什麼樣的類。
如果你能編寫易於修改的代碼,將來工作的時候絕對輕鬆不少。同樣的需求,別人要翻來覆去的改東西,而你勾勾手指頭就搞定了。一點也不誇張!
但是,一個初學者,認識的 Java 類沒幾個,更別說做什麼設計了。這樣的人能寫出這樣“高水平”的代碼嗎?
能!我教你一個簡單的原則:不管什麼方法都不要超過 5 行。我相信很多人不是第一次見到這句話,但真正把它放在心上的沒幾個。
我想說的是,初學者要能認準這句話,那就等於練了九陽神功,寫出來的代碼保證經脈通暢,內勁十足。
你別說做不到。初學者寫的程式本來就沒多少功能,一個方法不超過 5 行完全沒問題。
具體怎麼寫呢?舉個例子:寫一個計算機,main 函數該怎麼寫?
-
public static void main(String[] args) {
setupUIManager(); // 初始化 Swing 風格
new Calculator().setVisible(true); // 開啟表單
}
怎麼樣,兩行。Calculator 就是計算機的表單類。這個表單有很多控制項,初始化一定有很多代碼吧?NO,不需要:
-
public class Calculator extends JFrame {
public Calculator() {
setupFrame(); // 初始化表單大小、標題等
createLayout(); // 初始化布局
createMenu(); // 添加功能表列
createTextField(); // 添加文字框
createButtons(); // 添加按鈕
}
}
就是這樣,通過將代碼委派到其他方法,就能把方法縮小到 5 行以內。
看到這裡你也許哭笑不得:這搞法未免太弱智了吧?這有什麼好處?——告訴你,這樣做的好處就是:總攬全域,快速定位。
拿上面的代碼為例,如果將來要添加功能表項目,那麼一眼就看得出,要修改的只有 createMenu()
方法。如果啟動並執行時候發現少了一個按鈕,你也一眼就看得出,問題出在 createButtons()
方法。相反,如果這五個方法參雜在一起,這代碼我保證你看了就不想動,如果出了問題要修複,那個頭疼啊。。。
不僅如此,更重要的是,這種預先委派的編碼方式對你的思維也有提高。
打比方我要做的事情分為若干個步驟。在編寫步驟 A 的代碼之前,先將 A 委派給一個空的方法 a()。至於 a() 的內容,我現在不考慮,我現在考慮什嗎?我現在考慮 A 完成之後要做的事情。這就叫三萬英尺的高度。
假如 A 做完了就做 B,那麼我又將它委派給 b()。以此類推,等所有的事情都委派完了之後,我再考慮 a()、b()
裡面該寫什麼。這個時候,a() 已經把步驟 A 給限定了,傳入什麼,返回什麼,都已經定好了。那麼寫 a()
的時候根本不用考慮這個方法以外的事情。如果 a()
很複雜,我又可以委派給若干個方法來實現。每個方法都是一樣的來做,直到某個步驟已經很簡單了,我就可以寫最後的代碼了。
雖然整個邏輯,A,B,C,D,E,...很複雜,但是通過委派的方式,我每次都只需要考慮其中很小的一部分,所以寫起來很輕鬆。這樣寫出來的代碼脈絡清晰,好看又好改。
這就是所謂化整為零,分而治之。所以,一個方法不超過 5 行,不是絕對的,它體現的原則是:一個方法的內容要一眼就能看懂。咱行內有句俗話:代碼是給人看的,不是給機器看的。說句不好聽的,不是人看的東西,也一定不是人寫的!
你可能會說“沒那麼嚴重吧,程式能用就行了嘛”。想想看,如果我願意,所有的代碼都寫在 main() 裡面,程式不照樣能運行?既然能用,我又何必看什麼設計模式呢?——所以歸根結底,所謂設計,就是將程式碼群組織得更加易懂。易懂的東西才容易複用,容易複用才叫好的設計。學習設計的時候請務必記住這點。
開頭說了,這都是我的切身體會。如果不是當初學編程的時候在書上看到不要超過 5 行這句忠告,我都不敢想象自己現在會是什麼樣子。所以我特別崇拜這句話,雖然不知道是誰說的……
PS1:複雜的方法是可以化簡的。如果一個方法“光定義變數就得超過 5 行”,那麼可以說,這些變數中大部分實際的作用都是局部的,它們的作用範圍只是整個方法的一部分,而這部分就是可以提取出來的。
PS2:如何化簡長方法,有大師寫的專門介紹重構的書。其實本文主題不在於此,而是在於一開始就不要寫長方法。
一些 Java
入門書不注重這點,以至於就像本文回複中的,很多人根本不信。總結我個人經曆,改代碼的時間要比寫代碼的時間多得多。我改過不少代碼,各種風味的都有,包
括 6000 多行的類,400 多行的方法。所以我覺得從一開始就要糾正這種陋習,而且必須通過 “不超過 5 行” 這種看似極端的目標來實現。如果你已經有相當的編程經驗,或者已經在工作了,那麼你以前怎麼做的,那就繼續做下去,沒必要聽我嘮叨。如果你覺得我居心不良誤人子弟,本文出現在 CSDN 首頁實在是個禍害,那請趕緊寫篇文章駁一駁。
PS3:如果你是初學者,你不信,那也沒關係。所謂吃一塹方能長一智,經驗就是這麼來的。要是你看幾篇文章幾本書就能成熟手,那我們不要混飯吃了。