結對項目 四則運算
一、項目
代碼倉庫地址:https://git.coding.net/immtroal/Sizeyunsuan.git
結對作業成員:洪澤芳 2016011988 張林 2016012089
二、PSP
PSP |
任務內容 |
計劃時間(min) |
完成時間(min) |
Planning |
計劃 |
30 |
30 |
Estimate |
估計這個任務需要多少時間,並規劃大致工作步驟 |
40 |
30 |
Development |
開發 |
40*60 |
50*60 |
Analysis |
需求分析 |
5 |
5 |
Design Spec |
生成文檔 |
0 |
0 |
Design Review |
設計復審 |
20 |
25 |
Coding Standard |
代碼規範 |
0 |
0 |
Design |
具體設計 |
15*60 |
18*60 |
Coding |
具體編碼 |
20*60 |
30*60 |
Code Review |
代碼復審 |
90 |
#*60 |
Test |
測試 |
60 |
60 |
Reporting |
報告 |
5.5*60 |
9*60 |
Test Report |
測試報告 |
60 |
0 |
Size Measurement |
計算工作量 |
30 |
60 |
Postmortem& ProcessImprovement Plan |
事後總結, 並提出過程改進計劃 |
4*60 |
8*60 |
我們把前期預估和後期PSP所用的實際時間制作在同一個表格中,更直觀的分析查看。
三、接口設計
Information Hiding:信息隱藏
對於面向對象的程序設計而言,信息隱藏是一種重要的軟件開發手段,它與對象的封裝與模塊化相關。信息隱藏是開發整體程序結構時使用的法則,
將每個程序的隱蔽或封裝在一個單一的設計模塊中,定義每一個模塊時盡可能少地顯露其內部的處理。把信息隱蔽用作模塊化系統的一個設計標準,
在後面項目調試過程中,編程人員的任務量能夠得以減輕,對代碼的可維護性也提高了。
在本次的項目中,考慮到多用戶使用此軟件,我們組將每個用戶的註冊和登錄和用戶做的題目的信息等用函數方法進行封裝,這些都是個人自己的信
息。用戶只需登錄管理自己的題目即可。
Interface Design:接口設計
在GUI設計接口的時候,我們的內部的的分析是界面和四則運算的主函數程序是分開設計的,最後只需要在類的傳參連接方面進行優化即可。所以前
期分析時這兩個模塊我們是先分工後整合。最後通過Text.class接受四則運算產生題目集。
Loose Coupling:降低耦合
接口設計和低耦合是相輔相成的,接口化設計能夠降低程序的耦合度,低耦合則一定離不開接口化設計。但這一塊我們在進行接口化的設計時候,因為
基礎緣故,我們所期望的只是能夠實現接口的功能,優化方面實在是很難做到,所以還有待學習加強。
四、接口實現
客戶端程序當中,個封裝的類中,關於記錄運算和客戶信息的是獨立的兩個類,只有text.class用到了運算的方法。在方法的使用上。如上圖,最先調用
GetExpression,最後客戶端傳遞生成多少道題的數目,之後依次調用Expression殘生表達式,oproExpression,proExpression對分數或幀數的格式化計算
或比較,構建二叉樹完成表達式規範和計算答案,期間有使用BinaryTree.java,最後用setExpression方法返回值。
五、計算模塊化的性能改進進
六、計算模塊的部分單元展示
在單元測試中,我們首先對兩個接口的基本功能進行了測試,在確保基本功能都可以正確實現之後,我們對Command類進行了單元測試。
以下是Command用於測試的代碼:
1 package main; 2 3 4 import java.io.File; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.util.Scanner; 9 10 import data_struct.BinaryTree; 11 import expression.DataOper; 12 import expression.Expression; 13 import expression.GetExpression; 14 import expression.Grade; 15 16 17 18 public class Command { 19 20 public static void main(String[] args) { 21 try { 22 DataOper dataOper = new DataOper(); 23 // System.out.println(dataOper.gcd(90, 15)); 24 GetExpression ge = new GetExpression(); 25 Expression e = new Expression(); 26 System.out.println("?????????????????????????"); 27 Scanner sc = new Scanner(System.in); 28 String number = sc.nextLine(); 29 int n = Integer.parseInt(number); 30 String question[] = new String[n]; 31 String answer[] = new String[n]; 32 String you_answer[] = new String[n]; 33 System.out.println("?????????????????????????Χ??"); 34 String range = sc.nextLine(); 35 int r = Integer.parseInt(range); 36 System.out.println("???????????£?"); 37 File file1 = new File("D:/Exercises.txt"); 38 if(!file1.exists()) { 39 file1.createNewFile(); 40 } 41 File file2 = new File("D:/Answers.txt"); 42 if(!file2.exists()) { 43 file2.createNewFile(); 44 } 45 File file3 = new File("D:/yourAnswers.txt"); 46 if(!file3.exists()) { 47 file3.createNewFile(); 48 } 49 File file4 = new File("D:/Grade.txt"); 50 if(!file4.exists()) { 51 file4.createNewFile(); 52 } 53 String qu_str = null; 54 String an_str = null; 55 FileOutputStream fos1 =new FileOutputStream(file1); 56 FileOutputStream fos2 =new FileOutputStream(file2); 57 FileOutputStream fos3 =new FileOutputStream(file3); 58 FileOutputStream fos4 =new FileOutputStream(file4); 59 for(int i = 1; i<=n;i++) { 60 e = ge.getExpression(r); 61 question[i-1]=e.getExpression(); 62 qu_str = i+". "+question[i-1]+"="+"\r\n"; 63 fos1.write(qu_str.getBytes()); 64 System.out.print(qu_str); 65 answer[i-1]=e.getE_value(); 66 an_str = i+". "+answer[i-1]+"\r\n"; 67 fos2.write(an_str.getBytes()); 68 } 69 String you_answer1=""; 70 for(int j=1;j<=n;j++) { 71 System.out.println("?????"+j+"??????"); 72 you_answer1 = sc.nextLine(); 73 you_answer[j-1]=you_answer1; 74 you_answer1=j+". "+you_answer1+"\r\n"; 75 fos3.write(you_answer1.getBytes()); 76 } 77 Grade g = dataOper.getGrade(question, answer, you_answer); 78 String corrent[] = g.getCorrent(); 79 String s = "Correct: "+dataOper.getCount(g.getCorrent())+"("; 80 int k = 0; 81 while(k<corrent.length&&corrent[k]!=null) { 82 if(k==0) 83 s+=corrent[k]; 84 else { 85 s= s+","+corrent[k]; 86 } 87 k++; 88 } 89 s=s+")\r\n"; 90 fos4.write(s.getBytes()); 91 String w[] = g.getWrong(); 92 s = "Wrong: "+dataOper.getCount(g.getWrong())+"("; 93 k = 0; 94 while(k<w.length&&w[k]!=null) { 95 if(k==0) 96 s+=w[k]; 97 else { 98 s= s+","+w[k]; 99 } 100 k++; 101 } 102 s=s+")\r\n"; 103 fos4.write(s.getBytes()); 104 s="Repeat:"+g.getRepeat_count()+"\r\n"; 105 fos4.write(s.getBytes()); 106 s="RepeatDetail:\n\r"; 107 fos4.write(s.getBytes()); 108 String repeat1[]=g.getRepeat1(); 109 String repeat2[]=g.getRepeat2(); 110 int u=0; 111 while(u<repeat1.length&&repeat1[u]!=null) { 112 s="("+(u+1)+")"+repeat1[u]+" Repeat "+repeat2[u]+"\r\n"; 113 fos4.write(s.getBytes()); 114 } 115 fos1.close(); 116 fos2.close(); 117 fos3.close(); 118 fos4.close(); 119 } catch (NumberFormatException e) { 120 // TODO Auto-generated catch block 121 e.printStackTrace(); 122 } catch (FileNotFoundException e) { 123 // TODO Auto-generated catch block 124 e.printStackTrace(); 125 } catch (IOException e) { 126 // TODO Auto-generated catch block 127 e.printStackTrace(); 128 }finally { 129 130 } 131 } 132
133 }
在進行代碼覆蓋率測試的時候應用程序顯示錯誤,百度和查問同學都沒找怎麽解決,下面是錯誤截圖:
七、異常處理
異常處理一:就是對輸入出題數、運算符個數、範圍等進行判斷,判斷其是否合法或者超出其範圍。
下面是對四則運算的方法的異常處理。
1 2 3 4 5 6 7 8 9 10 11 12 |
catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
|
1 |
<span style= "font-family: 楷體" >客戶端ui我們小組設置的數值是 0 ~ 100 ,計算數值不在此區間,程序將不能繼續運行。</span>
|
八、模塊設計
界面模塊前端設計采用java創建JUI界面完成,通過text.class完成前後端的交互。
1.增量計算
(1)創建新記錄,寫入用戶記錄文件及總記錄文件
public static void writefile(Record record){ add_record("record.txt", record); add_record(record.getUsername(), record); } public static void add_record(String filename,Record record){ File file =new File(filename); FileOutputStream outp; try { outp = new FileOutputStream(file,true); PrintStream out=new PrintStream(outp, true); out.println(record); out.close(); System.out.println("write object success!"); } catch (IOException e) { System.out.println("write object failed"); e.printStackTrace(); }
(2)用戶登陸後,讀取自己的記錄文件
1 2 3 4 5 6 7 8 9 10 |
public static ArrayList<Record> readfile(String username) throws FileNotFoundException{
ArrayList<Record> r = new ArrayList<>();
Scanner input= new Scanner( new File(username));
while (input.hasNext()){
Record record= new Record(input.next(),input.nextInt(),input.nextInt(),input.nextDouble());
r.add(record);
}
input.close();
return r;
}
|
(3)累加文件全部記錄的答對題數、總題數。即可獲得該用戶的答題總情況
1 2 |
long end_time=System.currentTimeMillis();
double cost_time=(end_time-begin_time)* 1.0 / 1000 ;
|
九、
用戶的登錄和註冊界面:
客戶登錄之後的界面,包括出題,語言和時間設定:
十、描述結對的過程
此次編程作業,對於我們而言真的難度很大,乃至最後關頭才堪堪把它做完。中間出現了很多的問題,有技術上的也有各類的bug。不過壓力和困境即是動力,我們兩個對於不會的難懂的知識細致分工,又共同學習逐個擊破。一個完整的項目使我們兩個人的努力才能夠完成的,感謝我的隊友,這是我第一次結對編程,收獲良多。
十一、結對編程思考
結對編程的好的一面:
分工明確,效率高
兩人互相檢閱,代碼質量高
互相鼓勵,指導,思路更明確
在氣餒沮喪的時候,我並不是一個人在奮鬥!
結對編程不好的一面:
交流占了絕大部分的時間,但是我覺得也挺好的。總之,很有意義。磨刀不誤砍柴工嘛。
結對項目 四則運算