結對項目-小學生四則運算系統網頁版項目報告
結對作業搭檔:童宇欣
本篇博客結構一覽:
1).前言(包括倉庫地址等項目信息)
2).開始前PSP展示
3).結對編程對接口的設計
4).計算模塊接口的設計與實現過程
5).計算模塊接口部分的性能改進
6).計算模塊部分單元測試展示
7).計算模塊部分異常處理說明
8).界面模塊的詳細設計過程
9).界面模塊與計算模塊的對接
10).結對過程的描述
11).結對編程的優缺點
12).完成後實際的PSP
13).項目總結與改進
1)前言
本次結對項目,我們制作的是網頁版的四則運算系統。在結對的過程中,我(王文雨)負責前端,童宇欣負責後端。一起進行了兩部分功能的對接與融合
以下是我們的一些項目信息:
倉庫地址(王文雨的倉庫):https://coding.net/u/theMostCute/p/sizeyunsuanxitong/git/tree/master/?public=true
倉庫地址(童宇欣的倉庫):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下將其編譯,即可輸入數據進行測試運行。
2).開始前PSP展示
PSP
PSP2.1 |
任務內容 |
計劃共完成需要的時間(min) |
Planning |
計劃 |
20 |
Estimate |
估計這個任務需要多少時間,並規劃大致工作步驟 |
10 |
Development |
開發 |
1000 |
Analysis |
需求分析 (包括學習新技術) |
20 |
Design Spec |
生成設計文檔 |
20 |
Design Review |
設計復審 (和同事審核設計文檔) |
10 |
Coding Standard |
代碼規範 (為目前的開發制定合適的規範) |
1 |
Design |
具體設計 |
20 |
Coding |
具體編碼 |
500 |
Code Review |
代碼復審 |
20 |
Test |
測試(自我測試,修改代碼,提交修改) |
15 |
Reporting |
報告 |
20 |
Test Report |
測試報告 |
10 |
Size Measurement |
計算工作量 |
10 |
3).結對編程對接口的設計
在《構建之法》書中沒有找到有關信息,希望老師在設計要求的時候,可以告訴我們頁數。我在網上查閱了資料。
Information Hiding信息隱藏:信息隱藏指在設計和確定模塊時,使得一個模塊內包含的特定信息(過程或數據),對於不需要這些信息的其他模塊來說,是不可訪問的。
Interface Design接口設計:是傳統的後勤保障的一種要素也是一種後勤功能。
Loose Coupling松耦合:系統通常是基於消息的系統,此時客戶端和遠程服務並不知道對方是如何實現的。客戶端和服務之間的通訊由消息的架構支配。只要消息符合協商的架構,則客戶端或服務的實現就可以根據需要進行更改,而不必擔心會破壞對方。
本次作業采用的是網頁制作,整體采用MVC模型MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件裏面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。本次作業進行了模塊化編程,運算模塊和界面模塊相對較獨立,盡量做到了低耦合度。讓判斷正誤和計時以及條件受限放到前端制作,減少服務器的負擔。
4).計算模塊接口的設計與實現過程
我負責的有
①計算結果正誤判斷:
用js方法通過回答數組對答案數組的一一對應。
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++;
}
}
②智能出題的條件判斷,通過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;}
}
});
5).計算模塊接口部分的性能改進(這部分展示雨欣的成果)
1.性能分析改進
在運算模塊的性能分析過程中,大約花費了2小時,首先經過性能分析知道了我有些資源在使用結束後是沒有回收的,經過排查後,我發現了是在寫入文件後沒有關閉輸出流,導致了資源沒有完全回收。發現這一問題後,我針對它進行了改進,關閉了輸出流。使項目的性能得到了提高。同時經過性能分析,我發現我整個程序消耗最大函數是出題過程中的MakeQuestion3,即出題過程中不僅要出題,還要判斷題目是否符合要求,要調用調度場算法運算答案。因為這裏要滿足出題的時候必須在規定數字範圍內,及整除等條件,不符合要求的算式都要重新出題。發現這一問題後,我也對我的程序進行了改進,將是否能整除這些判斷在出兩個數字的簡單式子的時候直接進行了保證,使這裏只需要判斷每一步的運算結果是否在規定範圍內,使整個程序的性能得到了提高。
2.性能分析截圖
項目總體分析圖,從內存,多線程,CPU等方面分析了計算模塊的性能,截圖如下:
性能分析過程截圖:
首次按F4,出現以下截圖。可見有些資源沒有回收,經排查,我發現是我沒有關閉寫入文件的輸出流。解決過這個問題後,我再一次進行了性能分析。
經過以上的分析,讓我了解了性能分析的過程,也知道了性能分析的重要性。
6)計算模塊部分單元測試展示
(1)分別對計算模塊的Command.java和MakeQuestion.java進行了測試。寫了如下兩個單元測試類。
(2)以下是測試類的部分代碼截圖:
(3)構造測試數據思路
a.對於Command的測試,主要應保證參數的各種輸入情況都有涉及。所以我就分別構造了:參數輸入正確時的參數args數組;不包含必須輸入的參數,並且-o參數後沒有輸入應有數字的args1數組;-n參數後不包含應有的數字的args2數組;及字母參數後數字範圍有錯的args3,args4,args5,args6。經過以上設計,最終Command類的測試覆蓋率達90%以上。
b.對於MakeQuestion方法的測試,為保證測試覆蓋率,應保證各種類型的參數都輸入執行。所以這裏就構造了有乘除的,有括號的;沒有乘除的,沒有括號的;及不同運算符個數限制;不同數量;不同範圍限制這些情況。經過以上設計,最終MakeQuestion類的測試覆蓋率達90%以上。
(4)測試覆蓋率截圖展示
以下分別為兩個類測試覆蓋率的截圖展示以及部分代碼執行情況展示:
由圖可知,此次單元測試的覆蓋率還是相對較高的,執行通過的綠色占大部分,但仍有一些呈現黃色和紅色。也會繼續改進,爭取再次提高測試覆蓋率。
7)計算模塊部分異常處理說明
(1)沒有輸入必須的參數-m,-n
①通過if判斷對這種異常進行了處理。設計了兩個參數ifm和ifn判斷是否有-m,-n的輸入。
②單元測試樣例
③錯誤對應場景:例如命令行沒有輸入-n或-m。發生錯誤時,會提示用戶輸入的參數中必須包含題目數量/對題目數值上下界的設定。請重新輸入。
(2)輸入的參數超出指定範圍
①對於這種情況我設計了參數ifrun對能獲取到數字但是數字超出範圍的情況進行了判斷,出現異常時ifrun值為false。
②單元測試樣例
③錯誤對應場景:例如命令行輸入-n 10 –m -1 3。發生錯誤時,會提示用戶各個參數應有的界限,請用戶重新輸入。
(3)輸入的字母後沒有緊跟著對應數量的或對應形式的參數。
①對於這種情況用了try-catch語句判斷處理異常。輸入錯誤就會執行catch語句中內容,給出合理提示。
②單元測試樣例
③錯誤對應場景:例如-n –m 1 100的輸入。發生錯誤時,會提示用戶正確的輸入形式,請用戶重新輸入。
(4)出題後,寫入文件時出錯
對於這種情況用了try-catch語句判斷處理異常。輸入錯誤就會執行catch語句中內容,給出文件出錯提示。
8)界面模塊的詳細設計過程
整體思路:
①出題部分
功能如圖所示通過<form>表單進行功能實現向後臺傳輸數據
如果輸入的東西不符合要求,js會進行判斷
②文件上傳(題目導入)
功能如圖,文件提交由後臺代碼實現
③功能轉換
這三個功能在同一個頁面上,通過js改變css樣式進行改變。
$("#mia").click(function(){
$("#xinxi").css("display","block");
$("#miao").css("display","none");
});
$("#chu").click(function(){
$("#xinxi").css("display","none");
$("#miao").css("display","block");
});
$("#otou").click(function(){
$("#mengban").css("display","block");
});
$("#cha").click(function(e){
$("#chamian").css("display","block");
e.stopPropagation();
})
$("#chamian").click(function(e){
$("#chamian").css("display","block");
e.stopPropagation();
})
$(document).click(function(e){
$("#chamian").css("display","none");
});
④成績匯總
有兩個匯總,一個是全部成績,一個是最佳成績。點擊這兩個按鈕都會跳轉到同一個jsp頁面。而內容顯示的不同由後臺代碼實現
全部成績
嗷,前面截圖漏了學號
各用戶的最佳成績
⑤題目頁
沒有提交之前,包括計時器(js實現)和題目顯示,答案寫在<input>中通過js進行與答案的判斷
提交後出現答題情況的彈窗js判斷對錯,統計總題目數,答對題數,答錯題數,和總時間,將數據通過隱藏的<form>傳到後臺
答題情況的彈窗是可以拉動的,可以讓學生查看自己哪裏答錯了,可以再做但是不可以再次提交。拉動由js實現
//面板拖動
var drag=document.getElementById(‘drag‘);
drag.onmousedown=function(){
startMove();
}
var oCha=document.getElementById(‘QQcha‘);
oCha.onclick=function(){
var oBody=document.getElementById(‘mainbody‘);
var oCha=document.getElementById(‘QQcha‘);
oBody.style.display="none";
}
function startMove(event){
event=event || window.event;
var oBody=document.getElementById(‘mainbody‘);
var disX=event.clientX-oBody.offsetLeft;
var disY=event.clientY-oBody.offsetTop;
document.onmousemove=function(event){
event=event ||window.event;
okMove(event,disX,disY);
event.preventDefault();
}
document.onmouseup=function(){
document.onmousemove=null;
document.onmouseup=null;
}
}
function okMove(e,posX,posY){
var oBody=document.getElementById(‘mainbody‘);
var l=e.clientX-posX;
var t=e.clientY-posY;
var winW=document.documentElement.clientWidth || document.body.clientWidth;
var winH=document.documentElement.clientHeight || document.body.clientHeight;
var maxW=winW-oBody.offsetWidth-10;
var maxH=winH-oBody.offsetHeight;
if(l<0){
l=0;
}else if(l>maxW){
l=maxW;
}
if(t<0){
t=10;
}else if(t>maxH){
t=maxH;
}
oBody.style.left=l+‘px‘;
oBody.style.top=t+‘px‘;
}
9)界面模塊與計算模塊的對接。
作為前端,我只說我負責的部分:
①計時
// setInterval計時器
var theTime=document.getElementById(‘theTime‘);
var n=0;
var m=0;
var f=0;
var ff=0;
var timert=null;
function timeCount(){
clearInterval(timert);
timert=setInterval(
function(){
n=n+1;
f=n/60;
ff=parseInt(f)
m=n%60;
theTime.innerHTML=ff+" 分 "+m+" 秒";
},1000);
}
timeCount();
②判斷正誤
//判斷回答是否正確
var tiJiao=document.getElementById(‘tiJiao‘);
var oBody=document.getElementById(‘mainbody‘);
var huida=document.getElementsByClassName(‘huida‘);
var daan=document.getElementsByClassName(‘e‘);
var anwser=document.getElementsByClassName(‘anwser‘);
var yesno=document.getElementsByClassName(‘yesno‘);
var emm=document.getElementsByClassName(‘emm‘);
var allnum=document.getElementById(‘allnum‘);
var alltime=document.getElementById(‘alltime‘);
var allyes=document.getElementById(‘allyes‘);
// var yes=0;
// var no=0;
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);
③統計總題目數,答對題數,答錯題數,和總時間,將數據通過隱藏的<form>傳到後臺
HTML:
<form onsubmit="return PostData()" id="form1">
<input type="text" id="allnum" value="1" style="display: none;">
<input type="text" id="allyes" value="" style="display: none;">
<input type="text" id="alltime" value="" style="display: none;">
<input type="submit" class="quedinng" value="確定">
</form>
JS:
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;
}
}
10)描述結對的過程
我們的結對大約分為兩個階段,由於我們編寫的是網頁版,兩個人擅長的領域不相同
第一階段主要是一人負責前端,一人負責後端,這一過程我們相當於是分開各自編程的,所以這裏部分對駕駛員和領航員這種模式的切換和運用不夠明顯,每人負責自己的那部分代碼的編寫;
第二部分,進入合頁面和兩個模塊的對接過程,我們兩人一起合作,在這一階段也充分體驗了結對編程兩個人一起的高效之處。我們兩個人不斷切換駕駛員領航員角色,比較順利的完成了不同板塊的對接與項目的測試。同時也共同完成了整個項目的性能分析和單元測試的覆蓋率分析。
結對的時候,我們都要耐心傾聽,一起改bug,聽取對方的建議
11)結對編程的優點和缺點
結對編程的優點:鍛煉合作能力,溝通交流能力,分工配合能力
結對編程的缺點:兩人分開幹活,彼此進度不同,代碼功能不同。合在一起不容易
童宇欣的優點:學習的上進心,在最開始考慮項目功能時,她一直強調想做出附加功能
強大的代碼能力,在工作室她已經接手過幾個校級項目,對代碼熟悉
耐心,合作中配合,會有不同的bug一起改
童宇欣的缺點:真想不出來,和她配合很愉快
我的優點:積極配合,因為是前端,更多是輔助宇欣,她想要什麽功能都可以滿足
對前端語言的熟悉,在工作室也接手過項目
耐心,合作中配合,會有不同的bug一起改
我的缺點:對Java語言不熟悉
9)在你實現完程序之後,在附錄提供的PSP表格記錄下你在程序的各個模塊上實際花費的時間。(1‘)
PSP
PSP2.1 |
任務內容 |
實際完成需要的時間(min) |
Planning |
計劃 |
30 |
Estimate |
估計這個任務需要多少時間,並規劃大致工作步驟 |
10 |
Development |
開發 |
2700 |
Analysis |
需求分析 (包括學習新技術) |
40 |
Design Spec |
生成設計文檔 |
20 |
Design Review |
設計復審 (和同事審核設計文檔) |
20 |
Coding Standard |
代碼規範 (為目前的開發制定合適的規範) |
15 |
Design |
具體設計 |
60 |
Coding |
具體編碼 |
1800 |
Code Review |
代碼復審 |
45 |
Test |
測試(自我測試,修改代碼,提交修改) |
700 |
Reporting |
報告 |
840 |
Test Report |
測試報告 |
780 |
Size Measurement |
計算工作量 |
30 |
13)項目總結與改進
本次作業完成了所有基本功能,能夠實現規定要求的出題,和帶負數的計算,同時實現了允許多用戶做題,並能記錄所有用戶的全部成績和最好成績。
但仍然存在很多不足之處。比如另外一個附加功能(能夠支持多語言)沒能實現,還有由於對每一步運算結果的範圍限制,導致我們的程序出現括號的概率變小。接下來的時間我們一定會繼續改進我們的項目,爭取能呈現出更好的效果。
和宇欣合作非常棒!!她做事認真,熱情開朗,是一個非常棒的合作夥伴!!
結對項目-小學生四則運算系統網頁版項目報告