如何提高產(chǎn)品開發(fā)品質(zhì)_第1頁
如何提高產(chǎn)品開發(fā)品質(zhì)_第2頁
如何提高產(chǎn)品開發(fā)品質(zhì)_第3頁
如何提高產(chǎn)品開發(fā)品質(zhì)_第4頁
如何提高產(chǎn)品開發(fā)品質(zhì)_第5頁
已閱讀5頁,還剩56頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、編輯課件如何提高產(chǎn)品開發(fā)品質(zhì)如何提高產(chǎn)品開發(fā)品質(zhì)編輯課件講解內(nèi)容講解內(nèi)容目前開發(fā)過程存在的問題1產(chǎn)品開發(fā)品質(zhì)保障流程2代碼重構(gòu)3測試驅(qū)動4日構(gòu)建5編輯課件一、目前開發(fā)過程存在的問題一、目前開發(fā)過程存在的問題l沒有完善的品質(zhì)保障流程沒有完善的品質(zhì)保障流程l質(zhì)量低下的代碼質(zhì)量低下的代碼l不重視測試不重視測試編輯課件產(chǎn)品開發(fā)流程現(xiàn)狀產(chǎn)品開發(fā)流程現(xiàn)狀開發(fā)人員編寫代碼開發(fā)人員編寫代碼調(diào)試調(diào)試, 肉眼觀察肉眼觀察有問題有問題沒問題(自認為)沒問題(自認為)可交付的代碼可交付的代碼編譯編譯修正編譯錯誤修正編譯錯誤登記到登記到JIRAJIRA上上客戶提出需求或客戶提出需求或現(xiàn)場發(fā)現(xiàn)現(xiàn)場發(fā)現(xiàn)bugbug編輯課件

2、產(chǎn)品品質(zhì)管理嚴重缺失產(chǎn)品品質(zhì)管理嚴重缺失 該流程的最終目標和工作重心都是完成產(chǎn)品功能開發(fā),品質(zhì)管理嚴重缺失。產(chǎn)品的開發(fā)質(zhì)量完全靠開發(fā)人員的個人責任心以及工作經(jīng)驗來保障,缺乏一個穩(wěn)定可靠的質(zhì)量保障流程。這種流程開發(fā)出來的產(chǎn)品往往是質(zhì)量不可靠,需要經(jīng)常返工的劣質(zhì)產(chǎn)品。編輯課件質(zhì)量低下的代碼是導(dǎo)致產(chǎn)品品質(zhì)質(zhì)量低下的代碼是導(dǎo)致產(chǎn)品品質(zhì)不好的根本原因不好的根本原因質(zhì)量低下的代碼體現(xiàn)在以下幾個方面:l重復(fù)的代碼l過長的函數(shù)l過大類l過長的參數(shù)列表l過度復(fù)雜的邏輯判斷l(xiāng)數(shù)據(jù)泥團編輯課件沒有專職測試人員來進行功能性沒有專職測試人員來進行功能性測試工作測試工作在目前的開發(fā)流程中,開發(fā)出來的代碼只經(jīng)過開發(fā)人員自己

3、簡單的測試,沒有專職的測試人員來進行詳細的功能性測試。這樣導(dǎo)致的結(jié)果往往是提交到現(xiàn)場的代碼會帶有不少BUG,一定要經(jīng)過多次返工才能達到較高的品質(zhì)。而且這樣做的另一個后果是把客戶當作測試人員,會給客戶留下產(chǎn)品品質(zhì)不穩(wěn)定這樣一種非常不好的客戶體驗。編輯課件開發(fā)人員在開發(fā)過程中不重視單開發(fā)人員在開發(fā)過程中不重視單元測試元測試單元測試是提高產(chǎn)品品質(zhì)非常重要的一個方法,而我們的開發(fā)人員往往會忽視這一點。如果沒有單元測試,僅僅依靠測試人員的功能性測試,那么這樣的測試工作量會非常大,每次修改一個功能,可能會影響到的其他功能都要一一測試,不僅測試時間會非常長,而且效果也不好,很多細節(jié)不一定每次都能測到,這些都

