本篇博客結構一覽:
一.前言(包括倉庫地址等項目信息)
二.開始前PSP展示
三.結對編程對接口的設計
四.計算模塊接口的設計與實現過程
五.計算模塊接口部分的性能改進
六.計算模塊部分單元測試展示
七.計算模塊部分異常處理說明
八.界面模塊的詳細設計過程
九.界面模塊與計算模塊的對接
十.結對過程的描述
十一.結對編程的優缺點
十二.完成后實際的PSP
十三.項目總結與改進
一.前言
相比上次的個人項目,我覺得結對項目對於我來說一個更大的挑戰。生活中大概經常有這樣的情況,你以為一座山很高,自己根本無法看到山頂的風景,更無法翻越它,可是當以一步一步慢慢走,一點一點不放棄的緩緩前進時,你會發現,即使你走的很慢,你在不知不覺中已經走了很遠很遠,並且翻過了它。而當你翻越它時,你收獲的也不僅僅是山頂的風景。這次結對編程就給我這樣的感覺,收益頗多。當然,收獲的遠不止對代碼的熟悉程度和更多的知識經驗,還有結隊過程中兩人的合作與互幫互助精神,還有過程中對各種情況的應對和解決。
這次結對項目,我們制作的是網頁版的四則運算系統。所以在結對的過程中,我們先一人負責前端(王文雨同學),一人負責后端(我)。然后再一起進行了兩部分功能的對接與融合。以下是我們的一些項目信息:
代碼倉庫地址:https://git.coding.net/honey_xiaoxinxin/FreshCalculate.git
網頁版可測試的URL地址:http://47.93.197.5:8080/FirstCalculate/index.jsp
項目代碼說明:項目整體放在了Calculate文件夾下,里面包含命令行出題部分代碼NewCalculate,以及網頁版完整源代碼(web文件夾下)。命令行測試入口為src下Command.java;在src下將其編譯,即可輸入數據進行測試運行。
二.開始前PSP展示
PSP |
任務內容 |
計划共完成需要的時間(min) |
Planning |
計划 |
20 |
Estimate |
估計這個任務需要多少時間,並規划大致工作步驟 |
10 |
Development |
開發 |
1200 |
Analysis |
需求分析 (包括學習新技術) |
60 |
Design Spec |
生成設計文檔 |
20 |
Design Review |
設計復審 (和同事審核設計文檔) |
10 |
Coding Standard |
代碼規范 (為目前的開發制定合適的規范) |
10 |
Design |
具體設計 |
20 |
Coding |
具體編碼 |
720 |
Code Review |
代碼復審 |
30 |
Test |
測試(自我測試,修改代碼,提交修改) |
330 |
Reporting |
報告 |
480 |
Test Report |
測試報告(包括博客) |
420 |
Size Measurement |
計算工作量 |
30 |
Postmortem & Process Improvement Plan |
事后總結, 並提出過程改進計划 |
30 |
三.結對編程對接口的設計(
)1.首先我們明確了這些方法的具體含義:
(1)信息隱藏:信息隱藏指在設計和確定模塊時,使得一個模塊內包含的特定信息(過程或數據),對於不需要這些信息的其他模塊來說,是不可訪問的。
(2)接口設計:面向接口編程是軟件工程領域常用的設計手段
(3)松耦合度:基於面向接口編程,松耦合度是接口設計的目的,接口設計是松耦合度的實現手段
2.我們編程中的實現方法
(1)我們制作的是網頁版,整體采用了MVC模型,M是模型層,V是視圖層,C是業務邏輯層。在具體執行時,業務邏輯層並不需要知道方法內部是如何執行,實現的,只需要調用方法和實現接口就可以。從而實現了“將內部的算法實現封裝起來,對外部只提供調用的接口,使得程序之間各個模塊各司其職,互不影響”的效果。
(2)類的所有數據成員都是private,所有訪問都是通過訪問函數實現的。
private String studentId; private String perscore; private String avgtime; private String zttime; public String getStudentId() { return studentId; }
(3)進行了模塊化編程,運算模塊和界面模塊相對較獨立,盡量做到了低耦合度。
(4)人機交互邏輯集中到了一個單獨的類中,方便以后的修改。
四.計算模塊接口的設計與實現過程
1.類的組成
我的計算模塊由兩個類組成,一個是模塊的入口類Command,另一個類即是生成符合命令行參數要求的算式題目的類,MakeQuestion類。
2.各個類的基本功能及包含的函數
在上次作業的基礎上,按要求對這部分進行了相應的改進。
(1)Command類中包含了調用這部分的主函數,主要負責接收,判斷和處理命令行輸入的參數。實現了對是否輸入了必要的參數-m,-n的判斷;對每個參數范圍是否符合要求的控制;對相應字母后是否有相應個數的參數的判斷。並針對這些情況進行了合理的用戶提示和異常的處理。
(2)MakeQuestion類中函數總覽
a.實現命令行符合參數要求的最簡單兩個數四則運算題目的方法:MakeQuestion1(int min, int max, boolean multiply);
b.實現一個含規定運算符個數之內的四則運算題目的方法:MakeQuestion2(int min, int max, int p, boolean c, boolean b);
c.實現產生規定個數符合要求的四則運算式的方法:MakeQuestion3(int n, int min, int max, int o, boolean c, boolean b);
d.對每個式子運算的方法:solution(String question,int max,int min)。為了實現對負數的計算,在中綴轉后綴的過程中對相應的判斷做出了調整。
(3)MakeQuestion類中函數算法詳情
a.和上次基礎的四則運算一樣,MakeQuestion1是用來形成最簡單的兩個數的四則運算的函數,與上次不同的是,這次題目中數值的大小及是否包含乘除法不再是我們確定的,而是通過用戶輸入確定的,所以這里也就有了min(題目中出現數字的下界),max(題目中出現數字的上界),multiply(是否包含乘除法)這些參數。根據min,max的范圍使出現除法時,a始終是b的倍數,從而保證了可以整除。此方法也根據這些參數的要求產生組成題目的運算符和數字。
b. MakeQuestion2是對簡單運算的組合,形成符合運算符要求的一個四則混合運算式。根據最大最小值max,min;運算符最多個數p;是否包含乘除法c;是否包含括號b,這些參數,使用if-else語句對各種情況進行了分析和判斷,達到了生成符合要求運算式的效果。
c. solution函數是對每個運算式進行計算的函數,由於題目要求最大最小數值的約束范圍不僅要在題目中保證,還要在運算過程中給予保證,所以需要在出完題后對題目進行運算,判斷每一步的運算結果是否超出范圍。由於我采用了中綴表達式轉后綴表達式,再利用棧進行運算這種方法,所以實現以上要求,需要在從棧中彈出兩個數進行運算,再把運算結果壓入棧中時,判斷此時的運算結果是否在min和max之間。同時,改進了中綴轉后綴的過程。支持負數運算。當遍歷qustion這個String時,如果遇到“-”,需判斷其是減號還是負號,所以這里增加了判斷,當其前面是左括號或者前面也是一個符號時,就把它當作負號,和其后的數字一起入number數字棧。(較滿意的算法部分)
d. MakeQuestion3函數通過調用以上三個函數,生成規定數量要求的四則運算式。
3.函數間關系圖展示
藍色框代表類和方法,橘色框代表類和方法的作用
五.計算模塊接口部分的性能改進
1.性能分析改進
我在運算模塊的性能分析過程中,大約花費了2小時,首先經過性能分析知道了我有些資源在使用結束后是沒有回收的,經過排查后,我發現了是在寫入文件后沒有關閉輸出流,導致了資源沒有完全回收。發現這一問題后,我針對它進行了改進,關閉了輸出流。使項目的性能得到了提高。同時經過性能分析,我發現我整個程序消耗最大函數是出題過程中的MakeQuestion3,即出題過程中不僅要出題,還要判斷題目是否符合要求,要調用調度場算法運算答案。因為這里要滿足出題的時候必須在規定數字范圍內,及整除等條件,不符合要求的算式都要重新出題。發現這一問題后,我也對我的程序進行了改進,將是否能整除這些判斷在出兩個數字的簡單式子的時候直接進行了保證,使這里只需要判斷每一步的運算結果是否在規定范圍內,使整個程序的性能得到了提高。
2.性能分析截圖
項目總體分析圖,從內存,多線程,CPU等方面分析了計算模塊的性能,截圖如下:
性能分析過程截圖:
對CPU占用情況進行分析,JProfiler提供不同的方法來記錄訪問樹以優化性能和細節。以下是訪問樹 Call Tree視圖:
以下是熱點 Hot Spots視圖,顯示了消耗時間最多的方法的列表:
以下部分為內存視圖及分析過程:
首次按F4,出現以下截圖。可見有些資源沒有回收,經排查,我發現是我沒有關閉寫入文件的輸出流。解決過這個問題后,我再一次進行了性能分析。
再一次按F4后,如下圖顯示,資源全部被回收。證明沒有資源泄露。程序性能良好。
經過以上的分析,讓我了解了性能分析的過程,也知道了性能分析的重要性。
六.計算模塊部分單元測試展示
1.分別對計算模塊的Command.java和MakeQuestion.java進行了測試。寫了如下兩個單元測試類。
2.以下是測試類的部分代碼
測試Command.java類:
@Test public void testMain() { String[] args = {"-n","10","-m","1","100","-o","5","-c","-b"}; String[] args1 = {"-o"}; String[] args2 = {"-n","-m","1","100"}; String[] args3 = {"-n","100000","-m","100"}; String[] args4 = {"-m","1000","44","-n"}; String[] args5 = {"-o","100"}; String[] args6 = {"-m","-3","1"}; new Command(); Command.main(args); Command.main(args1); Command.main(args2); Command.main(args3); Command.main(args4); Command.main(args5); Command.main(args6); }
測試MakeQuestion.java類:
@Test public void testMakeQuestion3() { new MakeQuestion().MakeQuestion3(1000, 1, 100, 3, true, true); new MakeQuestion().MakeQuestion3(10, 1, 100, 3, false, false); new MakeQuestion().MakeQuestion3(10, 5, 100, 1, true, true); new MakeQuestion().MakeQuestion3(10, 1, 100, 1, false, false); }
測試結果:
3.構造測試數據思路
(1)對於Command的測試,主要應保證參數的各種輸入情況都有涉及。所以我就分別構造了:參數輸入正確時的參數args數組;不包含必須輸入的參數,並且-o參數后沒有輸入應有數字的args1數組;-n參數后不包含應有的數字的args2數組;及字母參數后數字范圍有錯的args3,args4,args5,args6。經過以上設計,最終Command類的測試覆蓋率達96.4%。
(2)對於MakeQuestion方法的測試,為保證測試覆蓋率,應保證各種類型的參數都輸入執行。所以這里就構造了有乘除的,有括號的;沒有乘除的,沒有括號的;及不同運算符個數限制;不同數量;不同范圍限制這些情況。經過以上設計,最終MakeQuestion類的測試覆蓋率達94.4%。
4.測試覆蓋率截圖展示
以下分別為兩個類測試覆蓋率的截圖展示以及部分代碼執行情況展示:
由圖可知,此次單元測試的覆蓋率還是相對較高的,執行通過的綠色占大部分,但仍有一些呈現黃色和紅色。我也會繼續改進,爭取再次提高測試覆蓋率。
七.計算模塊部分異常處理說明
1.沒有輸入必須的參數-m,-n
(1)我通過if判斷對這種異常進行了處理。設計了兩個參數ifm和ifn判斷是否有-m,-n的輸入。
if (ifn == false) { System.out.println("輸入的參數中必須包含題目數量,請重新輸入"); } else if (ifm == false) { System.out.println("輸入的參數中必須包含對題目數值上下界的設定,請重新輸入"); }
(2)單元測試樣例
String[] args1 = {"-o"};
new Command();
Command.main(args1);
(3)錯誤對應場景:例如命令行沒有輸入-n或-m。發生錯誤時,會提示用戶輸入的參數中必須包含題目數量/對題目數值上下界的設定。請重新輸入。
2.輸入的參數超出指定范圍
(1)對於這種情況我設計了參數ifrun對能獲取到數字但是數字超出范圍的情況進行了判斷,出現異常時ifrun值為false。
if (n <= 0 || n > 10000) { ifrun = false; System.out.println("請輸入1-10000的正整數作為題目個數的參數"); }
(2)單元測試樣例
String[] args6 = {"-m","-3","1"}; new Command(); Command.main(args6);
(3)錯誤對應場景:例如命令行輸入-n 10 –m -3 1。發生錯誤時,會提示用戶各個參數應有的界限,請用戶重新輸入。
3.輸入的字母后沒有緊跟着對應數量的或對應形式的參數
(1)對於這種情況我用了try-catch語句判斷處理異常。輸入錯誤就會執行catch語句中內容,給出合理提示。
try { n = Integer.parseInt(args[i + 1]); } catch (Exception e) { // TODO: handle exception System.out.println("題目個數為1-10000的正整數,請正確輸入"); } if(i < args.length-1){ i++; }else{ System.out.println("-n后必須要有一個正整數的輸入,請重新輸入"); } }
(2)單元測試樣例
String[] args7={"-n","b","-m"}; new Command(); Command.main(args7);
(3)錯誤對應場景:例如-n –m 1 100的輸入。發生錯誤時,會提示用戶正確的輸入形式,請用戶重新輸入。
4.出題后,寫入文件時出錯
對於這種情況我用了try-catch語句判斷處理異常。輸入錯誤就會執行catch語句中內容,給出文件出錯提示。
八.界面模塊的詳細設計過程
1.大致設計
這次四則運算系統我們做的是網頁版。所以界面模塊我們首先分為了三個板塊,用戶的出題模塊,用戶上傳題目進行做題的模塊,各個用戶做題記錄模塊。(附加功能,實現了多用戶做題,及記錄各用戶成績信息及最好成績)
(1)用戶出題板塊有對各個參數的輸入及判斷。
(2)用戶上傳題目的板塊包含文件上傳及用戶學號的輸入。用戶學號的輸入是為了實現對各個用戶成績的記錄,實現多用戶。做題頁面會呈現出全部題目,做完題后,會顯示正確錯誤情況及所用時間。
(3)做題記錄的模塊包含各用戶的所有做題記錄和各用戶最好成績統計兩個頁面。每個頁面都包含用戶的學號,做題正確率,做題總時間和提交時間這些信息。
2.設計思路圖
橘色方框代表所需頁面,其他框代表所需功能
3.實現過程
這些頁面具體是通過jsp頁面,css,js來實現的。
(1)用戶出題頁面,這部分主要是前台使用form表單把用戶輸入的信息傳到后台進行出題。與Command.java的命令行輸入不同,這部分對用戶輸入信息的各種情況的判斷,由前台的js判斷。
var oBiaodan=document.getElementById('oBiaodan'); $("#yiding").click(function(){ var nummMax=document.getElementById('nummMax'); var numm=document.getElementById('numm'); var minn=document.getElementById('minn'); var maxx=document.getElementById('maxx'); if(numm.value==""){ alert("請填寫題目數量!!!"); oBiaodan.onsubmit=function(){return false;} } if(numm.value<1||numm.value>10000){ alert("題目數量超出范圍,范圍為1-10000"); oBiaodan.onsubmit=function(){return false;} } if(minn.value==""||minn.value<1||minn.value>50){ alert("請填寫正確范圍!!!下線范圍1-100,上限范圍50到1000 "); oBiaodan.onsubmit=function(){return false;} } if(maxx.value==""||maxx.value<50||maxx.value>1000){ alert("請填寫正確范圍!!!下線范圍1-100,上限范圍50到1000 "); oBiaodan.onsubmit=function(){return false;} } });
(2)上傳題目頁面,同樣是form表單,后台完成文件上傳,並獲取到各用戶學號。這里文件上傳是以enctype="multipart/form-data"形式提交到后台的。
<form action="AllServlet?flag=MakeAnswer" enctype="multipart/form-data" method="post"> <div> <div class="eoo">學號:</div> <input type="text" class="hhh" name="xh"> </div> <div> <div class="eoo vp" onclick="myfile.click();">選擇文件</div> <input type="text" id="input1" class="mmm"> </div> <input type="file" id="myfile" name="file1" onchange="input1.value=this.value" style="display:none" > <input type="submit" id="otou" value="確定提交" class="eo"> </form>
(3)做題頁面,做題頁面時間的統計和答案對錯的判斷由前台完成。頁面可以呈現出所有題目。通過js對答案對錯進行了判斷。后台把所有題目和所有題目答案放在list里傳遞到前台,前台再通過js對答案對錯進行了判斷。答題完畢后的信息框可以拖動,便於用戶查看自己的答題情況。同時答題情況也將傳遞到后台,寫入一個文件,為之后的查看成績信息提供依據。
tiJiao.onclick=function(){ var yes=0; var no=0; //判斷回答是否正確 for(var i=0;i<huida.length;i++){ anwser[i].style.display="inline-block"; if(huida[i].value==daan[i].innerHTML){ yesno[i].innerHTML="√"; yesno[i].style.color="#1DF126"; yes++; }else{ yesno[i].innerHTML="×"; yesno[i].style.color="red"; no++; } } clearInterval(timert); oBody.style.display="block"; tiJiao.style.display="none"; allnum.value=daan.length; allyes.value=yes; emm[0].innerHTML=daan.length; emm[1].innerHTML=yes; emm[2].innerHTML=no; if(theTime.innerHTML=="計時區"){ emm[3].innerHTML="您沒有計時"; alltime.value=0; }else{ emm[3].innerHTML=theTime.innerHTML; alltime.value=theTime.innerHTML; } }
(4)統計題目頁面由后台判斷要顯示的是全部用戶的成績還是各個用戶的最好成績。通過參數k,對文件中的成績信息進行處理。k=0時,將文件信息全部輸出,k=1時,將文件信息進行排序,去重復處理,輸出各個用戶的最好成績。jsp頁面顯示各個用戶的做題記錄信息。
Servlet頁面:
int k=Integer.parseInt(request.getParameter("k")); if(k==0){ request.setAttribute("studentInf", studentInf); request.setAttribute("k", 0); request.getRequestDispatcher("/rank.jsp").forward(request, response); }else{ Collections.sort(studentInf, new Comparator<Student>(){ public int compare(Student o1, Student o2) { if(Double.valueOf(o1.getPerscore())<Double.valueOf(o2.getPerscore())){ return 1; } if(o1.getPerscore() == o2.getPerscore()){ return 0; } return -1; } }); for(int i = 0 ; i < studentInf.size() ; i++) { for(int j = i+1 ; j < studentInf.size() ; j++) { if(studentInf.get(j).getStudentId().equals(studentInf.get(i).getStudentId())){ studentInf.remove(j); j--; } } } for(int i = 0 ; i < studentInf.size() ; i++) { System.out.println(studentInf.get(i).getStudentId()); } request.setAttribute("studentInf1", studentInf); request.setAttribute("k", 1); request.getRequestDispatcher("/rank.jsp").forward(request, response);
jsp頁面:
<c:if test="${k=='0'}"> <c:set var="startIndex" value="${fn:length(studentInf)-1 }"></c:set> <c:forEach items="${studentInf}" var="t" varStatus="status"> <ul class="ti"> <li>${studentInf[startIndex - status.index].studentId}</li> <li>${studentInf[startIndex - status.index].perscore}%</li> <li>${studentInf[startIndex - status.index].avgtime}</li> <li style="width: 350px;"> ${studentInf[startIndex - status.index].zttime} </li> </ul> </c:forEach> </c:if> <c:if test="${k=='1'}"> <c:forEach items="${studentInf1}" var="t" > <ul class="ti"> <li>${t.studentId}</li> <li>${t.perscore}%</li> <li>${t.avgtime}</li> <li style="width: 350px;"> ${t.zttime} </li> </ul> </c:forEach> </c:if>
九.界面模塊與計算模塊的對接
1.整體對接方式
由於我們制作的是網頁版,所以對接主要體現在jsp頁面和servlet頁面的交互和信息傳遞,后台從jsp頁面獲取到需要的參數,在servlet頁面對獲取到的參數進行處理,並調用計算模塊的方法實現相應功能。
2.對接詳情
(1)出題。獲取到參數后,調用MakeQuestion3方法,進行出題,出完題后將題目寫入文件,並進行文件下載,使用戶把文件下載到本地。
String path = this.getServletContext().getRealPath("/"); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); String newName = "Makequestion"+sdf.format(new Date())+".txt"; String ResultName=path +"document/"+newName; PrintStream ps = new PrintStream(ResultName);// 創建一個打印輸出流 System.setOut(ps);// 把創建的打印輸出流賦給系統。即系統下次向 ps輸出 question.MakeQuestion3(n, min, max, o, c, b); //下載 SmartUpload smartUpload1 = new SmartUpload(); smartUpload1.initialize(getServletConfig(), request, response); smartUpload1.setContentDisposition(null);//取消默認打開方式 try { smartUpload1.downloadFile(ResultName); } catch (Exception e) { response.getWriter().print("<script language='javascript'>alert('出題文件下載失敗')</script>"); if(e.getMessage().indexOf("系統找不到指定的路徑。") != -1){ response.getWriter().print("<script language='javascript'>alert('出題文件下載失敗:文件不存在!')</script>"); } e.printStackTrace(); }
(2)做題頁面。用戶上傳題目后,將所有題目和計算所得的答案封裝到list集合中,傳遞到前台。
try{ InputStreamReader read = new InputStreamReader( new FileInputStream(file),encoding);//考慮到編碼格式 BufferedReader br = new BufferedReader(read);//構造一個BufferedReader類來讀取文件 String s = null; List<String> questionList=new ArrayList<String>(); List<String> answerList=new ArrayList<String>(); while((s = br.readLine())!=null){//使用readLine方法,一次讀一行 Answer answer=new Answer(); questionList.add(s); answerList.add(answer.solution(s)); } br.close(); request.setAttribute("questionList", questionList); request.setAttribute("answerList", answerList); request.getRequestDispatcher("/answer.jsp").forward(request, response); }catch(Exception e){ e.printStackTrace(); }
(3)各用戶做題記錄顯示頁面。本頁面的對接已經在第八點第四條給出。jsp頁面根據不同的k值,利用jstl表達式和el標簽顯示。進行<c:if>判斷,顯示出不同情況。
3.項目截圖展示
主頁面:
出題功能展示:
答題頁面展示:
用戶成績記錄頁面:
主頁面提供兩種選擇:
各用戶全部成績記錄頁面,按時間倒序,最新的在最上面:
各用戶最好成績統計頁面:
十.結對過程的描述
1.我們的結對大約分為兩個階段,由於我們編寫的是網頁版,兩個人擅長的領域不相同,所以第一階段主要是一人負責前端,一人負責后端,這一過程我們相當於是分開各自編程的,所以這里部分對駕駛員和領航員這種模式的切換和運用不夠明顯,每人負責自己的那部分代碼的編寫;第二部分,進入合頁面和兩個模塊的對接過程,我們兩人一起合作,在這一階段也充分體驗了結對編程兩個人一起的高效之處。我們兩個人不斷切換駕駛員領航員角色,比較順利的完成了不同板塊的對接與項目的測試。同時也共同完成了整個項目的性能分析和單元測試的覆蓋率分析。
2.結對照片展示
十一.結對編程的優缺點
1.結對編程的優缺點
優點:充分鍛煉了兩個人的合作,溝通交流能力。兩個人之間可以相互交流學習,從而互相取長補短。后期兩人共同對接模塊時,充分結合了兩人的優點,使對接較為順利的完成。
缺點:需要一段磨合時間,剛開始時效率不高。互相熟悉了解代碼風格之后漸入佳境。
2.結對個人優缺點
王文雨 優點:(1)代碼能力強,完成前端頁面速度快,質量高。做事不拖沓,有自己的規划和節奏
(2)細心。對細節的處理很好,使得用戶的體驗更好
(3)耐心。當出現問題時能夠和我一起分擔,一起修改
缺點:對java語言熟悉度不夠高
我的 優點:(1)編程思路清晰,能夠盡自己最大的能力實現自己能做到的最好
(2)耐心,不懼怕問題的出現,出現問題時不驕不躁,能靜下心來處理解決問題
(3)有上進心。在完成基本功能的前提下,根據時間估計,盡力完成了部分附加功能
缺點:一些部分對細節的處理不夠精致。以后應該更細膩一些
十二.完成后實際的PSP
PSP |
任務內容 |
計划時間(min) |
完成時間(min) |
Planning |
計划 |
20 |
30 |
Estimate |
估計這個任務需要多少時間,並規划大致工作步驟 |
10 |
10 |
Development |
開發 |
1200 |
2700 |
Analysis |
需求分析 |
60 |
40 |
Design Spec |
生成文檔 |
20 |
20 |
Design Review |
設計復審 |
10 |
20 |
Coding Standard |
代碼規范 |
10 |
15 |
Design |
具體設計 |
20 |
60 |
Coding |
具體編碼 |
720 |
1800 |
Code Review |
代碼復審 |
30 |
45 |
Test |
測試 |
330 |
700 |
Reporting |
報告 |
480 |
840 |
Test Report |
測試報告(包括寫博客) |
420 |
780 |
Size Measurement |
計算工作量 |
30 |
30 |
Postmortem & Process Improvement Plan |
事后總結, 並提出過程改進計划 |
30 |
30 |
通過以上PSP可知,我們將大量時間都投入到了此次結對編程中。單從代碼的開發就花費了45小時左右。這部分時間主要花費在代碼的開發和測試階段。此次對項目進行了單元測試和性能分析,這兩部分也讓我學到了很多。相比上次,我花費在寫博客上的時間也大量增加,一共用了13小時左右完成博客。寫博客的過程也並不是一氣呵成,而是寫寫停停,邊寫博客邊發現問題,邊寫博客邊思考,邊進一步改進了自己的項目。寫博客的過程中,也讓我對接口的設計有了更好的理解。
十三.項目總結與改進
這次結對編程我收獲很多。從項目角度看,我們完成了所有基本功能,能夠實現規定要求的出題,和帶負數的計算,同時實現了允許多用戶做題,並能記錄所有用戶的全部成績和最好成績。我對項目整體還是比較滿意的。但我們的項目仍然存在很多不足之處。比如另外一個附加功能(能夠支持多語言)沒能實現,還有由於對每一步運算結果的范圍限制,導致我們的程序出現括號的概率變小。接下來的時間我們一定會繼續改進我們的項目,爭取能呈現出更好的效果。從整體過程看,和文雨的合作十分愉快,她是一個很棒的結對伙伴,相信我們通過此次結對,對對方都有了更深的了解,促進了我們之間的友誼。