軟件工程師親訴——軟件工程最佳實踐準則20條

提升代碼的可讀性

開發人員須要花費大量的時間閱讀代碼,甚至超過了編寫代碼的時間。這裏我所說的閱讀包括如下工做:調試代碼、檢查他人提交的代碼、學習新的代碼庫等等。node

所以,你應該確保本身的代碼便於閱讀,即使有的時候你須要更長的命名、編寫更多代碼,以及捨棄本身的「小聰明」。程序員

 

舉個例子,雖然變量名 timeInMillis 比 time 更長,你須要輸入的字符也更多,可是開發人員無需查看其餘代碼就能明白這個變量計算的是哪一種時間。web

再舉一個例子,網上有不少一行代碼的解決方案。例如,以下判斷迴文數的寫法很是聰明(注:迴文數指的是像 14641 這樣「對稱」的數,即:將這個數的數字按相反的順序從新排列後,所獲得的數和原來的數同樣):面試

def isPalindrome(self, x: int) -> bool:
   a=list(str(x))    return a==a[::-1]編程

可是,很是難以理解。一行代碼的解決方案頗有挑戰性,不建議在多人共同維護的代碼庫中採用這種寫法。架構

重構的價值

只有當重構幫助你和團隊成員節省的時間超太重構花費的時間,才值得投入。你應該將精力集中到頻繁閱讀和編寫的代碼上。函數

你能夠考慮,將不緊急的重構分配給新來的團隊成員練手,這樣他們不但有機會學習,同時也能貢獻價值。工具

將技術負債視做財務負債,能夠適量承擔一些

有時,從業務的角度出發,儘快提供有價值的功能能夠獲取更大利益,好比趕在競爭對手發佈相似的功能以前,即便這個時候的功能還不夠完美也不要緊,只要你能夠創建計劃,趕在債臺高築,被「利息」壓得透不過氣來以前,及時地改善代碼。單元測試

若是技術負債的積累速度超過你的償還能力,那麼就會出現問題,代碼庫的處理難度就會愈來愈大。學習

例如,在時間緊迫的狀況下,在完成測試以前就發佈某項功能也多是正確的業務決策,可是過後你須要當即補上測試。若是你拖延測試,很快這些未測試的代碼之上就會出現新的代碼,未經測試就發佈的功能也會相繼出現,那麼償還這部分技術負債的難度就會愈來愈大,很難再還給團隊一個維護良好的代碼庫。

 

不要製造驚喜

團隊成員會假定你的代碼遵循常見的慣例,因此你不該該偏離這些慣例,不要給他們製造驚喜。

例如,若是你編寫了一個函數 isButtonEnabled(),那麼團隊成員確定會假定這個函數是在檢查某個按鈕,它會返回一個布爾值,由於絕大多數的這類函數名稱都以「is-」開頭。若是你的函數還作了其餘處理,那麼就應該在名稱中澄清。

命名的長度應該視範圍而定

例如,for 循環中可使用 i 和 j 之類的變量名,可是全局常量的名稱應該更加精準地表達它的意圖。

函數也須要保證可讀性,而不只僅是爲了不重複

通常,咱們常說重複三次以上的代碼都應該寫成函數,但我還想再加兩點應該寫成函數的狀況:

1)當須要添加註釋解釋這段代碼的用途的時候;

2)當嵌套超過3層的時候。

舉個例子,假設我編寫了下列UI函數:

fun setupViews() {// set up textView
   textView.isVisible = …
   textView.text = …
   …more textView setup…// set up imageView
   imageView.image = …
   imageView.backgroundColor = …
   …more imageView setup…
}

咱們應該將相應的代碼分別放入另外兩個函數 setupTextView() 和 setupImageView(),即使它們不包含重複代碼。

經過這種方式編寫出來的代碼,自己就能夠做爲文檔,若是有人須要修改或調試 imageView,他能夠直接去 setupImageView(),而無需閱讀全部的代碼。