4、是產(chǎn)生BUG的隱患。同時由于我們業(yè)務(wù)需求都非常復(fù)雜多變的,沒有一個完善自動化測試流程,而僅僅依靠人工測試,對產(chǎn)品品質(zhì)的影響是不言而喻的。編輯課件我們的目標!我們的目標!l編寫出邏輯清晰、結(jié)構(gòu)簡潔、擴展性良好、可測試性高的優(yōu)秀代碼。l強化單元測試工作,提高單元測試覆蓋率,搭建自動單元測試集,通過日構(gòu)建來持續(xù)集成,對產(chǎn)品質(zhì)量進行全面控制。l通過嚴格的產(chǎn)品質(zhì)量管理流程,強化質(zhì)量管理工作,將所有BUG消滅在公司內(nèi)部。編輯課件二、產(chǎn)品開發(fā)品質(zhì)保障流程二、產(chǎn)品開發(fā)品質(zhì)保障流程編輯課件開發(fā)質(zhì)量管理開發(fā)質(zhì)量管理本開發(fā)流程的目標是開發(fā)出質(zhì)量優(yōu)良的產(chǎn)品,流程的重心在于質(zhì)量管控,通過質(zhì)量保障人員對產(chǎn)品質(zhì)量進行全面把

5、關(guān)。l對于沒有編寫單元測試的代碼直接打回!l質(zhì)量保障人員負責進行功能性測試,并對提交出去的代碼負責。l質(zhì)量保障人員另一個職責是思考如何持續(xù)改進產(chǎn)品質(zhì)量。編輯課件需求管控需求管控l對每個需求進行分級評審,最大程度的降低需求變更的頻度。l所有需求開發(fā)前都經(jīng)過內(nèi)部評審,對于一些復(fù)雜需求把握更加準確,不至于在開發(fā)時候產(chǎn)生較大偏差。l所有需求的開發(fā)工作都有經(jīng)過客戶簽字的開發(fā)工作量評估,為商務(wù)工作開展創(chuàng)造有利條件。l所有需求都有詳細開發(fā)計劃,片區(qū)人員可以安排相應(yīng)的測試計劃。編輯課件全過程管控全過程管控l所有缺陷和經(jīng)過評審的需求都必須在JIRA上登記,否則不予開發(fā)。l開發(fā)計劃通過JIRA進行精確體現(xiàn)。l片區(qū)

