讓我們?cè)倭牧腡DD 續(xù)——人人都在做TDD
在上一篇文章《讓我們?cè)倭牧腡DD》里面,通過對(duì)DHH的文章以及DHH和Kent Beck等討論的分析,我闡述了對(duì)TDD的理解和分類,現(xiàn)在來繼續(xù)聊聊TDD的實(shí)施和分層。
現(xiàn)在還有非常多的軟件工程師在質(zhì)疑TDD的可行性,比如太難不會(huì)、成本太高無法推動(dòng)、意義不是很大等,但是他們卻一直都在做著TDD,只不過沒有意識(shí)到而已,這便是“不識(shí)廬山真面目,只緣身在此山中”。
TDD的實(shí)施一般分為思維層面和技術(shù)層面。一般來說,思維層面上的實(shí)施成本較低、容易接受,但是缺點(diǎn)很多,比如難以傳遞、難以持續(xù)獲得快速反饋等;而技術(shù)層面上的實(shí)施一般成本較高、不容易被人接受,但是優(yōu)點(diǎn)更多,比如可以獲得快速反饋、更容易傳遞和協(xié)作等。而現(xiàn)實(shí)世界中TDD的實(shí)施一般分為三個(gè)階段,即無意識(shí)的TDD、被動(dòng)通過技術(shù)實(shí)現(xiàn)的TDD、以及有意識(shí)和主動(dòng)通過技術(shù)實(shí)現(xiàn)的TDD。
1. ***階段:無意識(shí)的TDD
對(duì)于軟件開發(fā)人員,當(dāng)他們拿到一個(gè)新的軟件需求時(shí),首先會(huì)思考如何實(shí)現(xiàn),其中包括當(dāng)前軟件架構(gòu)、業(yè)務(wù)分解、實(shí)現(xiàn)設(shè)計(jì)、代碼分層、代碼實(shí)現(xiàn)等。然后通過思考和設(shè)計(jì)所得到的產(chǎn)出物來驅(qū)動(dòng)代碼實(shí)現(xiàn),進(jìn)而在代碼實(shí)現(xiàn)中會(huì)思考如何通過一個(gè)或多個(gè)函數(shù)或者算法來實(shí)現(xiàn)業(yè)務(wù)邏輯。所以軟件系統(tǒng)的實(shí)現(xiàn)要先通過意識(shí)層面的思考,再進(jìn)行技術(shù)層面的工作。
當(dāng)開發(fā)人員思考和設(shè)計(jì)這些函數(shù)或者方法的時(shí)候,一般都會(huì)思考它們有哪些參數(shù),然后想象將這些參數(shù)換成真實(shí)的數(shù)據(jù)后傳遞進(jìn)去,會(huì)得到怎樣的返回值。好一點(diǎn)的開發(fā)人員會(huì)思考如何處理異常輸入和異常返回值。
這類思考其實(shí)已經(jīng)是意識(shí)思維上的TDD,它幫助開發(fā)人員先在大腦里面設(shè)計(jì)并驗(yàn)證代碼實(shí)現(xiàn),甚至幫助其重構(gòu)代碼。所以很多開發(fā)人員都在無意識(shí)的情況下做著TDD。
比如在一個(gè)銀行系統(tǒng)里面,開發(fā)人員拿到一個(gè)需求,需要開發(fā)一個(gè)通過手機(jī)APP轉(zhuǎn)賬的功能。
首先開發(fā)人員會(huì)基于當(dāng)前的軟件架構(gòu)思考:是開發(fā)一個(gè)全新的模塊來處理這個(gè)業(yè)務(wù)?還是基于當(dāng)前架構(gòu)中的某個(gè)模塊來添加代碼進(jìn)行處理?
當(dāng)確定架構(gòu)和設(shè)計(jì)之后,就開始思考具體的代碼實(shí)現(xiàn),比如類的設(shè)計(jì)、方法的設(shè)計(jì)或者函數(shù)的設(shè)計(jì)等。當(dāng)開發(fā)“將錢從原帳號(hào)轉(zhuǎn)出”這個(gè)功能前,開發(fā)人員會(huì)思考:這個(gè)功能需要支持當(dāng)錢從原帳號(hào)中轉(zhuǎn)出成功后,原帳號(hào)中的余額等于原始余額減去轉(zhuǎn)出金額。進(jìn)一步有些程序員還會(huì)設(shè)計(jì)一些用來驗(yàn)證功能的實(shí)例,比如帳號(hào)中的原始余額是999.99,轉(zhuǎn)出111.11,那么剩余的金額就應(yīng)該是888.88。
在這樣思考之后,開發(fā)人員便開始根據(jù)自己大腦中的測試邏輯和用例來驅(qū)動(dòng)和輔助開發(fā)過程。在代碼開發(fā)完畢之后還會(huì)想一些辦法來驗(yàn)證一下所實(shí)現(xiàn)的功能是否符合預(yù)期,比如人工使用之前的或者新的測試用例再測試一下。如果驗(yàn)證正確,就會(huì)認(rèn)為自己開發(fā)的功能正確了,并交給測試人員進(jìn)行測試。
其實(shí)開發(fā)人員在開發(fā)前思考測試邏輯和用例的過程就是在做TDD了。
很多做業(yè)務(wù)分析的BA和測試分析前移的QA也同樣在無意識(shí)的做著TDD(注:在前一篇文章中已說明TDD包含ATDD),比如分析驗(yàn)收條件、寫出驗(yàn)收文檔等。只不過這些AC和驗(yàn)收文檔可能寫得不是很明確或者不是很好,比如不是實(shí)例化需求等,但是本質(zhì)上已經(jīng)是TDD了。
只不過是初級(jí)的無意識(shí)的TDD,可能有的人做得好,有的人做得不好,而且沒有明確的產(chǎn)出來協(xié)助和規(guī)范這個(gè)測試驅(qū)動(dòng)開發(fā)方式,也缺乏快速反饋、度量、傳遞和協(xié)作等。因此從無意識(shí)到有意識(shí)將是做好TDD的一個(gè)重要過渡。
2. 第二階段:被動(dòng)通過技術(shù)實(shí)現(xiàn)TDD
當(dāng)有一部分軟件工程師意識(shí)到了TDD的意義和普遍存在性之后,就開始準(zhǔn)備解決思維上的TDD的缺點(diǎn)。而解決這些問題的方法就是在技術(shù)層面上用代碼來實(shí)現(xiàn)TDD,用明確的代碼來協(xié)助和規(guī)范開發(fā)人員的測試驅(qū)動(dòng)開發(fā)行為,來度量他對(duì)業(yè)務(wù)邏輯以及代碼實(shí)現(xiàn)的理解度。通過將他的理解傳遞給以后的維護(hù)人員,讓他的理解能重復(fù)被使用,以及和其他人協(xié)作開發(fā)。
但是現(xiàn)實(shí)中很多開發(fā)人員的認(rèn)識(shí)不足以及技術(shù)能力不夠,就算管理層支持并且主動(dòng)推動(dòng)TDD,最終
由于開發(fā)人員設(shè)計(jì)和選取的測試用例合理性很差,導(dǎo)致驅(qū)動(dòng)出來的代碼有效性差,測試用例無法體現(xiàn)出SBE(Specification by example)導(dǎo)致易讀性差,對(duì)于自動(dòng)化測試框架和測試編寫不熟悉導(dǎo)致開發(fā)速度很慢等,往往是被動(dòng)的在技術(shù)層面上去實(shí)現(xiàn)TDD,所以出現(xiàn)了各種怨言,各種抵觸,進(jìn)而導(dǎo)致技術(shù)層面上的TDD很難以大規(guī)模實(shí)施。
由于意識(shí)層面上的難易程度和工作量都比技術(shù)層面上相對(duì)較小,所以前者實(shí)施起來相對(duì)容易一些,而后者則相對(duì)較難,所以如果通過了各種手段強(qiáng)行實(shí)施TDD,而沒有主動(dòng)去擺正做TDD的意識(shí),甚至沒有足夠的技術(shù)能力,那么這樣的TDD就是一個(gè)倒三角,非常容易倒塌。
TDD倒三角
所以,如果不希望技術(shù)層面上的TDD隨時(shí)倒塌,就需要把這個(gè)倒三角補(bǔ)全,才能更好的、長久的實(shí)施TDD。
3. 第三階段:有意識(shí)和主動(dòng)通過技術(shù)實(shí)現(xiàn)TDD
為了大規(guī)模以及有效的實(shí)施TDD,首先要突破思維意識(shí)的局限,認(rèn)識(shí)到TDD的普遍存在性和適用性,不要害怕和排斥TDD這種思維和開發(fā)模式。
其次要主動(dòng)學(xué)習(xí),并刻意練習(xí)TDD的技術(shù)實(shí)現(xiàn),提升自己的技術(shù)能力,從而在技術(shù)層面能更容易的實(shí)現(xiàn)TDD,擺脫被動(dòng)TDD的困境。其中學(xué)習(xí)的方法包括閱讀TDD相關(guān)的書籍和文章,書籍包括《測試驅(qū)動(dòng)開發(fā)》、《重構(gòu)》、《BDD In Action》以及《系統(tǒng)思考》等,從而充分理解TDD優(yōu)點(diǎn)和局限。
對(duì)于刻意練習(xí),一定要長時(shí)間堅(jiān)持去做,讓其成為一種習(xí)慣。如果在項(xiàng)目中沒有合適的環(huán)境去練習(xí),還可以通過一些第三方的TDD練習(xí)系統(tǒng)去做刻意練習(xí),比如Cyber-dojo。只有大量的刻意練習(xí)才能讓你在真實(shí)的代碼編寫過程中去思考和理解TDD,去運(yùn)用你通過學(xué)習(xí)得到的知識(shí),最終才能做到有意識(shí)和主動(dòng)的通過技術(shù)去實(shí)現(xiàn)TDD,TDD的倒三角才能變成一個(gè)穩(wěn)定的磚塊,然后哪里需要往哪里搬。
TDD磚塊
4. 總結(jié)
綜上,大部分開發(fā)人員都應(yīng)該在做TDD,只不過他們是無意識(shí)的或者被動(dòng)的去實(shí)現(xiàn)的,只有少部分是有意識(shí)和主動(dòng)的去實(shí)現(xiàn)的。
既然人人都在做TDD,那么我們?yōu)槭裁床荒芎秃诳偷蹏锩娴腘eo一樣選擇紅色藥丸來認(rèn)清楚現(xiàn)實(shí),主動(dòng)擁抱TDD,并通過大量的刻意練習(xí)去改變自己的工作習(xí)慣,讓TDD成為自己工作習(xí)慣的一部分,這樣才能更好的提升軟件質(zhì)量,大大降低軟件維護(hù)成本。不管你信不信,反正我信了。