1. 程式人生 > >軟體開發和測試的 30 個最佳實踐

軟體開發和測試的 30 個最佳實踐

這些軟體開發和測試的最佳實踐,可以幫你節省時間和避免問題。

加入一個企業文化和程式設計實踐已經定型的新公司,可能會是一種令人沮喪的經歷。當我加入 Ansible 團隊後,我決定整理我多年以來所學併為之奮鬥的軟體工程實踐和準則。這是一個不明確的也不夠詳盡的準則列表,使用它們時需要智慧和靈活性。

我對測試充滿熱情,因為我相信良好的測試實踐既能確保滿足最低質量標準(可悲的是許多軟體產品做不到),並能指導和塑造開發本身。本文提到的這些準則,很多是與測試實踐和理念相關的。其中一些準則針對 Python 的,但大多數不是。(對於 Python 開發者,PEP 8 應該是程式設計風格和指南的首先。)

開發和測試的最佳實踐

1. YAGNI 原則:“You Aint Gonna Need It”。不要寫你認為將來可能需要但現在不需要的程式碼。這是為假想的未來用例編碼,這些程式碼將不可避免地變成死程式碼,或需要重寫,因為未來結果總是與想象的稍有不同。

如果你寫程式碼用於將來的用例,我將在程式碼評審中對其質疑。(你可能而且必須設計 API,並確保未來的用例可用,但這是不同的問題。)

這條原則也適用於被註釋掉的程式碼;如果一個被註釋掉程式碼塊即將進入一個釋出版本,那麼它就不應該存在。如果程式碼可能要還原,請為程式碼刪除建立一個問題單並引用提交物件的雜湊字串。YAGNI 原則是敏捷程式設計的核心要素,這個話題最好的參考書是 Kent Beck 寫的《解析極限程式設計》(《Extreme Programming Explained》)。

2 . 測試不需要測試。用於測試需要的基礎設施、框架和庫需要測試。除非你真的需要不要測試瀏覽器或外部庫。測試你寫的程式碼,而不是別人的程式碼。

3.當第三次編寫相同的程式碼時,也是將其提取成通用的輔助函式(併為其編寫測試)的正確時機。測試中的輔助函式不需要測試;但當你將它們剔除出去然後再重用它們時,它們需要測試。到你第三次編寫類似程式碼的時候,你通常會清楚地認識到你正在解決的通用問題的模型是什麼。

4. 現在來談談 API 設計(面向外部的物件API):把簡單的事情做簡單了,複雜的事情自然成為可能。首先設計簡單的用例,如果有可能最好是零配置或引數化。為更復雜和靈活的用例(如需要)增加選項或額外的 API 方法。

5. 快速失敗。檢查輸入,如果遇到無意義輸入或非法狀態則儘早失敗,最好是通過異常或錯誤響應使問題對呼叫者變得清晰。允許你的程式碼處理“有創意”的用例(例如,除非真的需要,否則在做輸入驗證的時候不要做型別檢查)。

6.單元測試測的是行為單元,而不是實現單元。我們的目標是在改動實現的情況下不改動行為,也不必更新測試,儘管這個目標不總是能實現。因此在可能的情況下將測試物件視為黑盒,通過公共 API 測試,而不呼叫私有方法或玩弄狀態位。

在一些複雜的情況可能做不到,如在特定的複雜狀態下測試行為,以找到一個偶發的錯誤。這一點對於寫測試非常有幫助,因為它迫使你在寫測試程式碼之前思考你程式碼的行為以及你將如何測試它。測試首先鼓勵更小,更模組化的程式碼單元,這通常意味著好程式碼。關於“測試優先”方法有一本很好的入門參考書,就是 Kent Beck 寫的《測試驅動開發》(《Test Driven Development by Example》)