6、人員可以通過JIRA實時跟蹤產(chǎn)品開發(fā)進度。l方便后續(xù)各類工作量的統(tǒng)計。編輯課件三、利用代碼重構(gòu)來提高代碼質(zhì)量三、利用代碼重構(gòu)來提高代碼質(zhì)量 重構(gòu)(Refactoring):是對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變外部行為的前提下,提高其可理解性,降低其修改成本編輯課件為什么重構(gòu)(為什么重構(gòu)(1)l改進軟件的設(shè)計。l程序員對代碼所做的為了滿足短期利益代碼改動,或再沒有完全清楚增個架構(gòu)下的改動,都很容易是代碼失去它的清晰結(jié)構(gòu),偏離需求或設(shè)計。而這些改動的積累很容易使代碼偏離它原先設(shè)計的初衷而變得不可立即和無法維護。l重構(gòu)則幫助重新組織代碼,重新清晰的體現(xiàn)結(jié)構(gòu)和進一步改進設(shè)計。編輯課件為什么重構(gòu)(

7、為什么重構(gòu)(2)l提高代碼質(zhì)量,更易被理解l容易理解的代碼可以很容易的維護和做進一步的開發(fā)。即使對寫這些代碼的程序員本身,容易理解代碼也可以幫助容易地做修改。程序代碼也是文檔。而代碼首先是寫給人看的,讓后才是給計算機看的。l重構(gòu)幫助盡早的發(fā)現(xiàn)錯(Bugs)l重構(gòu)是一個code review和反饋的過程。在另一個時段重新審視自己或別人代碼,可以更容易的發(fā)現(xiàn)問題和加深對代碼的理解。l重構(gòu)是一個良好的軟件開發(fā)習慣。編輯課件為什么重構(gòu)(為什么重構(gòu)(3)l重構(gòu)可以提高開發(fā)速度l重構(gòu)對設(shè)計和代碼的改進,都可以有效的提高開發(fā)速度。好的設(shè)計和代碼質(zhì)量實體提高開發(fā)速度的關(guān)鍵。在一個有缺陷的設(shè)計和混亂代碼基礎(chǔ)上的

8、開發(fā),即使表面上進度較快,但本質(zhì)是試延后對設(shè)計缺陷的發(fā)現(xiàn)和對錯誤的修改,也就是延后了開發(fā)風險,最終要在開發(fā)的后期付出更多的時間和代價。l項目的維護成本遠高于開發(fā)成本.編輯課件何時重構(gòu)何時重構(gòu)? ?l添加或者修改功能時一并重構(gòu)l為了增加一個新的功能或者修改原有的功能,程序員需要首先讀懂現(xiàn)有的代碼。l修補錯誤時一并重構(gòu)l為了修復(fù)一個Bug,程序員需要讀懂現(xiàn)有的代碼。lCode Review時一并重構(gòu)編輯課件何時不該重構(gòu)何時不該重構(gòu)? ?l代碼太混亂,設(shè)計完全錯誤。與其Refactor,不如重寫。l明天是DeadLinel永遠不要做Last-Minute-Change。推遲重構(gòu),但不可以忽略,即使進

9、入產(chǎn)品期的代碼都正確的運行。編輯課件重構(gòu)方法介紹:提取函數(shù)(重構(gòu)方法介紹:提取函數(shù)(1)String name = request.getParameter(Name);if( name != null & name.length() 0 ).String age = request.getParameter(Age);if( age != null & age.length() 0 ).String name = request.getParameter(Name);if( !isNullOrEmpty( name ) ).String age = request.getPa

10、rameter(Age);if( !isNullOrEmpty( age ) ).private boolean isNullOrEmpty( final String string )if( string != null & string.length() 0 )return true;elsereturn false;編輯課件重構(gòu)方法介紹:提取函數(shù)(重構(gòu)方法介紹:提取函數(shù)(2) 提取函數(shù)是我最常用的重構(gòu)手法之一。當我看見一個過長的函數(shù)或者一段需要注釋才能讓人理解用途的代碼,我就會將這段代碼放進一個獨立的函數(shù)中。有數(shù)個原因造成我喜歡簡短而有良好命名的函數(shù)。首先,如果每個函數(shù)的粒度都很

11、小,那么函數(shù)之間彼此復(fù)用的機會就更大;其次,這會使高層函數(shù)讀起來就像一系列注釋;再者,如果函數(shù)都是細粒度,那么函數(shù)的覆寫(override )也會更容易些: 的確,如果你習慣了看大型函數(shù),恐怕需要一段時問才能適應(yīng)達種新風格,而且只有當你能給小型函數(shù)很好地命名時,它們才能真正起作用,所以你需要在函數(shù)名稱下點功夫,一個函數(shù)多長才算合適?在我看來.長度不是問題,關(guān)鍵在于函數(shù)名稱和函數(shù)本體之間的語義距離,如果提煉動作可以強化代碼的清晰度,那就去做,就是函數(shù)名稱比提煉出來的代碼還長也無所謂。編輯課件重構(gòu)方法介紹:去除臨時變量重構(gòu)方法介紹:去除臨時變量(1)(1)編輯課件重構(gòu)方法介紹:去除臨時變量重構(gòu)方法

12、介紹:去除臨時變量(2)(2)我喜歡盡量除去函數(shù)內(nèi)的臨時變量。臨時變量往往形成問題,它們會導(dǎo)致大量參數(shù)被傳來傳去,而其實完全沒有這種必要。你很容易失去它們的蹤跡,尤其在長長的函數(shù)之中更是如此。而且,臨時變量的存在,往往會阻礙提取函數(shù)等其他重構(gòu)手法的進行。編輯課件重構(gòu)方法介紹:重新命名函數(shù)重構(gòu)方法介紹:重新命名函數(shù)(1)(1)public String getItemName (int itemSort,String itemName)return +itemSort+、+itemName; public String formatItemName (int itemSort,String it

13、emName)return +itemSort+、+itemName; 編輯課件重構(gòu)方法介紹:重新命名函數(shù)重構(gòu)方法介紹:重新命名函數(shù)(2)(2)我極力提倡的一種編程風格就是:將復(fù)雜的處理過程分解成小函數(shù)。但是,如果做得不好,這會使你費盡周折卻弄不清楚這些小函數(shù)各白的用途、.要避免這種麻煩,關(guān)鍵就在于給函數(shù)起一個好名稱;函數(shù)的名稱應(yīng)該準確表達它的用途;給函數(shù)命名有一個好辦法。首先考慮應(yīng)該給這個函數(shù)寫上一句怎樣的注釋,然后想辦法將注釋變成函數(shù)名稱。人生不如意十之八九:你常常無法第一次就給函數(shù)起一個好名稱,這時候你可能會想,就這樣將就著吧,畢竟只是一個名稱而已。當心!這是惡魔的召喚,是通向混亂之路,

14、千萬不要被它誘惑!如果你看到一個函數(shù)名稱不能很好地表達它的用途,應(yīng)該馬上加以修改。記住,你的代碼首先是為人寫的,其次才是為計算器寫的。而人需要良好名稱的函數(shù)。想想過去曾經(jīng)浪費的無數(shù)時間吧,如果給每個函數(shù)都起一個良好的名稱,也許你可以節(jié)約好多時間。取一個好名稱并不容易,需要經(jīng)驗,要想成為一個真正的編程高手,取名稱的水平是至關(guān)重要的。編輯課件重構(gòu)方法介紹:以多態(tài)取代條件重構(gòu)方法介紹:以多態(tài)取代條件表達式(表達式(1 1)public class PlanUtil public void setPlanState(int planYear,int itemId,int dataType)switch

15、 dataType case 1:setPrePlanState(planYear,itemId); case 2:setColPlanState(planYear,itemId); case 3:setA(planYear,itemId); default:throw new RuntimeException(不正確的計劃類型:+dataType);/.更新建議計劃狀態(tài)public void setPrePlanState /.更新綜合計劃狀態(tài)public void setColPlanState. /.更新開工計劃狀態(tài)public void setA.public class PlanUt

16、il public static PlanUtil create (int dataType)switch (dataType)case 1:return new PrePlanUtil();case 2:return new ColPlanUtil();case 3:return new A();default:throw new RuntimeException(不正確的計劃類型:+dataType);public abstract void setPlanState (int planYear,int itemId,int dataType);public abstract void s

17、avePlan (int planYear,int itemId,int dataType);編輯課件重構(gòu)方法介紹:以多態(tài)取代條件重構(gòu)方法介紹:以多態(tài)取代條件表達式(表達式(2)/保存計劃數(shù)據(jù)public void savePlan(int planYear,int itemId,int dataType)switch dataTypecase 1:savePrePlan(planYear,itemId);case 2:saveColPlan(planYear,itemId);case 3:saveA(planYear,itemId); default: throw new RuntimeEx

18、ception(不正確的計劃類型:+dataType);/.保存建議計劃數(shù)據(jù)public void savePrePlan /.保存綜合計劃數(shù)據(jù)public void saveColPlan/.保存開工計劃數(shù)據(jù)public void saveApublic class PrePlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新建議計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存

19、建議計劃數(shù)據(jù)方法public class ColPlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新綜合計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存綜合計劃數(shù)據(jù)方法編輯課件重構(gòu)方法介紹:以多態(tài)取代條件重構(gòu)方法介紹:以多態(tài)取代條件表達式(表達式(3)/調(diào)用更新計劃狀態(tài)的方法planUtil.setPlanState(year,itemId,dataType);/調(diào)用保存計劃數(shù)

20、據(jù)的方法planUtil.savePlanyear,itemId,dataType);public class AftPlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新開工計劃狀態(tài)方法public void savePlan (int planYear,int itemId,int dataType)保存開工計劃數(shù)據(jù)方法/調(diào)用PlanUtil planUtil = PlanUtil .create(dataType);/調(diào)用更新計劃狀態(tài)的方法planUtil.

21、setPlanState(year,itemId,dataType);/調(diào)用保存計劃數(shù)據(jù)的方法planUtil.savePlan (year,itemId,dataType);編輯課件重構(gòu)方法介紹:以多態(tài)取代條件重構(gòu)方法介紹:以多態(tài)取代條件表達式(表達式(4)l多態(tài)最根本的好處就是:如果你需要根據(jù)對象的不同型別而采取不同的行為,多態(tài)使你不必編寫明顯的條件式。正因為有了多態(tài),所以你會發(fā)現(xiàn):針對type code(型別碼)而寫的switch語句,以及針對type string(型別名稱字符串)而寫的if-then-else語句在面向?qū)ο蟪绦蛑泻苌俪霈F(xiàn)。l多態(tài)能夠給你帶來很多好處。如果同一組條件式在

22、程序許多地點出現(xiàn),那么使用多態(tài)的收益是最大的。使用條件式時,如果你想添加一種新型別,就必須杳找并更新所有條件式。但如果改用多態(tài),只需建一個新的subclass并在其中提供適當?shù)暮瘮?shù)就行了。class用戶不需要了解這個subclass,這就大大降低了系統(tǒng)各部分之間的耦合程度,使系統(tǒng)升級.更加容易。編輯課件重構(gòu)方法介紹:以委托取代繼承重構(gòu)方法介紹:以委托取代繼承(1)(1)/繼承解決方案public classBusPlanManagerServiceImpl public void setPlanState (int planYear,int itemId,int dataType). 更新建議

23、計劃狀態(tài)方法 public void savePlan (int planYear,int itemId,int dataType)保存建議計劃數(shù)據(jù)方法public class PrePlanService extends BusPlanManagerServiceImpl .public class ColPlanService extends BusPlanManagerServiceImpl .public class AftPlanService extends BusPlanManagerServiceImpl ./委托解決方案public classBusPlanManagerSe

24、rviceImplpublic void setPlanState (int planYear,int itemId,int dataType)PlanUtil planUtil = PlanUtil .create(dataType);/調(diào)用更新計劃狀態(tài)的方法planUtil.setPlanState(year,itemId,dataType);public void savePlan (int planYear,int itemId,int dataType)PlanUtil planUtil = PlanUtil .create(dataType);/調(diào)用更新計劃狀態(tài)的方法planUti

25、l. savePlan (year,itemId,dataType); 編輯課件重構(gòu)方法介紹:以委托取代繼承重構(gòu)方法介紹:以委托取代繼承(2)(2)l繼承是一件很棒的事,但有時候它并不是你要的。常常你會遇到這樣的情況:一開始你繼承了一個class ,隨后發(fā)現(xiàn)superclass中的許多操作井不真正適用于subclass。這種情況下你所擁有的接口并末真正反映出class的功能?;蛘撸憧赡馨l(fā)現(xiàn)你從superclass中繼承了一大堆subclas并不需要的數(shù)據(jù),抑或者你可能發(fā)現(xiàn)superclass中的某些protected函數(shù)對subclass并沒有什么意義。l你可以選擇容忍,并接受傳統(tǒng)說法:su

26、bclass可以只使用superclas、功能的一部分。但這樣做的結(jié)果是:代碼傳達的信息與你的意圖南轅北轍,這是一種混淆,你應(yīng)該將它去除。如果以委托取代繼承,你可以更清楚地表明:你只需要受托類的一部分功能。接口中的哪一部分應(yīng)該被使用,哪一部分應(yīng)該被忽略,完全由你主導(dǎo)控制。這樣做的成本則是需耍額外寫出委托函數(shù),但這些函數(shù)都非常簡單,極少可能出錯。編輯課件重構(gòu)方法介紹:引入?yún)?shù)對象重構(gòu)方法介紹:引入?yún)?shù)對象(1)public List getYearPlanList (String operatorID, String planYear,String iSeason, String planTyp

27、e,String dataType).public List getLastYearPlanList (String operatorID, String planYear,String iSeason, String planType,String dataType)public void fillPlanData (String operatorID, String planYear,String iSeason, String planType,String dataType)PlanData planData=new PlanData();planData.setYeraPlanLis

28、t(getYearPlanList (operatorID,planYear, iSeason,planType,dataType);planData.setLastYeraPlanList(getLastYearPlanList (operatorID,planYear, iSeason,planType,dataType);public class PlanParamObj private String operatorID;private String planYear;private String iSeason;private String planType,;private Str

29、ing dataType;public PlanParamObj (String operatorID, String planYear,String iSeason, String planType,String dataType) this.operatorID=operatorID;this.planYear=planYear;this.iSeason=iSeason;this.planType=planType;this.dataType=dataType;編輯課件重構(gòu)方法介紹:引入?yún)?shù)對象重構(gòu)方法介紹:引入?yún)?shù)對象(2)public List getYearPlanList (Pla

30、nParamObj paramObj).public List getLastYearPlanList (PlanParamObj paramObj).public void fillPlanData (String operatorID, String planYear,String iSeason, String planType,String dataType)PlanParamObj paramObj = new PlanParamObj (operatorID,planYear, iSeason,planType,dataType);PlanData planData=new Pla

