初學者在學習了語法和一堆的 API 以後,就會嘗試本身寫一些具備完整功能的程序。這個過程中很容易養成寫一個上百行甚至幾百行的方法的習慣。總的來講,這是思惟當中缺乏抽象、設計和封裝的表現。隨着編程經驗的豐富,總會有克服的一天。java
但若是想盡早克服這種狀況,像專業程序員那樣去思考,那麼要多讀一些設計和代碼可讀性方面的書。業界有不少經典的書,好比《設計模式》、《重構》、《代碼整潔之道》、《實現模式》等。我強烈推薦這四本,由於我我的從中受益不淺,以爲它們都是必讀的。程序員
當一個屏幕裝不下你的方法體時,就要小心了。
長方法的壞處很是多,主要體如今如下幾個方面:數據庫
長的方法邏輯多,變量天然也多。太多的變量常常會伴隨下面的問題:編程
一、命名困難。當你要定義4個元素類型爲 UnfinishedCustomOrder
的 List,以及4個元素類型爲 FinishedCustomOrder
的 List 時,這些變量的名字會很是長,並且眼神很差的話,後面還容易用錯,出現 bug。設計模式
二、重(chong)用變量。 初學者對變量的命名存在隨意性,同時使用變量也存在隨意性。好比定義一個 boolean flag
變量,在這段邏輯裏面用過一遍,而後在那段邏輯裏面再用一遍。學習
三、重複的變量。 一個方法長到必定程度後,常常會出現寫到後面忘了前面的狀況。因而出現好比說,又從新去數據庫查詢以前已經查過一次的內容的狀況。這種現象特別容易出如今反覆修改過屢次,並且每次都是不一樣的人來改的代碼中。編碼
四、改了變量內容可是忘了。 好比下面這種:設計
public void processAllOrders() { List allOrders = ...; // 查詢全部訂單 ... // 排除掉已完成訂單。注意這條語句甚至可能被委託到 // 另外一個方法執行,本方法中徹底看不到。 allOrders.removeAll(finishedOrders); ... ... // 兩百行代碼後 ... ... ... // 此時另外一個程序員接手實現需求變動。他只關注這部分要改的, // 僅看變量名就認爲 allOrders 依舊包含全部訂單,因而出錯 allOrders.forEach(order -> {...}); ... }
這屬於嚴重違反編碼原則的狀況。有人說,是否是接手的這個程序員閱讀代碼不認真啊?請注意,閱讀代碼自己是很是消耗心智的。讀代碼不是讀小說,要嚴絲合縫的理解代碼的行爲。若是代碼可讀性不好,那麼理解出錯的機率天然也會大,更別說上面的例子中,變量名存在誤導性,這能怪閱讀者嗎?調試
一個長方法的執行過程其實是分幾個階段完成的,每一個階段可能有本身的遠程調用、數據校驗和拋出異常,這會致使長方法中有不少出口。一個方法有多個出口,大多數狀況下是很差的編程習慣,主要體如今:code
一、調試斷點會出現不肯定性。 好比你在某行打了個斷點,但調試的時候發現沒有執行,由於方法在這以前就經過某個出口結束了。反覆嘗試尋找斷點下降了開發效率。
二、反覆構建返回值。 若是方法是有返回值的,那麼多個出口的返回值固然是不同的,它們的前面必然會出現相同的構建這些返回值的過程。一旦這個過程須要改動,那麼遺漏某處就意味着BUG。
三、有的 return 語句寫在層層縮進當中,會給閱讀帶來困難。 由於當你讀到這裏時,會發現腦海中構建的一層層的邏輯,到了這裏忽然被完全中斷了,在某個場景下,方法在這裏結束。因而你必須牢記,後面的代碼中的全部邏輯都要排除這個場景。這樣的結束若再來個兩三次,恐怕能把你逼瘋。
我以前說的是大多數狀況。那麼剩下的狀況是指什麼呢?主要是校驗方法,好比:
public boolean validate(Order order) { if (order == null) { return false; } if (order.isCancelled()) { return false; } ... return true; }
此類方法有多個出口我以爲是能夠接受的。
咱們閱讀方法時,會在腦海中構建每一個參數和變量,理解它們的演變過程。這個時候每多一個變量,都是增長了一分腦力負擔。要知道,人與人之間的腦力承受能力是不一樣的,就算同一我的,在不一樣的精神狀態下的承受能力也有差異。因此,若是一個軟件產品或項目,想要在整個生命週期中減小出錯的可能,那麼就有必要提高代碼可讀性,換句話說,就是減小閱讀代碼的腦力負擔。代碼可讀性是風險控制的一部分,長方法爲項目增長了風險。
上面說的就是一個方法太長會帶來哪些問題。要克服的話,首先是看我最開始推薦的那幾本書,其次是培養本身的抽象思惟,從具體的功能中提取出多個層次的抽象邏輯,將功能的實現拆分到不一樣的抽象層。