小学四则运算结对项目
一、项目
代码仓库地址: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 }
在进行代码覆盖率测试的时候应用程序显示错误,百度和查问同学都没找怎么解决,下面是错误截图:
七、异常处理
异常处理一:就是对输入出题数、运算符个数、范围等进行判断,判断其是否合法或者超出其范围。
下面是对四则运算的方法的异常处理。
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 {
}
客户端ui我们小组设置的数值是0~100,计算数值不在此区间,程序将不能继续运行。
八、模块设计
界面模块前端设计采用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)用户登陆后,读取自己的记录文件
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)累加文件全部记录的答对题数、总题数。即可获得该用户的答题总情况
long end_time=System.currentTimeMillis();
double cost_time=(end_time-begin_time)*1.0/1000;
九、
用户的登录和注册界面:
客户登录之后的界面,包括出题,语言和时间设定:
十、描述结对的过程
这一次的编程练习,虽然我们有很明确地分工。在做的时候也是到处的寻找同学解答和帮忙,很庆幸的是,我的队友没有因为遇到问题了就不迎难前进
推脱掉不管。总的来说第一次的大项目的,感觉有同伴在机房和自己琢磨研究查资料解决问题,成就感还是蛮大的。如果这次作业让我一个人做的话,
可能我坚持不到最后,虽然完后过程有些没解决,但是也尽了自己最大的努力了,感谢自己。
十一、结对编程思考
结对编程的好的一面:
①就像我过程中所总结的,结对编程,当自己快被难倒很烦闷的时候,看见队友还在坚持,感觉自己不能比他差,要死磕到底。队友也挺求知好学的没有
迎难而退。
②分工比较明确各自有自己的针对的长处和处理问题的能力。
③铁哥们义气更浓了。
结对编程不好的一面:
①要花费大量时间进行交流和解释各自项目,一致代码和功能的衔接。
②还是有一点队友的性格比较的倔,碰到什么的总要依着他来,感觉有时自己做的东西被改了会很不自在。