31、nData();planData.setYeraPlanList(getYearPlanList (paramObj);planData.setLastYeraPlanList(getLastYearPlanList (paramObj );編輯課件重構(gòu)方法介紹:引入?yún)?shù)對象重構(gòu)方法介紹:引入?yún)?shù)對象(3)l你常會看到特定的數(shù)組參數(shù)總是一起被傳遞??赡苡泻脦讉€函數(shù)都使用這一組參數(shù),這些函數(shù)可能隸屬同個class,也可能隸屬不同的classes。這樣一組參數(shù)就是所謂的data Clump(數(shù)據(jù)泥團),我們可以運用一個對象包裝所有這些數(shù)據(jù),再以該對象取代它們。哪伯只是為了把這些數(shù)據(jù)組織在一起,這樣

32、做也是值得的。本項重構(gòu)的價值在于縮短了參數(shù)列的長度,而你知道,過長的參數(shù)列總是難以理解的。此外,新對象所定義的訪問函數(shù)還可以使代碼更具一致性,這又進一步降低了代碼的理解難度和修改難度。l本項重構(gòu)還可以帶給你更多好處。當你把這些參數(shù)組織到起之后,往往很快可以發(fā)現(xiàn)一些可被移至新建class的行為。通常,原本使用那些參數(shù)的函數(shù)對那些參數(shù)會有一些共通措施,如果將這些共通行為移到新對象中,你可以減少很多重復(fù)代碼編輯課件重構(gòu)方法介紹:函數(shù)遷移重構(gòu)方法介紹:函數(shù)遷移(1)(1)public class RepUtilFunc private List initFundList().this.copyFund