7. 對於單元測試(包括測試基礎設施測試),所有程式碼路徑都應該被測到。100% 覆蓋是一個好的開始。你不能覆蓋所有可能狀態的排列/組合(組合性爆炸),因此這個問題需要考慮。只有當有很好理由的情況下才允許有程式碼路徑未經測試。沒有時間不是一個好理由,最終會花費更多的時間。可能的好理由包括:真正的不可測(以任何有意義的方式),現實中不可能發生,或被其它測試覆蓋。沒有測試的程式碼是一種債。測量覆蓋率和拒絕減少覆蓋率 PR(拉取請求) 是確保你在正確的方向演進的一種方式。

8. 程式碼是敵人:它可能出錯,並且需要維護。少寫程式碼,刪除程式碼,不要寫你不需要的程式碼。

9. 隨著時間的推移,程式碼註釋不可避免地成為謊言。在現實中,很少有人在事情變化的時候更新註釋。通過良好的命名法和已知的程式設計風格,努力使你的程式碼可讀和自文件化。

對於那些晦澀的程式碼,一定要寫註釋,例如偶發錯誤或意外情況的變通方案,或者必要的優化。解釋程式碼的意圖和及其原因,而不是解釋程式碼在做什麼。(順便說一句,有些觀點認為註釋變謊言是有爭議的。我仍然認為這是正確的,《程式設計實踐》(《The Practice of Programming》)的作者 Kernighan 和 Pike 同意我的觀點。)

10. 防守思維。總是考慮什麼會出錯,無效的輸入會引發什麼,什麼可能會失敗,這將有助於你在許多錯誤發生之前發現他們。

11.無狀態和無副作用的單元測試,其邏輯應簡單。將邏輯分解成單獨的函式,而不是將邏輯混合到有狀態和充滿副作用程式碼中。將有狀態程式碼和有副作用程式碼,分為較小的更容易模擬的函式和無副作用地單元測試。(測試的開銷越小意味著更快的測試)副作用確實需要測試,但是測試一次然後處處模擬它們通常是一個好的模式。

12. 全域性變數不好。函式優於型別。物件可能比複雜的資料結構更好。

13.使用 Python 內建型別及其方法將比自己編寫的型別執行快(除非你用C語言編寫)。如果效能是一個考慮因素,請嘗試弄懂如何使用標準的內建型別,而不是自定義物件。

14. 依賴注入是一個實用的程式設計模式,明確你的依賴是什麼和它們來自哪裡。(物件,方法等以引數的形式接收它們的依賴,而不是例項化新物件本身。)這確實讓 API 簽名更復雜,所以這裡需要權衡。如果一個方法最後為所有的依賴設定了10個引數,那這是一個不錯的訊號,不管為什麼你的程式碼做得太多。關於依賴注入的權威文章是 Martin Fowler 的《控制反轉容器&依賴注入模式》(《Inversion of Control Containers and the Dependency Injection Pattern》)。

15. 需要模擬測試的程式碼越多,你的程式碼就越糟糕。為了測試一個特定的行為,需要例項化和牽扯的程式碼越多,程式碼越糟糕。我們的目標是小型可測試的單元,以及更高級別的整合和功能測試,以測試各單元是否配合正確。

16. 面向外部的 API 是“預先設計”——同時要考慮未來的用例——真正重要的地方。改變 API 對我們和使用者來說是一種痛苦,造成向後不相容是可怕的(儘管有時無法避免的)。設計面向外部的 API 要細心,仍然要堅持“把簡單的事情做簡單”的原則。

17.如果函式或方法超過 30 行程式碼,考慮分解它。一個良好的模組最大約 500 行。測試檔案往往比這個要大。

18 .不要在物件建構函式中工作,這裡很難測試而且經常發生意外。不要在__init__ .py中新增程式碼(匯入名稱空間除外)。__init__ .py不是程式設計師通常期望找程式碼的地方,所以它是個“驚喜”。

