這篇文章要介紹的,是我作為專業程式設計師這些年來學到的能真正提高我的程式碼質量和整體工作效率的 10 件事情。
1. 永遠不要複製程式碼
不惜任何代價避免重複的程式碼。如果一個常用的程式碼片段出現在了程式中的幾個不同地方,重構它,把它放到一個自己的函式里。重複的程式碼會導致你的同事在讀你的程式碼時產生困惑。而重複的程式碼如果在一個地方修改,在另外一個地方忘記修改,就會產生到處是 bug,它還會使你的程式碼體積變得臃腫。現代的程式語言提供了很好的方法來解決這些問題,例如,下面這個問題在以前很難解決,而如今使用 lambda 卻很好實現:
/// <summary> /// 一些函式含有部分重複程式碼 /// </summary> void OriginalA() { DoThingsA(); // unique code DoThingsB(); } /// <summary> /// 另外一個含有部分重複程式碼的函式 /// </summary> void OriginalB() { DoThingsA(); // 沒有重複的程式碼 DoThingsB(); }
現在我們重構含有部分相同程式碼的函式,用 delegate 模式重寫它們:
/// <summary> /// Encapsulate shared functionality /// </summary> /// <param name="action">User defined action</param> void UniqueWrapper(Action action) { DoThingsA(); action(); DoThingsB(); } /// <summary> /// New implmentation of A /// </summary> void NewA() { UniqueWrapper(() => { // unique code }); } /// <summary> /// New implementation of B /// </summary> void NewB() { UniqueWrapper(() => { // unique code }); }
2. 留意你開始分心的時候
當你發現自己在瀏覽 facebook 或微博,而不是在解決問題,這通常是一種你需要短暫休息的訊號。離開辦公桌,去喝一杯咖啡,或去跟同事聊 5 分鐘。儘管這樣做看起來有點反直覺,但長久去看,它會提高你的工作效率。
3. 不要匆忙趕任務而放棄原則
當帶著壓力去解決一個問題或修改一個 bug,你很容易失去自制,發現自己匆匆忙忙,甚至完全忘了一直堅持的重要的測試過程。這通常會導致更多的問題,會讓你在老闆或同事眼裡顯得很不專業。
4. 測試你完成的程式碼
你知道你的程式碼能做什麼,而且試了一下,它確實好用,但你實際上需要充分的驗證它。分析所有可能的邊界情況,測試在所有可能的條件下它都能如期的工作。如果有引數,傳遞一些預期範圍外的值。傳遞一個 null 值。如果可能,讓同事看看你的程式碼,問他們能否弄壞它。單元測試是到達這種目的的常規方法。
5. 程式碼審查
提交你的程式碼之前,找個同事一起坐下來,向他解釋你做了哪些修改。通常,這樣做的過程中你就能發現程式碼中的錯誤,而不需要同事說一句話。這比自己審查自己的程式碼要有效的多得多。
6. 讓程式碼更少
如果你發現寫了大量的程式碼來解決一個簡單的問題,你很可能做錯了。下面的 boolean 用法是一個很好的例子:
if (numMines > 0) { enabled=true; } else { enabled=false; }
這時你應該寫成這樣:
enabled = numMines > 0;
程式碼越少越好。這會使 bug 更少,重構可能性更小,出錯的機率更小。要適度。可讀性同等重要,你可不能這樣做而使程式碼喪失可讀性。
7. 為優雅的程式碼而努力
優雅的程式碼非常的易讀,只用手邊很少的程式碼、讓機器做很少的運算就能解決問題。在各種環境中都做到程式碼優雅是很難的,但經過一段時間的程式設計,你會對優雅的程式碼是個什麼樣子有個初步的感覺。優雅的程式碼不會透過重構來獲得。當你看到優雅的程式碼是會很高興。你會為它自豪。例如,下面就是一個我認為是優雅的方式來計算多邊形面積的方法:
static public double GetConvexPolygonArea (Vector2[] vertices) { double area = 0; for (int i = 0; i < vertices.Length; i++) { Vector2 P0 = vertices[i]; Vector2 P1 = vertices[(i + 1) % vertices.Length]; area += P0.Wedge (P1); } return area / 2; }
8. 編寫不言自明的程式碼
勿庸置疑,註釋是程式設計中很重要的一部分,但能夠不言自明的程式碼更勝一籌,因為它能讓你在看程式碼時就能理解它。函式名變數名要慎重選擇,好的變數/方法名字放到語言語義環境中時,不懂程式設計的人都能看懂。例如:
void DamagePlayer (Player player, int damageAmount) { if (!player.m_IsInvincible && !player.m_IsDead) { player.InflictDamage ( damageAmount ); } }
能自我說明的程式碼不能代替註釋。註釋是用來解釋“為什麼”的,而自我說明的程式碼是來描述“是什麼”的。
9. 不要使用純數字
直接把數字嵌入程式碼中是一種惡習,因為無法說明它們是代表什麼的。當有重複時更糟糕——相同的數字在程式碼的多個地方出現。如果只修改了一個,而忘記了其它的。這就導致 bug。一定要用一個命名常量來代表你要表達的數字,即使它在程式碼裡只出現一次。
10. 不要做手工勞動
當做一系列動作時,人類總是喜歡犯錯誤。如果你在做部署工作,並且不是一步能完成的,那你就是在做錯事。儘量的讓工作能自動化的完成,減少人為錯誤。當做工作量很大的任務時,這尤其重要。
11. 避免過早最佳化
當你要去最佳化一個已經好用的功能程式碼時,你很有可能會改壞它。最佳化只能發生在有效能分析報告指示需要最佳化的時候,通常是在一個專案開發的最後階段。效能分析之前的最佳化活動純屬浪費時間,並且會導致 bug 出現。