另外一個常見的狀況是關於函數的最大代碼行數,這個值的設置很是隨意,一般在5~100的範圍內。我我的認爲基本的標準是:閱讀函數的時候不須要翻頁。

重複的呈現形式有不少種

DRY(Don't repeat yourself,不要重複你本身)是一個衆所周知的軟件工程原則。最多見的重複就是徹底相同的代碼,可是也有一些重複的形式並無那麼明顯,例如實現的重複。

舉個例子,對於以下定義的類:

class TreeNode {
    val value: String
    var children: List<TreeNode>
    val isLeaf: Boolean        fun addChild(node: TreeNode) {
       children.add(node)
       isLeaf = false
   }
    
    fun removeChild(node: TreeNode) {
        children.remove(node)        if (children.isEmpty()) isLeaf = true
   }
}

不須要在每次 child 更新的時候設置 isLeaf, 你能夠添加 fun isLeaf() = children.isEmpty(),如此一來,在更新這個類的時候,你就無需檢查 isLeaf 是否被更新了。

不要重複其餘人的工做

在實現某個功能以前,首先你應該先檢查一下代碼庫中是否已有現成的實現。

例如,你須要處理時間,常量 SECONDS_PER_MINUTE 可能已經存在了,你能夠直接重用,而不該該在同一個代碼庫中屢次定義這個常量。

學習並遵照項目的編程風格

一套統一的開發指南能夠方便團隊成員理解彼此的代碼,也能夠方便新來的成員。一般,實際的規則並不重要,重要的是你須要確保這些規則被貫徹執行了。例如,我曾見過一些 Kotlin,全部包含擴展函數的文件名都以「-Ext」結尾,而其餘文件則使用「-s」結尾。實際的選擇並不重要,重要的是全部人的選擇必須統一,只有這樣程序員才知道哪裏能找到 Foo 的擴展函數,是在 FooExt.kt 中仍是在 Foos.kt 中?

經過 lint 規則提高代碼的整潔度

若是你在項目中使用了lint工具,並且你常常手動調整格式,或者在代碼審覈時常常有人提出格式方面的建議,那麼就應該考慮一下增長一條新的lint規則。

學習使用 IDE

現代 IDE(好比Android Studio 和 VSCode)很是強大。你應該學習如何使用 IDE 的各類小工具(好比調試器),以及鍵盤快捷鍵,雖然這須要投入必定的時間,但從長遠打算來看可以爲你節省不少時間。

你應該自定義設置和鍵盤快捷鍵,優化你的工做流程。例如,JetBrains IDE 默認不提供「Split editor tab」的快捷鍵(你必須點擊Window → Editor Tabs → Split Vertically),可是我添加了一個自定義的快捷鍵,由於我常用。

註釋應該解釋緣由,而不是實現方式

理想狀況下,代碼應該不言自明,不須要添加註釋。程序員在修改代碼的時候,常常忽略更新註釋,時間久了,註釋就會不許確,與實際的代碼截然不同。在你打算寫註釋,解釋代碼的功能時,不妨考慮一下重構代碼,讓代碼不言自明。

然而,僅靠代碼自身還不足以解釋爲何你選擇這種方式。註釋能夠提供上下文,好比幫助你作出決策的產品需求、系統限制或出於效率的考慮。

不要將測試代碼視做二等公民

在編寫生產代碼的時候,你可能須要花點時間計劃代碼,確保在功能發佈以前達到良好的品質,可是程序員一般都會忽視測試代碼,只要能正常運行就能夠了。然而,測試代碼也須要維護,若是這些代碼很難理解,那麼就會增長維護的負擔。

部分問題是測試代碼通常都不須要通過嚴格的審覈。你們會花費大量時間審覈生產代碼,卻以爲測試代碼沒這個必要,由於畢竟已經經過了測試。

表格驅動測試

幾個月之前,我發現了Junit的參數化測試,這種方法幫助我編寫了更多完全的測試。

在常規單元測試中,一般每一個輸入只有一個測試函數。最後會致使不少函數都有重複的代碼,並且很容易漏掉一些輸入。表格驅動測試有一個單獨的測試函數,還有一個表格囊括了全部可能的輸入以及預想的輸出,只須要一個測試函數,就能夠測試全部輸入。

採用新庫有風險

每一個庫都有預發佈的版本,頗有可能會破壞已有的功能。

在新發布的庫中,易於測試多是次要考慮因素,若是你想在大型項目中採用新庫,事先必須驗證這些庫是否可以經過你的測試代碼,併兼容生產代碼。

在社區普遍採納某個庫以前,遇到問題時,很難找到資源。並且可能這個庫永遠也不會被普遍採納,項目自己也會被維護人員遺忘。

對於有些庫,看似每一個人都在使用,可是真正的項目中採用了這些庫嗎?仍是說只是出如今演示程序中?

向團隊成員尋求幫助時,應該注意他們的方法,而不僅是解決方案

注意團隊成員使用的資源和工具,若是未來再遇到相似的問題,你可以更好地武裝本身,靠本身的力量解決問題。發現新的資源和工具都頗有價值,好比文檔資源、Git命令、鍵盤快捷鍵等。

審覈人員對代碼變動感到不解或產生誤解,則說明代碼有問題

除了迴應審覈意見以外,你應該考慮重構或添加註釋來澄清。這樣能夠確保未來其餘人閱讀這段代碼的時候,不會遇到一樣的困惑。

閱讀代碼審覈意見

當你在理解某段代碼時遇到困難,則應該仔細閱讀代碼的審覈意見。從代碼的審覈意見能夠看出,同時間內還有哪些代碼發生了變化,所以閱讀這些審覈意見頗有價值,並且其中還可能包含代碼背後的決策說明。

若是你正在實現的某個功能與某個已有的功能很是類似,那麼閱讀類似功能的代碼審覈意見,能夠幫助你規劃本身的實現。例如,若是我想添加某個Android 功能,但iOS或Web已有這個功能,則看看其餘平臺的實現方法會有頗有幫助性。

 

按照本身喜歡的方式學習

上大學的時候,除了課堂上的學習以外,你的知識主要來自本身的業餘項目,在找工做的時候,這些經驗會幫助你脫穎而出。可是,在以後的工做中,若是你想跳槽,則與本身的業餘項目相比,實際工做項目的經驗更能贏得面試官的青睞。

在業餘項目中,你能夠作本身喜歡作的事情,固然你能夠繼續享受這些項目!可是,除此以外,還有不少其餘的學習方式:閱讀博客、看演講、參加在線課程、聽播客等等。你能夠找到本身最喜歡的方式,或者你也能夠利用工做以外的時間發展其餘興趣愛好。

在線資源的質量層次不齊

任何人均可以經過互聯網發表技術博客文章。若是你打算經過某篇博客文章學習新技術,卻發現其中的內容不太合理,那麼可能只是由於文章自己寫得不怎樣,你沒必要就此放棄,而是應該嘗試其餘資源。

官方的資源和教程一般都是很好的切入點。會議演講以及公司的技術博客的質量通常也都比較高,由於這些資源都通過了嚴格的審查。

最後

說到學習資源,如下是我常去的一些網站,本文說起的不少準則也正是來自這些資源:

    • Refactoring Guru:一個網站,介紹瞭如何編寫和重構整潔的代碼。

    • Clean Code:經典的軟件工程書籍。有些內容有點過期,並且還與Refactoring Guru有重疊,可是仍然值得一讀。

    • Martin Fowler’s website:做者撰寫了不少有關軟件開發的書籍,並且他的網站也有不少關於軟件架構與重構的信息。

    • Android Weekly newsletter:一份週刊,精選了不少技術文章、播客以及演講。僅限於Android,可是其餘平臺也有相似的週刊。

    • Yelp Android school:科技演講GitHub存儲庫。有一半是Android爲主,還有一半討論的是軟件工程。

若是你還想了解更多編程知識,詳情點擊下方瞭解更多噢~《+Q羣:1151395975》

相關文章
相關標籤/搜索