19. DRY(不要重複自己)在測試中沒有在生產程式碼中要緊。單個測試檔案的可讀性比可維護性更重要(跳出模組複用的限制)。這是因為測試是單獨被執行和閱讀的,而且它們自己不是大系統的一部分。雖然在很多重複的時候建立可重用的元件更方便,但相較於產品程式碼,測試程式碼較少考慮。

20.每當你看到有需要有機會就重構。程式設計是關於抽象的,你的抽象對映越接近問題域,程式碼就越容易理解和維護。隨著系統的有機增長,需要改變結構以擴大它們的用例。系統越來越多的抽象和結構,如果不改變它們就成為技術性的債務。它會是更加痛苦的工作(更慢,越來越多的錯誤)。在特性開發估計中請考慮清除技術債務(重構)的成本。你遺留債務的時間越長,積累的利息就越高。關於重構和和測試的一本很棒的書是 Michael Feathers 的《修改程式碼的藝術》(《Working Effectively with Legacy Code》)。

21. 程式碼正確為第一位,速度快第二位。在處理效能問題時,在修復錯誤之前先要做效能剖析。通常瓶頸不是你認為的那樣。如果寫晦澀的程式碼的唯一價值就是更快而且你已經做過效能剖析並證明了,那麼它實際就是值得的。編寫測試定期檢測你要做效能剖析的程式碼,這樣可以很容易讓你知道你什麼時候測試過。測試可以留在測試套件中,以防止效能退化。(通常情況下,新增定時程式碼總會改變程式碼的效能特性,使效能工作成為令人沮喪的任務之一。)

22. 當更小、範圍有限的單元測試失敗的時候,可以給出更多有價值的資訊,告訴你具體是什麼錯誤。如果一個測試牽涉了半個系統來測試行為,那麼它需要更多的調查以確定什麼是錯誤的。一般來說,執行超過 0.1 秒的測試不是單元測試。沒有所謂的慢單元測試。用限定範圍的單元測試測試行為,你的測試行為扮演了事實上的程式碼規範。理想情況下如果有人想了解你的程式碼,他們應該能夠把測試套件轉換為行為的“文件”。Gary Bernhardt 的《快測,慢測》(《Fast Test, Slow Test》)是關於單元測試實踐的一篇很棒的演講。

23. ”非我所創“不像人們說的那麼壞。如果程式碼是我們寫的,那麼我們知道它是什麼,我們知道如何維護它,在我們可以在適當的時候自由地擴充套件和修改它。這遵循了 YAGNI 原則:我們用那些適合我們需要用例的特定程式碼,而不用我們不需要的可以做複雜事情的通用程式碼。另一方面,程式碼是敵人,擁有必要的程式碼比擁有更多的程式碼更好。引入新的依賴關係時要權衡。

24. 共享程式碼所有權是我們目標;沉默的知識不是好知識。這意味著最低限度要討論或記錄設計決策和重要的實施決策。程式碼評審(Code Review)是開始討論設計決策的最壞時刻,因為在程式碼編寫後,很難徹底更改。(當然在評審時指出並修改設計錯誤比沒有好。)

25. 生成器很棒!它們通常比迭代或重複執行的狀態物件更短更容易理解。David Beazley的《系統程式設計師的生成器訣竅》(《Generator Tricks for Systems Programmers》)是關於生成器一個很好的介紹。

26.讓我們成為工程師!讓我們考慮設計、構建健壯並實現良好的系統,而不是做膨脹的有機怪物。然而程式設計是一種平衡。我們並不總是建造火箭。過度設計(洋蔥架構)同設計不完善的程式碼一樣,處理起來非常痛苦。Robert Martin 的作品幾乎都值得一讀,《架構之潔:一個工匠的軟體結構和設計指南》(《Clean Architecture: A Craftsman’s Guide to Software Structure and Design》)是這個話題一個很好的資源。《設計模式》(《Design Patterns》)是每一位工程師都應該閱讀的經典程式設計書。

