天天看點

年輕程式員需要學習的5大經驗

在過去的7年半時間裡,我帶過的軟體實習生超過一打,也看到過數以百計的學生和畢業生的檔案。我發現很多事情他們都需要學習。或許你會說,我說的不

就是某種特定的技術、算法、數學,或者其他特定形式的知識嗎?沒錯,這的确是需要學習的,但卻并不是最重要的事情。他們需要學習的最重要的東西是“自我規

範”。這些規範就是:盡可能地寫出最簡潔的代碼;如果代碼後期會因為改動而變得淩亂不堪就得重構;盡量删除沒用的代碼,并添加注釋。

我花了很多時間來敦促這些實習生去學習這些内容。我經常會問他們,怎麼樣才能成為一名優秀的程式員,他們也通常會回答說,代碼應該清晰易懂易于維護。這的确是我想聽到的聲音,但是很少有年輕的程式員真的能夠始終如一地貫徹這一點。

請謹記這一點,要懂得“自我規範”,也不能一旦代碼“起效了”就立馬置之腦後。如果所有的變量都命名錯誤,但是代碼依然可以完美地運作,那麼這些代

碼絕對亂糟糟得讓人不忍直視。将功能代碼改進為簡潔代碼可能在短期内是看不到回報的:代碼原本就可以工作,在清潔之後依然可以工作。這就是為什麼你需要

“自我規範”這一步驟了。這也是為什麼實習工作是如此必要:一個好的上司是相當注重代碼品質的(即使所謂“好代碼”的定義對于每個程式員都不一樣),進而

迫使實習生和初級程式員不得不反複修改。

年輕程式員需要學習的5大經驗

下面我舉的一些例子都是新手程式員寫代碼的時候經常出現的:

名不副實的函數/變量/類

這些函數、類和變量實際所做的事與其名字所表達的含義并不一緻。片面看名字是正确的,但是聯系實際的話,有的甚至是毫不相關的。

舉個例子,我上一期的實習生寫了兩個類:editorgui和editorobjectcreatorgui。用于處理編輯界面的代碼。讓我哭笑不

得的是,用于建立新對象的是editorgui,而editorobjectcreatorgui隻能通過處理不同的對象進行導航。兩者的含義居然是截然

相反的!即使代碼還算相對簡單,但我還是花了相當長的一段時間用來了解它,因為一開始我是在一種完全相反的假設基礎上來了解的。這種情況的解決方案非常簡

單:重命名editorobjectcreatorgui為editorobjectnavigationgui即可,這樣就易于了解多了。

這種情況我看到過很多。之是以會發生這種情況是因為代碼在工作過程中發生了演變。在選擇名字的時候可能還是正确的,但到了寫完代碼的那一刻,就名不副實了。關鍵是要時刻銘記命名法則。你得明白你添加的東西是否依然符合函數和類的名稱。

混亂的類

另一個問題是類很亂:類做了很多不相關的事情。新功能的添加很簡單,但是慢慢的,你會發現你的代碼變得臃腫不堪,各種不相關的功能随處可見。有時候,臃腫與否也并不指的是類的大小:某個類可能隻有幾百行,但依然囊括了不屬于它的代碼。

為什麼會發生這種情況呢?舉個例子:假設由于某種原因,某個gui類需要分析什麼樣的紋理可行(可能是有按鈕要用來選擇紋理)。如果這個gui類是

唯一需要這個分析結果的類,那麼在gui類中這樣做是有意義的。然而,由于某種原因,一個完全無關的gameplay類也需要這些資訊。是以你需要将這些

紋理查詢的資訊從gui類傳給gameplay類。這時候,其實這個gui類已經變大了:因為它裡面其實還包括了textureanalyser類。解決

方法也簡單:将textureanalyser類分割為一個單獨的類,gui類和gameplay類都可以使用它。

關于這一條經驗法則很多人提出質疑:要是我添加的功能仍然适合原來這個類的名字呢?如果的确不适合,那麼我就必須重命名,或者将其分割成單獨的類,抑或用代碼寫成一個不同的類嗎?

如果你不能為你的類想出一個合适的名字,給人的感覺就會不舒服。如果你不能在類的名字中描述它的目的,那麼就會顯得亂七八糟。有時候我們還需要将某個臃腫的類分割成幾部分,并各自取一個恰當的名字。

過于龐大的類

這和上一點——混亂的類有些類似:很多東西一點一點地都添加到類中,然後它不可避免地就臃腫了。在這種情況下,這樣一個類仍然是有意義的,但就是長

得太大個了點。這麼個龐然大物不但繁瑣,而且很容易出現bug,因為大量的代碼需要用于操作同一個私有成員變量,是以我們很容易忽視一些細節。

分割一個已經長得很大的類其實是相當枯燥的。這也會成為一個挑戰,如果類中的代碼高度交織在一起的話。再加上它已經在工作,修複時不能添加新功能,這樣一來,我不得說,分割一個過于龐大的類,不能嚴格地自我規範是不行的。

根據在ronimo的普遍經驗,類保持在500行代碼以下、函數保持在50行代碼以下是最合适的。不過有時候,這樣做反倒不可行,也不明智。但是一般說來,一旦類或函數超出了那個界限我們就可以想辦法重構,并将之分割為更小更易于管理的片段了。

關于代碼注釋

幾乎所有的示例代碼都會包含注釋好了的代碼片段,而不說明為什麼。這段代碼需要修複嗎?舊的代碼是否已經被取代了?為什麼那兒要寫這些代碼?大家都知道沒有注釋的代碼常常不知所言,但不知何故,很多人都會忘記在自己的代碼上注釋。

并行邏輯和代碼重複

還有一個問題就是我經常能在若幹個代碼段處看到相似的邏輯。

例如,我們可以從紋理這個名稱知道它大概的目标對象,比如說是“treebackground.dds”。為了知道紋理是否可以用于tree,我們

檢查了檔案名以便知道它是不是以“tree”開的頭。可能使用sdk的話我們用filename.beginswith(“tree”)可以很快地檢測出

來。隻是這句代碼這麼短,我們往往會選擇哪個地方需要,就直接複制粘貼。當然這樣就是代碼重複了,而正如每個人都知道的,我們應該避免重複代碼,但如果複

制的代碼是如此之短,我們往往會忘記這一點,很自然地就直接copy了。此處我們面對的問題也是顯而易見的:也許後面我們檢查某個紋理是否适合tree的

方法就得變了,然後我們就不得不實行“霰彈式修改”(即到處修改)政策,一處一處地修複。

此處的一般規律是,如果是非常具體的代碼,那就不要複制,即使原本的代碼超級之短,調用函數甚至比直接寫需要更多的代碼,也應該封裝成函數。

上面讨論的這些内容已經講得非常透徹了。很多内容甚至你在大學中就學過。但是現在要面臨的挑戰是你需要一步步地從被動遵守到主動銘記于心養成一種習慣。這也是為什麼ronimo中的實習生最重要的不是學習知識,而是學會自我規範。

作者:john

來源:51cto

繼續閱讀