天天看點

TDD實戰感想

近期針對TDD,進行了理論學習及實戰,完全吸收需要花費不少時間,故文字記錄以便加深、鞏固及後續學習。本博文主要記錄TDD了解及實戰感想。

  1. 什麼是TDD?

TDD(Test-Driven Development)是測試驅動開發的英文簡稱,是靈活開發中的一項核心實踐和技術,也是一種設計方法論。TDD的原理是在開發功能代碼之前,先編寫單元測試用例代碼,然後隻編寫使測試通過的功能代碼,通過測試來推動整個開發的進行。

  1. 為什麼TDD?

TDD一種淺顯的認知:先寫測試用例,再寫代碼,通過用例看護代碼品質,就叫TDD。其實不然,TDD的核心在于--分離關注點:

  1. 關注點WHAT:通過測試用例的撰寫、設計,理清需求、驗收條件,明确系統/子產品要做什麼,制定契約;
  2. 關注點HOW:代碼層面如何實作。

大多數開發慣有思維:忽略WHAT,直接站在實作(即HOW)的角度思考問題,而TDD能夠強制開發人員分離關注點為WHAT、HOW兩步,先站在驗收/使用者角度思考問題,明确子產品輸入、輸出(即驗收标準),輔助設計,劃清職責、邊界,再考慮如何基于設計實作代碼。基于分離關注點,可帶來如下好處:

  1. 從使用者角度抽象服務接口,隔離實作,使接口設計更加合理、穩定;
  2. 優先明确子產品輸入、輸出,有助于劃清子產品職責、邊界,後續易通過打樁等測試手段隔離依賴,保證子產品獨立可測;
  3. 提前明确驗收标準,理清需求,既可以防止功能缺失,又可以避免開發盲目的設計/實作無明确來源、需求的功能,減少不必要開發。代碼寫的越少,功能越簡單,錯誤越少,穩定性越高;
  4. 基于驗收角度設計的用例,隻關注需求,程式的輸入、輸出,不關心中間過程,能夠保證測試用例的穩定性,避免因為代碼實作的變動而導緻用例頻繁變動。
  1. 如何做TDD?

針對TDD落地,最關鍵步驟:

  1. 任務分解:将複雜問題拆解為可驗證、互相獨立、易讀易懂的簡單任務。任務分解因人而異,原則:拆解到自己認為簡單、可控制即可(eg:15分鐘内可利用上下文圖将任務表達出來)。任務拆解是TDD中最難的部分,可能需要領域驅動設計/面向對象設計等方法,對系統進行抽象、分解;
TDD實戰感想
  1. 明确驗收标準:明确各簡單任務驗收标準(即WHAT)。
  2. 嚴格遵守以上兩點,直到最終分解的任務可驗證、互相獨立。現實開發過程中,離代碼實作越近時,開發就越急于編碼,而跳過部分任務分解、驗收标準的明确,導緻最終實作代碼耦合、函數職責不單一等問題。
  1. 實踐總結
  1. TDD用例、設計很難一步到位,需要代碼實作的檢驗

教育訓練過程中,老師要求嚴格按照TDD流程,如下圖所示:

  1. 先做任務分解,然後基于分解的任務,寫測試用例,測試fail;
  2. 再寫代碼實作,測試pass;
  3. 對代碼進行重構。
TDD實戰感想

通過近期個人實踐發現,設計、用例和代碼實作在不斷疊代循環,很難做到用例、設計一步到位。實際操作中,均是在先大緻考慮并輸出設計、測試用例後,通過代碼實作檢驗類圖、測試用例的正确性,不斷疊代。實際操作中,可通過補充時序圖、上下文圖等方法幫忙理清思路,盡量提高前期設計的正确性,避免後續實作時返工。

教育訓練期間,老師如此嚴格要求的目的可能在于:将TDD的執行流程推向極緻,讓大家有個深刻印象吧!!

  1. 可以不用TDD,但是驗收角度思考不能少

通過前面小節介紹可知,TDD最核心的價值在于:分離關注點,使開發者站在驗收角度思考問題,明确WHAT。

實際工作中,不見得必須使用TDD,但是作為開發人員,在承接新需求、設計、編碼任何環節,面臨新問題,都能夠注意站在驗收角度去思考問題,明确WHAT,再說HOW。

  1. 上下文圖

上下文圖主要用于表示已被分解的簡單任務,将函數的輸入、輸出(細化到參數類型、結構)圖形化,類似于時序圖的簡化版,有助于問題的拆解以及表達,适合内部交流使用。不過上下文圖非标準圖形,具體表達元素隻要組織内部達成一緻,形成統一語言即可:

  1. 函數名:帶命名的表示過程的方框;
  2. 輸入:指向方框的箭頭;
  3. 輸出:背離方框的箭頭。

如下圖所示,使用者流量套餐系統中的查詢套餐業務,上下文圖将簡單任務分解為:

  1. commandLine(指令行)

輸入:使用者指令(類型:字元串);

輸出:使用者套餐資訊(類型:字元串)

  1. Systemcontrol(系統控制)

輸入:NA,指令行系統解析指令後,直接調用systemcontrol對應處理,無輸入

輸出:使用者套餐資訊(類型:字元串),後面依次類推,不再逐個描述

  1. QueryPackageInfo(查詢套餐資訊)
  1. GetPackageInfo(擷取套餐資訊);
  2. PackageFormat(套餐資訊格式化);
  1. GetMenuInfo(擷取主菜單);
TDD實戰感想

在使用上下文圖時,若上下文圖嵌套的子產品層次太深時,會導緻圖形過于複雜,此時可基于場景對系統進一步拆分,保證上下文圖的簡潔、易讀。如上面例子所示的“使用者流量套餐系統”可基于使用者場景分為:查詢流量套餐、注冊使用者、訂閱流量套餐、取消流量套餐四個場景。應針對四種場景逐個畫上下文圖,而不是将四個場景融合在一個上下文圖中。要謹記上下文圖要簡潔、易讀,一個簡單的衡量方法:15分鐘内可完成的上下文圖認定為符合簡潔、易讀原則。

繼續閱讀