27. 間歇失敗的測試會侵蝕測試套件的價值,以至於最終每個人都忽略測試執行結果,因為總有一些失敗的事情。修復或刪除間歇性失敗測試是痛苦的,但這些努力是值得的。

28. 一般來說,特別是在測試中,在需要等待一個特定的變化時候不要採用休眠隨機時間的方式。Voodoo(Python 庫) 的 sleeps 很難理解而且使你的測試套件變慢。

29. 至少讓你的測試失敗一次。故意加入一個錯誤,並確保它失敗,或在測試的行為不完整的情況下執行測試。否則你不知道你真的在測試什麼。瞎寫的測試實際上不能測試任何東西或它很可能永遠不會失敗。

30. 最後一點:只關注特性改進是開發軟體的一種可怕方式。如果開發者的工作不能確保最好的結果,那麼不要讓他們為自己的工作感到自豪。不處理技術債務會使開發變慢並最終導致產品更糟,問題更多。

感謝 Ansible 團隊,尤其是 Wayne Witzel,為改善這個列表中的準則而提出的意見和建議。

相關推薦

軟體開發測試30 最佳實踐

這些軟體開發和測試的最佳實踐,可以幫你節省時間和避免問題。 加入一個企業文化和程式設計實踐已經定型的新公司,可能會是一種令人沮喪的經歷。當我加入 Ansible 團隊後,我決定整理我多年以來所學併為之奮鬥的軟體工程實踐和準則。這是一個不明確的也不夠詳盡的準則列表

MySQL性能優化的21最佳實踐 mysql使用索引

