四则运算之GUI
四则运算之GUI
Coding克隆地址:https://git.coding.net/lvgx/pair_programming.git
|
目录:
一、前言
二、计划时间——PSP
三、接口设计
四、接口实现
五、性能分析
六、单元测试
七、异常处理
八、模块设计
九、模块对接
十、她
十一、结对编程思考
十二、实际时间——PSP
一、前言
首先我很感谢我的队友——吕国馨(www.cnblogs.com/lvgx/p/8733486.html),谢谢她清明假期仍在认真的敲代码,放弃自己休息的时间。第二我要感谢一位大佬,当我对GUI没丝毫头绪时,大佬的一篇博客给了我启发。
下面带上大佬博客:www.cnblogs.com/mafx/p/8536796.html
二、计划PSP
PSP |
任务内容 |
计划时间(min) |
Planning |
计划 |
30 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
30 |
Development |
开发 |
35*60+25 |
Analysis |
需求分析 |
60 |
Design Spec |
生成文档 |
0 |
Design Review |
设计复审 |
2*60 |
Coding Standard |
代码规范 |
10 |
Design |
具体设计 |
12*60 |
Coding |
具体编码 |
2*8*60 |
Code Review |
代码复审 |
4*60 |
Test |
测试 |
15 |
Reporting |
报告 |
5.5*60 |
Test Report |
测试报告 |
60 |
Size Measurement |
计算工作量 |
30 |
Postmortem& ProcessImprovement Plan |
事后总结, 并提出过程改进计划 |
4*60 |
尤其在编程GUI时候,花费了大量的时间。
三、接口设计
接口设计和低耦合是相辅相成的,接口化设计能大大降低程序的耦合度,低耦合一定离不开接口化设计。个人理解:接口化设计就是模块化设计,让不同方法放入到不同类中,并且使得各个类相互独立,减少关联性。低耦合和接口化设计差不多,使得各个模块之间减少依赖性,从而提高容错率。
我们的设计:我们已经尽我最大的努力,来进行模块化设计了,比如界面生成和算式生成是相互独立的,优先级判断、计算结果和算式生成又是相互独立的。但是我们的程序还有很多不足,比如界面设计,我们的五个界面都在同一个函数中实现的。原本我们尽力让他们在不同函数中,但是在继承时过程中,总是出现错误,最后我们还是放弃了。Java的继承我们还要再学一学。
四、接口实现
本次界面程序一共用到了9个类,14个函数,此9个类的调用关系如下图:
我们此界面程序的关键之处在于监听器的运用,大概用到了3个监听器,分别是复选框监听器、按钮监听器、文件监听器,本打算使用时间监听器,来计算当前时间和用时,但是发现可以直接调用java中自带的类,方便起见,就没有使用。代码的独特之处在于:界面套界面。即是亮点又是污点,亮点在于方法简单,实现方便,容易掌握(灵感来源于:www.cnblogs.com/mafx/p/8536796.html)。同时这也是一个不好之处,导致程序无法分解,耦合度太高,后期维护困难。
五、性能分析
说句实话,自我感觉能完成这个项目就很不错了,还要什么性能优化呀。。。但是我们已经尽力优化性能了,比如挺高代码利用率了。比如Puanduan类,和Yunsuan类,我们把它两生成两个类,其他类直接调用,减少代码长度。尽量减少内存开支,比如不定义数组,改用容器,因为数组的每个存储单元利用率不高。一般数组我们都往大的开,因为怕其不够用,但是这种方法会导致,大量内存单元没有被利用。题目要求最大生成10000到题目,如果你开10000大小的数组,当我们只生成10道题时,会有99990个内存没被利用。我们还尽量减少循环套循环,从而减少时间的消耗。
如何性能分析?百度上说是,进行溢出测试,将代码进行死循环,使得当CPU达到100%时,查看时间,时间越短,性能越好。
我们的分析方法是:通过JProfiler,进行性能分析。
总体分析图:包括CPU,内存,线程等等。
性能分析过程:
我们用三组数据分别对三个主要函数进行时间上的测试:
函数一:Algorithm函数,他用时最短,只用了11640微妙,且30%的原因在于文本的输入与输出,这是无法避免的,所以未进行优化。
函数二:Algorithm2函数,用时37789微妙,此函数30%的用时是在调用JiSuan函数上,JiSuan的用时主要是在出栈上,也是无法避免的。
函数三:Algorithm1函数用时最长,用时60390微妙,此函数用时主要是循环,此函数中有一个三重循环和大量二重循环,导致了时间过长。从图像也可以看出,橙色占的比例接近90%(橙色代表,阻碍与消耗,不是正常运行程序时间)。
性能优化:对于循环过多的Algorithm1函数,进行了优化,减少了几个循环,之后,我们又减少了大量循环,因为老师的需求降低(中间过程可以保证不再范围之内,这使得我们的程序,更加简洁)
可见,时间明显降低!
我们还对界面程序的性能进行分析,和优化,改进,文件也通过ps.close();进行关闭,按F4再一次查看,内存占用率明显减少,文件也都关闭了,但是仍有内存没释放,我们会继续改进的,性能分析结果如下。
六、单元测试
测试单元代码:
1 public class Test { 2 3 private static int n=10; 4 private static int m1=1; 5 private static int m2=50; 6 private static int o=4; 7 private static int c=0; 8 private static String s="11+(43-(35-(14+26)))"; 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 Command.main(null);// 主界面 13 System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成题目函数一 14 System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成题目函数二 15 System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成题目函数三 16 GUI.main(null); // 中文界面 17 GUI1.main(null); // 英文界面 18 //JiSuan.JiSuan(s); 19 } 20 21 }
我们对9个类进行了测试:采用结合或者独立的测试方法,来分别观察其代码覆盖率。(表中分别为:函数名、覆盖率、执行行数、错过行数、总行数)
第一组数据:
Command.java:这是一个语言选择窗口。
Algorithm.java:是一个可以生成加减乘除并且带有括号式子的类。
JiSuan.java:是一个可以计算式子,并且返回结果的类。
Panduan.java:是一个判断运算符优先级的类
测试结果如下:
第二组数据:
GUI.java和GUI1.java:分别是生成汉语出题窗口和英语出题窗口、汉语上传文件和英语上传文件的窗口。测试结果如下:
第三组数据:
YunSuan.java:一个进行简单加减乘除运算的类。测试结果如下:
第四组数据:
Algorithm1.java:是一个能生成乘除不带括号和不带乘除不带括号式子的类。测试结果如下:
Algorithm2.java:是一个生成不带乘除带括号式子的类。测试结果如下:
总体来说,代码覆盖率为:91.47%
七、异常处理
异常处理一:就是对输入出题数、运算符个数、范围等进行判断,判断其是否合法或者超出其范围。(只展示了,出题数的代码,其他雷同)
1 try { 2 n1 = Integer.parseInt(n.getText()); 3 if (n1 <= 0 || n1 > 10000) { 4 n.setText("n的范围不在[1,10000]内,请重新输入"); 5 return; 6 } 7 flag0 = 1; 8 } catch (Exception a) { 9 n.setText("n的格式不合法,请重新输入!"); 10 }
对应场景:
异常处理二、文件异常处理
1 try { 2 ps = new PrintStream("result.txt");// 生成文件 3 System.setOut(ps); 4 } catch (Exception e) { 5 System.out.println("文件生成错误");// 提示 6 }
对应场景:
点击出题时,如果文件生成错误,将不再生成。
异常处理三:文件过滤
1 FileNameExtensionFilter filter = new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx");
对应场景:
只能找到此格式的文件,其他格式文件,都被过滤了。
异常处理四:编码异常
1 InputStreamReader read = new InputStreamReader(new FileInputStream(f), "UTF-8");
对应场景:
只能处理UTF-8文件,要不会出现乱码。
异常处理五:用户不存在异常
如果你没有注册,即文件中没你的用户信息,会报用户不存在异常。
1 int flag = yanZheng(user.getText(), password.getText()); 2 if (flag == 1) { 3 GUI.main(null); 4 } else if (flag == 0) { 5 user.setText("密码错误!"); 6 return; 7 } else { 8 user.setText("账号不存在!"); 9 return; 10 }
对应场景:
异常处理六:用户和密码不匹配
即当用户存在时,但是密码输入和注册时的不同时,会报密码错误。代码如上:
对用场景:
异常处理七:用户已存在
即当注册过程中,如果该用户已存在,会报用户已存在错误。
1 int temp = yanZheng(user.getText(), password.getText()); 2 if(temp==0||temp==1) 3 { 4 user.setText("账号已存在,请重新注册!"); 5 return ; 6 }
对应场景:
异常处理八:注册信息不合法
注册时,对账号和密码有一定限制,当超出限制时,会报错。
1 try { 2 int user1 = Integer.parseInt(user.getText()); 3 if (user1 <= 0 || user1 >= 1000000) { 4 user.setText("用户名多余6位,或者不合法!"); 5 return; 6 } 7 } catch (Exception a) { 8 user.setText("账号有多余字符(只能是数字),请重新注册!"); 9 return; 10 } 11 try { 12 int password1 = Integer.parseInt(password.getText()); 13 } catch (Exception a) { 14 user.setText("密码有多余字符(只能是数字),请重新注册!"); 15 return; 16 }
为了方便起见,限制有点严格,必须是数字字符串,而且不能超过6位,其实不太合理,但是程序实现很简单。
对应场景:
八、模块设计
1、首先先设计一个语言选择功能,可以进行语言选择,通过按钮和调用函数来实现。
1 private JButton jcChina = new JButton("中文");//两个按钮,分别生成两种不同语言的界面 2 private JButton jcEnglish = new JButton("English");//可以用一个数组,存入多种语言,实现多语言转化 3 jcChina.addActionListener(new ActionListener() {//按钮监听器,为了实现中文界面 4 @Override 5 public void actionPerformed(ActionEvent e) { 6 GUI.main(null); 7 } 8 }); 9 jcEnglish.addActionListener(new ActionListener() {//按钮监听器,为了实现英文界面 10 @Override 11 public void actionPerformed(ActionEvent e) { 12 GUI1.main(null); 13 } 14 });
2、然后进行出题界面设计,此界面就是简单的GUI界面设计。
1 JPanel p1 = new JPanel(); 2 p1.setLayout(new GridLayout(4, 2, 5, 5)); 3 p1.add(new JLabel("出题数[1,10000]:")); 4 p1.add(n); 5 p1.add(new JLabel("数值左边界[1,100]:")); 6 p1.add(m1); 7 p1.add(new JLabel("数值右边界[50,1000]:")); 8 p1.add(m2); 9 p1.add(new JLabel("运算符数[1,10]:")); 10 p1.add(o);
3、然后进行上传文件的界面设计,此界面可以直接调用,java中已经有了。
1 JFileChooser chooser = new JFileChooser(); 2 chooser.setMultiSelectionEnabled(true); 3 // 过滤文件类型 4 FileNameExtensionFilter filter = new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx"); 5 chooser.setFileFilter(filter);
4、然后设计答题界面设计,此界面和出题界面类似,但是调用方法不同,在下面我会讲到。
1 JPanel panel2 = new JPanel(); 2 JTextField text = new JTextField(10); 3 panel2.setLayout(new GridLayout(3, 2, 5, 5)); 4 label.setText(addProblem()); 5 panel2.add(label); 6 panel2.add(new JLabel("/*为了美观*/")); 7 panel2.add(new JLabel("请输入答案:")); 8 panel2.add(text); 9 panel2.add(jbnext); 10 panel2.add(jbsubmit);
5、统计页面设计,内容设计,改用调用list实现。
1 JPanel panel = new JPanel(); 2 panel.add(new JLabel( 3 "做题总数: " + size + " " + " 正确数:" + rightAnswer + " 用时(S):" + (t2 - t1) / 1000)); 4 setLayout(new GridLayout(100, 1, 5, 5)); 5 for (int i = 0; i < size; i++) { 6 panel.add(new JLabel(list.get(i))); 7 } 8 resultFrame.add(panel);
九、模块对接
1、语言选择功能
相当于主函数,它通过按钮调用GUI和GUI1类
2、出题功能
它也是通过按钮调用做题界面和上传界面。
3、做题功能
通过下一题按钮进行判断和再次出题,通过按钮调用统计界面。
4、统计和计时
最终页面,不进行调用。代码如下:
5、上传文件及解析
代码如下:
调用提交和下一题按钮,代码和上面一样,但是会有一个上传成功的提示,代码如下:
6、用户注册和登录功能
没有注册的用户必须注册后才能进入程序进行答题和出题界面。
通过按钮对模块之间进行连接。
十、她
我们原本打算做前端,即Web的四则运算程序,而且她已经完成了,前端开发,如图:
但是由于我不会套页,即不能和后端连起来。所以最后放弃了Web项目,改做GUI。让她白做了一场,惭愧(就当给她个机会,让她练习练习前端知识了,嘻嘻)。
1、她:优点:技术强;聪明;乐观。缺点:做事不认真。
2、我:优点:认真,上进,创造性思维强。缺点:模块化思维欠缺。
十一、结对编程思考
结对编程有好处:
一、可以减轻两个人的压力。
二、相互学习、相互指正。
三、增强两个人的关系,增强合作能力、增强代码理解能力。
四、分工明确,增加办事效率。
结对编程有坏处:
一、如果交流不到位,那所做的项目将会功亏一篑。比如这次项目,因为我们前期交流没有到位,导致Web项目进行到一半,就进行不下去了。
二、两个人各做各的,导致后期两者的项目结合比较困难。
三、两人的分工不均匀,比如技术强的人可能做得就比较多,技术差可能就会抱大腿。
四、要花费大量时间进行交流和解释项目,毕竟代码不好看懂。
十二、实际PSP
PSP |
任务内容 |
完成时间(min) |
Planning |
计划 |
60 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
60 |
Development |
开发 |
45*60 |
Analysis |
需求分析 |
45 |
Design Spec |
生成文档 |
0 |
Design Review |
设计复审 |
3*60 |
Coding Standard |
代码规范 |
15 |
Design |
具体设计 |
12*60 |
Coding |
具体编码 |
3*8*60 |
Code Review |
代码复审 |
4*60 |
Test |
测试 |
60 |
Reporting |
报告 |
9*60 |
Test Report |
测试报告 |
0 |
Size Measurement |
计算工作量 |
60 |
Postmortem& ProcessImprovement Plan |
事后总结, 并提出过程改进计划 |
8*60 |
对于附加功能多语言,我们实现了两种语言的转换,其实可以通过数组实现多种语言转换,也可以通过我这种方法实现,即在生成一个界面。这种方法的好处在于简单,坏处在于代码比较多,还琐碎。
对于附加功能多用户,我们的这个GUI界面程序,可以多人下载,多人使用,实现多用户同时在线。用户必须登陆后才能进行上传题目、出题、做题等功能的使用,还可以统计用户人数。
参考网站:
www.cnblogs.com/mafx/p/8536796.html //基本的GUI语法
https://zhidao.baidu.com/question/184288577.html //上传文件语法
https://www.cnblogs.com/happyzm/p/6530384.html //覆盖率教程