




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、如何提高產品開發質量.講解內容目前開發過程存在的問題1產品開發質量保證流程2代碼重構3測試驅動4日構建5.一、目前開發過程存在的問題沒有完善的質量保證流程質量低下的代碼不注重測試.產品開發流程現狀開發人員編寫代碼調試, 肉眼察看有問題沒問題自以為可交付的代碼編譯修正編譯錯誤登記到JIRA上客戶提出需求或現場發現bug.產品質量管理嚴重缺失 該流程的最終目的和任務重心都是完成產品功能開發,質量管理嚴重缺失。產品的開發質量完全靠開發人員的個人責任心以及任務閱歷來保證,缺乏一個穩定可靠的質量保證流程。這種流程開發出來的產品往往是質量不可靠,需求經常返工的劣質產品。.質量低下的代碼是導致產品質量不好的
2、根本緣由質量低下的代碼表達在以下幾個方面:反復的代碼過長的函數過大類過長的參數列表過度復雜的邏輯判別數據泥團.沒有專職測試人員來進展功能性測試任務在目前的開發流程中,開發出來的代碼只經過開發人員本人簡單的測試,沒有專職的測試人員來進展詳細的功能性測試。這樣導致的結果往往是提交到現場的代碼會帶有不少BUG,一定要經過多次返工才干到達較高的質量。而且這樣做的另一個后果是把客戶當作測試人員,會給客戶留下產品質量不穩定這樣一種非常不好的客戶體驗。.開發人員在開發過程中不注重單元測試單元測試是提高產品質量非常重要的一個方法,而我們的開發人員往往會忽視這一點。假設沒有單元測試,僅僅依托測試人員的功能性測試
3、,那么這樣的測試任務量會非常大,每次修正一個功能,能夠會影響到的其他功能都要一一測試,不僅測試時間會非常長,而且效果也不好,很多細節不一定每次都能測到,這些都是產生BUG的隱患。同時由于我們業務需求都非常復雜多變的,沒有一個完善自動化測試流程,而僅僅依托人工測試,對產品質量的影響是不言而喻的。.我們的目的!編寫出邏輯明晰、構造簡約、擴展性良好、可測試性高的優秀代碼。強化單元測試任務,提高單元測試覆蓋率,搭建自動單元測試集,經過日構建來繼續集成,對產質量量進展全面控制。經過嚴厲的產質量量管理流程,強化質量管理任務,將一切BUG消滅在公司內部。.二、產品開發質量保證流程.開發質量管理本開發流程的目
4、的是開發出質量優良的產品,流程的重心在于質量管控,經過質量保證人員對產質量量進展全面把關。對于沒有編寫單元測試的代碼直接打回!質量保證人員擔任進展功能性測試,并對提交出去的代碼擔任。質量保證人員另一個職責是思索如何繼續改良產質量量。.需求管控對每個需求進展分級評審,最大程度的降低需求變卦的頻度。一切需求開發前都經過內部評審,對于一些復雜需求把握更加準確,不至于在開發時候產生較大偏向。一切需求的開發任務都有經過客戶簽字的開發任務量評價,為商務任務開展發明有利條件。一切需求都有詳細開發方案,片區人員可以安排相應的測試方案。.全過程管控一切缺陷和經過評審的需求都必需在JIRA上登記,否那么不予開發。
5、開發方案經過JIRA進展準確表達。片區人員可以經過JIRA實時跟蹤產品開發進度。方便后續各類任務量的統計。.三、利用代碼重構來提高代碼質量 重構Refactoring:是對軟件內部構造的一種調整,目的是在不改動外部行為的前提下,提高其可了解性,降低其修正本錢.為什么重構1改良軟件的設計。程序員對代碼所做的為了滿足短期利益代碼改動,或再沒有完全清楚增個架構下的改動,都很容易是代碼失去它的明晰構造,偏離需求或設計。而這些改動的積累很容易使代碼偏離它原先設計的初衷而變得不可立刻和無法維護。重構那么協助重新組織代碼,重新明晰的表達構造和進一步改良設計。.為什么重構2提高代碼質量,更易被了解容易了解的代
6、碼可以很容易的維護和做進一步的開發。即使對寫這些代碼的程序員本身,容易了解代碼也可以協助容易地做修正。程序代碼也是文檔。而代碼首先是寫給人看的,讓后才是給計算機看的。重構協助盡早的發現錯(Bugs)重構是一個code review和反響的過程。在另一個時段重新審視本人或他人代碼,可以更容易的發現問題和加深對代碼的了解。重構是一個良好的軟件開發習慣。.為什么重構3重構可以提高開發速度重構對設計和代碼的改良,都可以有效的提高開發速度。好的設計和代碼質量實體提高開發速度的關鍵。在一個有缺陷的設計和混亂代碼根底上的開發,即使外表上進度較快,但本質是試延后對設計缺陷的發現和對錯誤的修正,也就是延后了開發
7、風險,最終要在開發的后期付出更多的時間和代價。工程的維護本錢遠高于開發本錢.何時重構?添加或者修正功能時一并重構為了添加一個新的功能或者修正原有的功能,程序員需求首先讀懂現有的代碼。修補錯誤時一并重構為了修復一個Bug,程序員需求讀懂現有的代碼。Code Review時一并重構.何時不該重構?代碼太混亂,設計完全錯誤。與其Refactor,不如重寫。明天是DeadLine永遠不要做Last-Minute-Change。推遲重構,但不可以忽略,即使進入產品期的代碼都正確的運轉。.重構方法引見:提取函數1String name = request.getParameter(Name);if( na
8、me != 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.getParameter(Age);if( !isNullOrEmpty( age ) ).private boolean isNullOrEmpty( final String string )if( st
9、ring != null & string.length() 0 )return true;elsereturn false;.重構方法引見:提取函數2 提取函數是我最常用的重構手法之一。當我看見一個過長的函數或者一段需求注釋才干讓人了解用途的代碼,我就會將這段代碼放進一個獨立的函數中。有數個緣由呵斥我喜歡簡短而有良好命名的函數。首先,假設每個函數的粒度都很小,那么函數之間彼此復用的時機就更大;其次,這會使高層函數讀起來就像一系列注釋;再者,假設函數都是細粒度,那么函數的覆寫(override )也會更容易些: 確實,假設他習慣了看大型函數,恐怕需求一段時問才干順應達種新風格,而且只需當他能給
10、小型函數很好地命名時,它們才干真正起作用,所以他需求在函數稱號下點功夫,一個函數多長才算適宜?在我看來.長度不是問題,關鍵在于函數稱號和函數本體之間的語義間隔,假設提煉動作可以強化代碼的明晰度,那就去做,就是函數稱號比提煉出來的代碼還長也無所謂。.重構方法引見:去除暫時變量(1).重構方法引見:去除暫時變量(2)我喜歡盡量除去函數內的暫時變量。暫時變量往往構成問題,它們會導致大量參數被傳來傳去,而其實完全沒有這種必要。他很容易失去它們的蹤跡,尤其在長長的函數之中更是如此。而且,暫時變量的存在,往往會妨礙提取函數等其他重構手法的進展。.重構方法引見:重新命名函數(1)public String
11、getItemName (int itemSort,String itemName)return +itemSort+、+itemName; public String formatItemName (int itemSort,String itemName)return +itemSort+、+itemName; .重構方法引見:重新命名函數(2)我竭力提倡的一種編程風格就是:將復雜的處置過程分解成小函數。但是,假設做得不好,這會使他費盡周折卻弄不清楚這些小函數各白的用途、.要防止這種費事,關鍵就在于給函數起一個好稱號;函數的稱號應該準確表達它的用途;給函數命名有一個好方法。首先思索應該給這
12、個函數寫上一句怎樣的注釋,然后想方法將注釋變成函數稱號。人生不如意十之八九:他經常無法第一次就給函數起一個好稱號,這時候他能夠會想,就這樣將就著吧,畢竟只是一個稱號而已。留意!這是惡魔的呼喚,是通向混亂之路,千萬不要被它誘惑!假設他看到一個函數稱號不能很好地表達它的用途,應該馬上加以修正。記住,他的代碼首先是為人寫的,其次才是為計算器寫的。而人需求良好稱號的函數。想想過去曾經浪費的無數時間吧,假設給每個函數都起一個良好的稱號,也許他可以節約好多時間。取一個好稱號并不容易,需求閱歷,要想成為一個真正的編程高手,取稱號的程度是至關重要的。.重構方法引見:以多態取代條件表達式1public clas
13、s PlanUtil public void setPlanState(int planYear,int itemId,int dataType)switch dataType case 1:setPrePlanState(planYear,itemId); case 2:setColPlanState(planYear,itemId); case 3:setAftPlanState(planYear,itemId); default:throw new RuntimeException(不正確的方案類型:+dataType);/.更新建議方案形狀public void setPrePlanS
14、tate /.更新綜合方案形狀public void setColPlanState. /.更新開工方案形狀public void setAftPlanState.public class PlanUtil public static PlanUtil create (int dataType)switch (dataType)case 1:return new PrePlanUtil();case 2:return new ColPlanUtil();case 3:return new AftPlanUtil();default:throw new RuntimeException(不正確的
15、方案類型:+dataType);public abstract void setPlanState (int planYear,int itemId,int dataType);public abstract void savePlan (int planYear,int itemId,int dataType);.重構方法引見:以多態取代條件表達式2/保管方案數據public void savePlan(int planYear,int itemId,int dataType)switch dataTypecase 1:savePrePlan(planYear,itemId);case 2:
16、saveColPlan(planYear,itemId);case 3:saveAftPlan(planYear,itemId); default: throw new RuntimeException(不正確的方案類型:+dataType);/.保管建議方案數據public void savePrePlan /.保管綜合方案數據public void saveColPlan/.保管開工方案數據public void saveAftPlanpublic class PrePlanUtil extends PlanUtil public void setPlanState (int planYe
17、ar,int itemId,int dataType). 更新建議方案形狀方法public void savePlan (int planYear,int itemId,int dataType)保管建議方案數據方法public class ColPlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新綜合方案形狀方法public void savePlan (int planYear,int itemId,int dataType)保管綜合方案數據方法.重構方法引
18、見:以多態取代條件表達式3/調用更新方案形狀的方法planUtil.setPlanState(year,itemId,dataType);/調用保管方案數據的方法planUtil.savePlanyear,itemId,dataType);public class AftPlanUtil extends PlanUtil public void setPlanState (int planYear,int itemId,int dataType). 更新開工方案形狀方法public void savePlan (int planYear,int itemId,int dataType)保管開工
19、方案數據方法/調用PlanUtil planUtil = PlanUtil .create(dataType);/調用更新方案形狀的方法planUtil.setPlanState(year,itemId,dataType);/調用保管方案數據的方法planUtil.savePlan (year,itemId,dataType);.重構方法引見:以多態取代條件表達式4多態最根本的益處就是:假設他需求根據對象的不同型別而采取不同的行為,多態使他不用編寫明顯的條件式。正由于有了多態,所以他會發現:針對type code(型別碼)而寫的switch語句,以及針對type string(型別稱號字符串)
20、而寫的if-then-else語句在面向對象程序中很少出現。多態可以給他帶來很多益處。假好像一組條件式在程序許多地點出現,那么運用多態的收益是最大的。運用條件式時,假設他想添加一種新型別,就必需杳找并更新一切條件式。但假設改用多態,只需建一個新的subclass并在其中提供適當的函數就行了。class用戶不需求了解這個subclass,這就大大降低了系統各部分之間的耦合程度,使系統晉級.更加容易。.重構方法引見:以委托取代承繼(1)/承繼處理方案public classBusPlanManagerServiceImpl public void setPlanState (int planYea
21、r,int itemId,int dataType). 更新建議方案形狀方法 public void savePlan (int planYear,int itemId,int dataType)保管建議方案數據方法public class PrePlanService extends BusPlanManagerServiceImpl .public class ColPlanService extends BusPlanManagerServiceImpl .public class AftPlanService extends BusPlanManagerServiceImpl ./委托
22、處理方案public classBusPlanManagerServiceImplpublic void setPlanState (int planYear,int itemId,int dataType)PlanUtil planUtil = PlanUtil .create(dataType);/調用更新方案形狀的方法planUtil.setPlanState(year,itemId,dataType);public void savePlan (int planYear,int itemId,int dataType)PlanUtil planUtil = PlanUtil .crea
23、te(dataType);/調用更新方案形狀的方法planUtil. savePlan (year,itemId,dataType); .重構方法引見:以委托取代承繼(2)承繼是一件很棒的事,但有時候它并不是他要的。經常他會遇到這樣的情況:一開場他承繼了一個class ,隨后發現superclass中的許多操作井不真正適用于subclass。這種情況下他所擁有的接口并末真正反映出class的功能。或者,他能夠發現他從superclass中承繼了一大堆subclas并不需求的數據,抑或者他能夠發現superclass中的某些protected函數對subclass并沒有什么意義。他可以選擇容忍,
24、并接受傳統說法:subclass可以只運用superclas、功能的一部分。但這樣做的結果是:代碼傳達的信息與他的意圖南轅北轍,這是一種混淆,他應該將它去除。假設以委托取代承繼,他可以更清楚地闡明:他只需求受托類的一部分功能。接口中的哪一部分應該被運用,哪一部分應該被忽略,完全由他主導控制。這樣做的本錢那么是需耍額外寫出委托函數,但這些函數都非常簡單,極少能夠出錯。.重構方法引見:引入參數對象(1)public List getYearPlanList (String operatorID, String planYear,String iSeason, String planType,Str
25、ing 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.setYeraPlanList(get
26、YearPlanList (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 String d
27、ataType;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;.重構方法引見:引入參數對象(2)public List getYearPlanList (PlanParamObj paramObj).p
28、ublic 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 PlanData();planData.setY
29、eraPlanList(getYearPlanList (paramObj);planData.setLastYeraPlanList(getLastYearPlanList (paramObj );.重構方法引見:引入參數對象(3)他常會看到特定的數組參數總是一同被傳送。能夠有好幾個函數都運用這一組參數,這些函數能夠隸屬同個class,也能夠隸屬不同的classes。這樣一組參數就是所謂的data Clump(數據泥團),我們可以運用一個對象包裝一切這些數據,再以該對象取代它們。哪伯只是為了把這些數據組織在一同,這樣做也是值得的。本項重構的價值在于縮短了參數列的長度,而他知道,過長的參數列總
30、是難以了解的。此外,新對象所定義的訪問函數還可以使代碼更具一致性,這又進一步降低了代碼的了解難度和修正難度。本項重構還可以帶給他更多益處。當他把這些參數組織到起之后,往往很快可以發現一些可被移至新建class的行為。通常,本來運用那些參數的函數對那些參數會有一些共通措施,假設將這些共通行為移到新對象中,他可以減少很多反復代碼.重構方法引見:函數遷移(1)public class RepUtilFunc private List initFundList().this.copyFundView(fView,planView); /匯總投資方案數據private void copyFundView
31、 (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 private List initFundList().fView.copyFundView(planView);
32、 /匯總投資方案數據.重構方法引見:函數遷移(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;getset方法public void copyFundView (PlanView planView)this.setFund(this.getFund
33、()+planView.getFund();this.setUpprefund(this.getUpprefund()+planView.getUpprefund();this.setDownprefund(this.getDownprefund()+planView.getDownprefund();.重構方法引見:函數遷移(3)函數遷移是重構實際的支柱。假設一個class有太多行為,或假設一個class與另一個class有太多協作而構成高度耦合,我就會遷移函數。經過這種手段,我可以使系統中的classes更簡單,這些classes最終也將更干凈利落地實現系統交付的義務。經常我會閱讀clas
34、s的一切函數,從中尋覓這樣的函數,運用另一個對象的次數比運用本人所駐對象的次數還多,就會進展函數遷移。.重構方法引見:將過程化設計轉換為面向對象設計有時間的話用一個實踐例子進展展現。.四、測試驅動開發方法簡介測試驅動開發Test Driven Development,英文縮寫TDD是極限編程的一個重要組成部分,它的根本思想就是在開發功能代碼之前,先編寫代碼的單元測試用例。也就是說在明確要開發某個功能后,首先思索如何對這個功能進展測試,并完成測試用例的編寫,然后編寫相關的代碼滿足這些測試用例。循環進展添加其他功能,直到完成全部功能的開發。代碼整潔可用(clean code that works)
35、 是測試驅動開發所追求的目的。.測試驅動開發優點(1)需求向來就是軟件開發過程中覺得最不好明確描畫、易變的東西。這里說的需求不只是指用戶的需求,還包括對代碼的運用需求。很多開發人員最害怕的就是后期還要修正某個類或者函數的接口進展修正或者擴展,為什么會發生這樣的事情就是由于這部分代碼的運用需求沒有很好的描畫。測試驅動開發就是經過編寫測試用例,先思索代碼的運用需求包括功能、過程、接口等,而且這個描畫是無二義的,可執行驗證的。 經過編寫這部分代碼的測試用例,對其功能的分解、運用過程、接口都進展了設計。而且這種從運用角度對代碼的設計通常更符合后期開發的需求。可測試的要求,對代碼的內聚性的提高和復用都非
36、常有益。因此測試驅動開發也是一種代碼設計的過程。 開發人員通常對編寫文檔非常膩煩,但要運用、了解他人的代碼時通常又希望能有文檔進展指點。而測試驅動開發過程中產生的測試用例代碼就是對代碼的最好的解釋。 .測試驅動開發優點(2)高興任務的根底就是對本人有自信心,對本人的任務成果有自信心。當前很多開發人員卻經常在擔憂:“代碼能否正確?“辛勞編寫的代碼還有沒有嚴重bug?“修正的新代碼對其他部分有沒有影響?。這種擔憂甚至導致某些代碼應該修正卻不敢修正的地步。測試驅動開發提供的測試集就可以作為他自信心的來源。 當然測試驅動開發最重要的功能還在于保證代碼的正確性,可以迅速發現、定位bug。而迅速發現、定位
37、bug是很多開發人員的夢想。針對關鍵代碼的測試集,以及不斷完善的測試用例,為迅速發現、定位bug提供了條件。 我的一段功能非常復雜的代碼運用TDD開發完成,真實環境運用中只發現幾個bug,而且很快被定位處理。您在運用后,也一定會為那種自信的開發過程,功能不斷添加、完善的覺得,迅速發現、定位bug的才干所感染,喜歡這個技術的。 .測試驅動開發根本過程明確當前要完成的功能。可以記錄成一個TODO列表。快速完成針對此功能的測試用例編寫。測試代碼編譯不經過。編寫對應的功能代碼。測試經過。對代碼進展重構,并保證測試經過。循環完成一切功能的開發 .測試驅動開發案例(1) 需求:實現Fibonacci數列F
38、ibonacci數列簡介:Fibonacci數列從第0項開場依次為0,1,1,2,3,5,8的數列,它存在如下特點:第0,1個數為0,1。從第2個數開場,該數是前面兩個數之和。 .測試驅動開發案例(2) 先編寫測試代碼 : import junit.framework.TestCase; public class FibonacciTest extends TestCasepublic void testFibonacci() FibUtil fb = new FibUtil(); 編寫完測試代碼之后在Eclipse中運轉該測試類,發現Junit運轉出錯(顯示了一條紅色杠) 這是在預料之中,由
39、于我們還沒有編寫FibUtil類。.測試驅動開發案例(3) 為了使測試經過,那么下面開場編寫FibUtil類public class FibUtil 然后再次運轉測試類。這時會發現測試勝利。 .測試驅動開發案例(4) 下面添加測試用例,開場測試Fibonacci數列的實現函數fib:public void testFibonacci() FibUtil fb = new FibUtil(); assertEquals(0,fb.fib(0); 由于出現編譯錯誤,所以需求在FibUtil類中添加fib方法如下:public int fib ( int i) return 0 ; 運轉測試用例,經過! .測試驅動開發案例(5) 繼續添加測試用例,判別1的情況:public void testFibonacci() FibUtil fb = new FibUtil(); assertEqu
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 水庫進口段施工方案模板
- 礦產資源開發與區域經濟發展-石墨滑石考核試卷
- 木結構防火施工方案
- 糧食批發商市場規范化管理與監管策略研究考核試卷
- 解答證券從業資格證考試疑難試題及答案
- 2023年中國鐵路上海局集團有限公司招聘高等職業院校畢業生3163人(二)筆試參考題庫附帶答案詳解
- 2024項目管理考試復習要點試題及答案
- 硫酸銅在金屬腐蝕中的應用考核試卷
- 2023年中國能建陜西院智能配網公司招聘變電電氣設計崗位工作人員筆試參考題庫附帶答案詳解
- 2023年中國聯合網絡通信有限公司會昌分公司公開招聘工作人員筆試參考題庫附帶答案詳解
- 第十五講新時代與中華民族共同體建設2012- -中華民族共同體概論專家大講堂課件
- 廣東省深圳市名校聯考2023-2024學年高一下學期數學期中考試試題(含答案)
- 中國革命戰爭的戰略問題(全文)
- MSOP(測量標準作業規范)測量SOP
- 包裝廠質量管理體系
- 初中花城版八年級下冊音樂4.狂歡之歌(15張)ppt課件
- 常用標準波導和法蘭尺寸
- 盤扣式腳手架高支模專項施工方案(共26頁)
- 不合格品控制流程圖
- 電纜敷設及接線施工方案(完整版)
- 紅領巾廣播稿:書香伴我成長之好書推薦
評論
0/150
提交評論