33、View(fView,planView); /匯總投資計劃數(shù)據(jù)private void copyFundView (FundView fView,PlanView planView)fView.setFund(fView.getFund()+planView.getFund();fView.setUpprefund(fView.getUpprefund()+planView.getUpprefund();fView.setDownprefund(fView.getDownprefund()+planView.getDownprefund();public class RepUtilFunc p

34、rivate List initFundList().fView.copyFundView(planView); /匯總投資計劃數(shù)據(jù)編輯課件重構(gòu)方法介紹:重構(gòu)方法介紹:函數(shù)遷移函數(shù)遷移(2)(2)public class FundView private double fund;private String upprefund; private String downprefund;getset方法public class FundView private double fund;private String upprefund; private String downprefund;gets

35、et方法public void copyFundView (PlanView planView)this.setFund(this.getFund()+planView.getFund();this.setUpprefund(this.getUpprefund()+planView.getUpprefund();this.setDownprefund(this.getDownprefund()+planView.getDownprefund();編輯課件重構(gòu)方法介紹:重構(gòu)方法介紹:函數(shù)遷移函數(shù)遷移(3)(3)函數(shù)遷移是重構(gòu)理論的支柱。如果一個class有太多行為,或如果一個class與另一個c

36、lass有太多合作而形成高度耦合,我就會遷移函數(shù)。通過這種手段,我可以使系統(tǒng)中的classes更簡單,這些classes最終也將更干凈利落地實現(xiàn)系統(tǒng)交付的任務(wù)。常常我會瀏覽class的所有函數(shù),從中尋找這樣的函數(shù),使用另一個對象的次數(shù)比使用自己所駐對象的次數(shù)還多,就會進行函數(shù)遷移。編輯課件重構(gòu)方法介紹:將過程化設(shè)計轉(zhuǎn)重構(gòu)方法介紹:將過程化設(shè)計轉(zhuǎn)換為面向?qū)ο笤O(shè)計換為面向?qū)ο笤O(shè)計l有時間的話用一個實際例子進行展示。編輯課件四、測試驅(qū)動開發(fā)方法簡介四、測試驅(qū)動開發(fā)方法簡介測試驅(qū)動開發(fā)(Test Driven Development,英文縮寫TDD)是極限編程的一個重要組成部分,它的基本思想就是在開發(fā)

37、功能代碼之前,先編寫代碼的單元測試用例。也就是說在明確要開發(fā)某個功能后,首先思考如何對這個功能進行測試,并完成測試用例的編寫,然后編寫相關(guān)的代碼滿足這些測試用例。循環(huán)進行添加其他功能,直到完成全部功能的開發(fā)。代碼整潔可用(clean code that works) 是測試驅(qū)動開發(fā)所追求的目標。編輯課件測試驅(qū)動開發(fā)優(yōu)點測試驅(qū)動開發(fā)優(yōu)點(1)(1)l需求向來就是軟件開發(fā)過程中感覺最不好明確描述、易變的東西。這里說的需求不只是指用戶的需求,還包括對代碼的使用需求。很多開發(fā)人員最害怕的就是后期還要修改某個類或者函數(shù)的接口進行修改或者擴展,為什么會發(fā)生這樣的事情就是因為這部分代碼的使用需求沒有很好的描

38、述。測試驅(qū)動開發(fā)就是通過編寫測試用例,先考慮代碼的使用需求(包括功能、過程、接口等),而且這個描述是無二義的,可執(zhí)行驗證的。 l通過編寫這部分代碼的測試用例,對其功能的分解、使用過程、接口都進行了設(shè)計。而且這種從使用角度對代碼的設(shè)計通常更符合后期開發(fā)的需求??蓽y試的要求,對代碼的內(nèi)聚性的提高和復(fù)用都非常有益。因此測試驅(qū)動開發(fā)也是一種代碼設(shè)計的過程。 l開發(fā)人員通常對編寫文檔非常厭煩,但要使用、理解別人的代碼時通常又希望能有文檔進行指導(dǎo)。而測試驅(qū)動開發(fā)過程中產(chǎn)生的測試用例代碼就是對代碼的最好的解釋。 編輯課件測試驅(qū)動開發(fā)優(yōu)點測試驅(qū)動開發(fā)優(yōu)點(2)(2)l快樂工作的基礎(chǔ)就是對自己有信心,對自己的工

39、作成果有信心。當前很多開發(fā)人員卻經(jīng)常在擔心:“代碼是否正確?”“辛苦編寫的代碼還有沒有嚴重bug?”“修改的新代碼對其他部分有沒有影響?”。這種擔心甚至導(dǎo)致某些代碼應(yīng)該修改卻不敢修改的地步。測試驅(qū)動開發(fā)提供的測試集就可以作為你信心的來源。 l當然測試驅(qū)動開發(fā)最重要的功能還在于保障代碼的正確性,能夠迅速發(fā)現(xiàn)、定位bug。而迅速發(fā)現(xiàn)、定位bug是很多開發(fā)人員的夢想。針對關(guān)鍵代碼的測試集,以及不斷完善的測試用例,為迅速發(fā)現(xiàn)、定位bug提供了條件。 l我的一段功能非常復(fù)雜的代碼使用TDD開發(fā)完成,真實環(huán)境應(yīng)用中只發(fā)現(xiàn)幾個bug,而且很快被定位解決。您在應(yīng)用后,也一定會為那種自信的開發(fā)過程,功能不斷增加

40、、完善的感覺,迅速發(fā)現(xiàn)、定位bug的能力所感染,喜歡這個技術(shù)的。 編輯課件測試驅(qū)動開發(fā)基本過程測試驅(qū)動開發(fā)基本過程l明確當前要完成的功能。可以記錄成一個 TODO 列表。l快速完成針對此功能的測試用例編寫。l測試代碼編譯不通過。l編寫對應(yīng)的功能代碼。l測試通過。l對代碼進行重構(gòu),并保證測試通過。l循環(huán)完成所有功能的開發(fā) 編輯課件測試驅(qū)動開發(fā)案例測試驅(qū)動開發(fā)案例(1)(1) 需求:實現(xiàn)Fibonacci數(shù)列Fibonacci數(shù)列簡介:Fibonacci數(shù)列從第0項開始依次為0,1,1,2,3,5,8的數(shù)列,它存在如下特點:第0,1個數(shù)為0,1。從第2個數(shù)開始,該數(shù)是前面兩個數(shù)之和。 編輯課件測試

41、驅(qū)動開發(fā)案例測試驅(qū)動開發(fā)案例(2)(2) 先編寫測試代碼 : import junit.framework.TestCase; public class FibonacciTest extends TestCasepublic void testFibonacci() FibUtil fb = new FibUtil(); 編寫完測試代碼之后在Eclipse中運行該測試類,發(fā)現(xiàn)Junit運行出錯(顯示了一條紅色杠) 這是在預(yù)料之中,因為我們還沒有編寫FibUtil類。編輯課件測試驅(qū)動開發(fā)案例測試驅(qū)動開發(fā)案例(3)(3) 為了使測試通過,那么下面開始編寫FibUtil類public class

42、FibUtil 然后再次運行測試類。這時會發(fā)現(xiàn)測試成功。 編輯課件測試驅(qū)動開發(fā)案例測試驅(qū)動開發(fā)案例(4)(4) 下面增加測試用例,開始測試Fibonacci數(shù)列的實現(xiàn)函數(shù)fib:public void testFibonacci() FibUtil fb = new FibUtil(); assertEquals(0,fb.fib(0); 由于出現(xiàn)編譯錯誤,所以需要在FibUtil類中增加fib方法如下:public int fib ( int i) return 0 ; 運行測試用例,通過! 編輯課件測試驅(qū)動開發(fā)案例測試驅(qū)動開發(fā)案例(5)(5) 繼續(xù)增加測試用例,判斷1的情況:public void testFibonacci() FibUtil fb = new FibUtil(); assertEquals(0,fb.fib(0)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論