结对项目——四则运算GUI项目
一、项目地址:https://git.coding.net/lvgx/wsz.git
PSP2.1 |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
15 |
15 |
Estimate |
估计这个任务需要多少时间 并规划大致工作步骤 |
15 |
15 |
Development |
开发 |
4225 |
5350 |
Analysis |
需求分析 (包括学习新技术) |
15 |
20 |
Design Spec |
生成设计文档 |
10 |
10 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
10 |
15 |
Design |
具体设计 |
25 |
45 |
Coding |
具体编码 |
4000 |
5000 |
Code Review |
代码复审 |
45 |
60 |
Test |
测试 (自我测试,修改代码,提交修改) |
120 |
200 |
Reporting |
报告 |
55 |
60 |
Test Report |
测试报告 |
15 |
15 |
Size Measurement |
计算工作量 |
10 |
5 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
30 |
40 |
三、说明在结对编程中是如何利用这些方法(Information Hiding, Interface Design, Loose Coupling)对接口进行设计的?
Information Hiding:对于面向对象的程序设计而言,信息隐藏是一种重要的软件开发手段,它与对象的封装(encapsulation)与模块化(modularity)密切相关。在我看来,信息隐藏使得一个类把复杂的、敏感的、一旦被外界捕获可能会引起不良后果的内容封装在自身内部,这个类以外的代码得不到此类信息(通过反射等手段可能对得到),以提高程序的安全性与健壮性。在本次作业中,对于这个部分我们进行了模块化设计,对函数进行了封装,只能调用方法,并且在GUI页面中我们将变量值设为私有的,只用使用它就可以。
Interface Design和Loose Coupling:这两个概念是相辅相成的,后者是前者的目的,前者是后者的实现手段。Loos Coupling的目标是最小化依赖。松耦合这个概念主要用来处理可伸缩性、灵活性和容错这些需求。松耦合要付出使系统更加复杂的代价。松耦合意味着更多的开发以及维护工作量。在本次作业中,由于我们的编程能力的问题我们并没有对这个部分进行设计。
四、计算模块接口的设计与实现过程
我们一共用了8个类,10多个函数,其中Main函数是负责接收参数判断参数是否合法(后以改为Command),Operation类是生成并计算不带括号的式子,Operation1是生成带括号并且带乘除的式子,Operation2是生成并计算带括号只带加减的式子,在GUI中用了两个监听器,是复选框监听器和按钮监听器,代码的特点是方法简单,实现起来很容易,但是缺点就是没有再细致地进行模块化,后期维护起来不太容易
五、计算模块接口部分的性能改
在性能分析这部分,原来我们因为项目的问题没有来得及做,后来在补充时我们花费了4个小时左右,在此我们还界面程序的性能进行分析,和优化,改进,尽量减少除法中随机数,以减少代码因随机数生成的无效循环,按F4再一次查看,内存占用率明显减少,但是仍有内存没释放,我们会继续改进的,性能分析结果如下。
六、计算模块部分单元测试展示
单元测试的代码如下
private static int n=10; private static int r1=1; private static int r2=50; private static int p=4; private static int z=0; private static String s="11+(43-(35-(14+26)))"; public static void main(String[] args) { // TODO Auto-generated method stub Main.main(null);// 主界面 System.out.println(Operation.Operation(n, r1, r2, p, z)); System.out.println(Operation.Operation(n, r1, r2, p, z)); System.out.println(Operation.Operation(n, r1, r2, p, z)); Gui.main(null); }
我们对五个类进行了测试,采用结合或者独立的测试方法,下面是代码覆盖率的展示;
1、Operation1生成带括号并且带乘除的式子:
2、GUi界面
3、Judge判断括号的优先级
4、Operationa2生成并计算带括号只带加减的式子
5、Choose简单的加减乘除
七、计算模块部分异常处理说明
1、判断输入的出题数、运算符个数、范围等是否合法或者超出其范围(展示了对数的范围的处理,代码结果如下)
try { r=Integer.parseInt(args[i+1]); r1=Integer.parseInt(args[i+2]); if(r<=0||r>100) { System.out.println("r不在范围[1,100]内"); return; } if(r1<50||r1>1000) { System.out.println("r1不在范围[50,1000]内"); return; } }catch(Exception e) { System.out.println("r的输入不合法,请重新输入"); } }
2、文件处理异常
try { PrintStream file=new PrintStream("../result.txt"); System.setOut(file); }catch(Exception e) { System.out.println("文件生成错误"); }
点击出题时,如果文件生成错误,将不再生成。
3、文件过滤
FileNameExtensionFilter filter=new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx");
在这里,我们只能找到文件类型相对应的文件,其余均被过滤,如图
八、界面模块的详细设计过程
1、出题GUI界面设计。
定义p1面板,添加r,r1,n,z组件,就是输入数字范围,出题数,运算符个数。
public static void main(String[] args) {
Gui frame=new Gui();
frame.pack();
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
frame.setVisible(true);
}
public Gui() {
JPanel p1=new JPanel(); p1.setLayout(new GridLayout(4,2,5,5)); p1.add(new JLabel("请输入数字左范围(1~100)")); p1.add(r); p1.add(new JLabel("请输入数字右范围(50~1000)")); p1.add(r1); p1.add(new JLabel("请输入出题个数(1~10000)")); p1.add(n); p1.add(new JLabel("请输入运算符个数(1~10)")); p1.add(z); p1.setBorder(new TitledBorder("四则运算出题系统")); JPanel p2=new JPanel(); p2.add(jbtArithmetic); jbtArithmetic.setMnemonic('V'); jbtArithmetic.setToolTipText("出题"); setLayout(new BorderLayout()); add(p1,BorderLayout.CENTER); add(p2,BorderLayout.SOUTH); jchkMulandDiv.setMnemonic('C'); jchkBracket.setMnemonic('B'); JPanel p3=new JPanel(); p3.setLayout(new GridLayout(3,1)); p3.add(jchkMulandDiv); p3.add(jchkBracket); add(p3,BorderLayout.WEST);
2、答题GUI界面设计
定义p2面板,添加labe,taxt,jbNextquestion,jbRefer组件,就是所出题目,输入答案,提交和下一题按钮
JFrame QuestionFrame=new JFrame();
QuestionFrame.setTitle("题目");
QuestionFrame.setSize(500,300);
QuestionFrame.setLocationRelativeTo(null);
QuestionFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
QuestionFrame.setVisible(true);
JPanel p4=new JPanel(); final JTextField text=new JTextField(10); p4.setLayout(new GridLayout(3,2,5,5)); label.setText(addProblem()); p4.add(label); p4.add(new JLabel("请回答")); p4.add(new JLabel("输入答案")); p4.add(text); p4.add(jbNextquestion); p4.add(jbRefer); QuestionFrame.add(p4);
3、最终页面设计
定义p5面板,最后出现答题所用时间,答题总数,答题是否正确等。
JPanel p5=new JPanel(); p5.add(new JLabel("做题总数: " + xd + " " + " 正确数:" + rightkey + " 用时(S):" + (time2 - t1) / 1000)); setLayout(new GridLayout(100,1,5,5)); for(int i=0;i<xd;i++) { p5.add(new JLabel(list.get(i))); } rFrame.add(p5)
九、界面模块与计算模块的对接
1、出题界面
它是通过按钮“出题”监听器来实现的,监听器是通过对不同按钮的点击事件进行监听,调用做题界面。
private class ButtonListener implements ActionListener{ public void actionPerformed(ActionEvent e) { try { n1=Integer.parseInt(n.getText()); if(n1<=0||n1>10000) { n.setText("n不在范围(1~10000)内,请重新输入"); return; } final long t1=Calendar.getInstance().getTimeInMillis(); JFrame QuestionFrame=new JFrame(); QuestionFrame.setTitle("题目"); QuestionFrame.setSize(500,300); QuestionFrame.setLocationRelativeTo(null); QuestionFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); QuestionFrame.setVisible(true); public void eventOnImport(JButton Upload) {//文件上传 JFileChooser select=new JFileChooser(); select.setMultiSelectionEnabled(true); FileNameExtensionFilter filter=new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx"); select.setFileFilter(filter); int backv=select.showOpenDialog(Upload); if(backv==JFileChooser.APPROVE_OPTION) { File[] opf=select.getSelectedFiles(); if(opf==null||opf.length==0) { return; }
2、做题界面
通过下一题按钮进行判断和再次出题,通过按钮调用统计界面。
long time2=Calendar.getInstance().getTimeInMillis(); JFrame rFrame=new JFrame(); rFrame.setSize(500,300); rFrame.setTitle("结果"); rFrame.setLocationRelativeTo(null); rFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); rFrame.setVisible(true); int xd=list.size(); JPanel p5=new JPanel(); p5.add(new JLabel("做题总数: " + xd + " " + " 正确数:" + rightkey + " 用时(S):" + (time2 - t1) / 1000));
3、最终界面
JPanel p5=new JPanel(); p5.add(new JLabel("做题总数: " + xd + " " + " 正确数:" + rightkey + " 用时(S):" + (time2 - t1) / 1000)); setLayout(new GridLayout(100,1,5,5));
4、上传文件界面,它是通过按钮“上传文件”监听器来实现的,先判断文件是否已经上传,然后如果没有则上传文件成功
try { for(File f:opf) { File ma=new File(lu); File[] na=ma.listFiles(); HashSet<String> she=new HashSet<String>(); for(File file:na) { she.add(file.getName());
十、描述结对的过程
结对作业成员:王晓哲(2016012052)、祁晨(2016012057)
我(王晓哲)与队友(祁晨)是同寝室室友,所以我们之间的组队对于在项目进行时的沟通交流十分有利,我们每天几乎都能够见到对方,因此在项目的问题上可以随时交流。并且对方如果遇到不会不懂的地方,我们也可以及时去一起处理、解决。由于我的队友缺少项目经验,并且基础编程能力较弱,因此她负责此次项目的设计、测试以及简单编写。而我将承担此次项目中的结构框架、所用的技术等等。
十一、说明结对编程的优点和缺点
通过看邹欣老师的《构建之法》第四章两人合作的内容,初步的了解了我们“为什么要结对编程?”。在结对编程模式下,一对程序员肩并肩、平等地、互补地进行开发工作。他们并排坐在一台电脑前,面对同一个显示器,使用同一个键盘、同一个鼠标一起工作。他们一起分析,一起设计,一起写测试用例,一起编码,一起做单元测试,一起集成测试,一起写文档,等等。(选自《构建之法》第四章)
但是经过这次结对项目之后,我才能亲身感受到两个人一起合作的苦乐。我在此次作业完成后,对于结对项目的优缺点有以下几点想法。
结对项目的优点:①在项目设计阶段,我们不在局限于一个人的想法,两个人共同思考、设计,使这个项目有了多个开始方向,一一选择,最终确定了一个我们看来“最好的”方案;②在项目开发阶段,一个人编程实在是过于枯燥,并且工作量实在太大。但是结对编程能够减少自身的工作量,两个人配合完成;③在编程过程中,两个人彼此协助,能够在对方遇到困难处时及时给予帮助,由此提高工作效率。
结对项目的缺点:①由于之前都是自己一人编程,因此大家都有自己的习惯与方式,所以在结对项目中会产生摩擦与冲突;②结对项目就等于是给自己增加了一个帮手,但同时对于较弱的那个人来说就会产生依赖心理,从而较强的那个人会感到更加的负担。
十二、指出结对的每一个人的优点和缺点在哪里 (要列出至少三个优点和一个缺点)
1、队友(祁晨)
优点:①对于安排的工作能够及时完成;②善于沟通,常和我交流自己的想法与问题;③对于我的问题与错误能够及时指出。
缺点: 缺少耐心,不够细心
2、自己(王晓哲)
优点:①有责任心,对于自己的工作总是完成的及时并且有质量;②对于自己不懂的问题愿意去查阅资料和询问老师同学;③积极思考,对于项目的每一步都有自己的想法。
缺点:缺乏项目经验,能力不足
十三、项目总结
我还是想总结一下我此次的项目,虽然这个没有做要求。这次的项目刚开始的时候可以说一点头绪都没有,然后我们去询问了夏江华同学,他给了我们很多思路,告诉我们具体该怎么去做,在改代码部分我也借鉴了夏江华同学的很多思路,包括刚开始一点都不懂GUI,也开始慢慢学习,参考了夏江华同学的很多代码,他也告诉我们应该怎样去做,再自己慢慢的敲出来,感觉挺不容易的,遇到了很多阻碍,还有就是上传文件的功能也没有实现,代码覆盖率,效能分析的问题等等,再就是自己的编程能力太弱了,希望自己以后可以继续加油,努力学习,最后真的特别感谢夏江华同学。在后来的改进中,我们实现了文件上传的功能,和效能分析等问题,对我们的代码做出了很大的改进。