oct 靜態 state zid 希望 lte 適合 實踐 打開 今天,數據庫的操作越來越成為整個應用的性能瓶頸了,這點對於Web應用尤其明顯。關於數據庫的性能,這並不只是DBA才需要擔心的事,而這更是我 們程序員需要去關註的事情。當我們去設計數據庫表結構,對操作數據庫時(

自動化UI測試條件下開發測試的協同實踐

前言 經過我們團隊持續不斷的推進,團隊的自動化UI測試終於走出了研發和嘗試階段,進入到實際專案應用階段,開始產生生產力。但經過了近兩個月的嘗試發現,引入了自動化UI測試後發現與原有的開發模式有所衝突,經過這段時間的摸索和磨合,團隊形成了一種新的開發和測試的協同模式,也就是SCM。

規模化敏捷開發的10最佳實踐(上)

【編者按】軟體開發和採購人員經常會對現有軟體開發方法、技巧和工具產生一些疑問。針對這些疑問,Kevin Fall 整理了五個軟體方面的話題:Agile at Scale,Safety-Critical Systems,Monitoring Software-In

嵌入式軟體開發除錯的3階段,技術方法

層次1:BringUP 在單板BringUp階段使用JTAG調式。大多數晶片廠家IDE都支援tcl指令碼語言,tcl語言可以控制jtag讀取基本的Register,memory,download等,使用jtag可以完成對pll,ddr等的初始化化配置,進而下載

[重要] -- MySQL效能優化的21最佳實踐 mysql使用索引

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效

MySQL效能優化的21最佳實踐 mysql使用索引

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效能。這裡,我們不會講過 多的SQL語句的優

msql效能優化的21最佳實踐mysql索引的使用

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效能。

軟體開發人員的幾階段思考總結

     6程式碼閱讀能力,中級開發人員有一定的程式碼閱讀能力,否則他無法和其他開發人員進行聯合開發和聯合除錯,但中級程式碼人員缺乏的是快速閱讀能力,和其他語言的閱讀能力(指那些未學習過的語言)。所以中級技術人員最怕開發平臺的變化。      說了這麼多。關於中級技術人員說一點自己的的看法。中級技術人員是一

使用者帳戶,授權密碼管理的 12 最佳實踐

賬戶管理,授權和密碼管理往往是很棘手的。對很多開發者來說,賬戶管理功能是一個暗角,不會引起足夠的重視。對於產品經理和使用者來說,產品的最終體驗往往超出預期。 幸運的是,谷歌雲平臺(GCP)提供了一些工具,能夠使你在產品創造、安全處理和使用者賬號(本文中指任何在你係統中註

MySQL性能優化的21最佳實踐

明顯 架構 crash 其它 string 簡單的 nts arch 網絡 當我們去設計數據庫表結構,對操作數據庫時(尤其是查表時的SQL語句),我們都需要註意數據操作的性能。這裏,我們不會講過多的SQL語句的優化,而只是針對MySQL這一Web應用最多的數據庫。 1. 為

spring通過profile實現開發測試環境切換

我們 其中 ror web cms -m acc 系統環境 oot 以開發測試為例,介紹tomcat部署應用和maven部署應用下利用profile實現測試環境和開發環境切換一、tomcat部署應用1、數據源配置dev.properties 路徑:/src/main/res

完美CSS文檔的8最佳實踐

風格 產品經理 sta war support display 主題 ucd 發生 在css的世界,文檔沒有被得到充分的利用。由於文檔對終端用戶不可見,因此它的價值常常被忽視。另外,如果你第一次為css編寫文檔,可能很難確定哪些內容值得記錄,以及如何能夠高效完

數據湖是一種方法 數據湖的四最佳實踐

發出 就是 arc 而不是 程序集 image new 裏的 子郵件 轉載自:http://bigdata.chinabyte.com/311/13871811.shtml數據湖聽起來很簡單:把數據或信息匯集到一個結合處理速度和存儲空間的大數據系統――Hadoop集群或內存

Java 中處理異常的 9 最佳實踐

lan method 永遠 是否 res ati 是你 dex mes 在本文中,作者介紹了9個處理異常的最佳方法與實踐,以舉例與代碼展示結合的方式,讓開發者更好的理解這9種方式,並指導讀者在不同情況下選擇不同的異常處理方式。 以下為譯文: Java中的異常處理不是一個簡單

第一行代碼:以太坊(2)-使用Solidity語言開發測試智能合約

之一 腳本語言 其他 括號 add row ans img 運行方式 智能合約是以太坊的核心之一,用戶可以利用智能合約實現更靈活的代幣以及其他DApp。不過在深入講解如何開發智能合約之前,需要先介紹一下以太坊中用於開發智能合約的Solidity語言,以及相關的開發和測試環境

第5章:座標依賴/5.9 最佳實踐/5.9.2 依賴屬性使用變數

依賴屬性使用變數 概念:用變數定義依賴的某一部分屬性,具體依賴中直接使用這個依賴即可,這樣做的好處是以後修改這個屬性時只需要修改這個變數即可 語法: 定義變數: <properties> <!—變數名--> <spring

第5章:座標依賴/5.9 最佳實踐/5.9.1 排除依賴

排除依賴 概念:用於排除某個依賴,比如某個傳遞依賴版本不穩定時,用於排除這個傳遞性依賴;又比如某個傳遞性依賴存在版權問題,而不能放在中央倉庫,所以要進行排除 語法: <exclusions>   <exclusion> <grou

符合 ISO26262 規範的軟體開發測試諮詢服務

概述 隨著汽車電子系統的普及性和複雜性不斷地提高,汽車電子產品的系統失效、部件失效等安全問題日益嚴峻。恆潤科技從 2008 年起開始研究 ISO-26262 功能安全相關標準和技術 , 2012 年恆潤參與國標委組織的功能安全標準的討論會,併成為功能安全標準制定小組的成員。 經過多年的研究和

EOS智慧合約開發測試框架EOSFactory

EOS Factory是一個EOS智慧合約開發和測試框架。 自2017年秋季以來,Tokenika一直致力於建立基於Python的EOS智慧合約開發平臺,以便輕鬆建立,測試和部署智慧合約。隨著EOS的不斷髮展,我們已經習慣了其基礎程式碼的突然變化,並且隨著我們的進展而逐漸減少詛咒;)今天