结对作业

组员:吕国馨  夏江华

1.coding.net地址:https://git.coding.net/lvgx/pair_programming.git

2.12.PSP:

SP2.1

任务内容

计划共完成需要的时间(min)

实际完成需要的时间(min)

Planning

计划

30

60

·        Estimate

·   估计这个任务需要多少时间,并规划大致工作步骤

30

60

Development

开发

35*60+25分

45*60分

·        Analysis

·         需求分析 (包括学习新技术)

60

45

·        Design Spec

·         生成设计文档

0

0

·        Design Review

·         设计复审 (和同事审核设计文档)

2*60

3*60

·        Coding Standard

·         代码规范 (为目前的开发制定合适的规范)

10

15

·        Design

·         具体设计

12*60

12*60

·        Coding

·         具体编码

2*8*60

3*8*60

·        Code Review

·         代码复审

4*60

4*60

·        Test

·         测试(自我测试,修改代码,提交修改)

15

60

Reporting

报告

5.5*60

9*60

·         Test Report

·         测试报告

60

0

·         Size Measurement

·         计算工作量

30

60

·         Postmortem & Process Improvement Plan

·         事后总结, 并提出过程改进计划

4*60

8*60

3.看教科书和其它资料中关于Information Hiding, Interface Design, Loose Coupling的章节,说明你们在结对编程中是如何利用这些方法对接口进行设计的。

  Information Hiding:信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。

1972年,David Parnas 发表了一篇题为《论将系统分解为模块的准则》的论文首次让公众注意到信息隐藏这一概念。 信息隐藏式结构程序设计与面向对象设计的基础之一。在面向对象设计中,它又引出了封装和模块化的概念,并与抽象的概念紧密相关。 信息隐藏是软件的首要技术使命中格外重要的一种启发式方法,因为它强调的就是隐藏复杂度。

  信息隐藏在设计的所有层次上都有很大作用:从用具名常量代替字面常量,到创建数据类型,再到类的设计、子程序的设计以及子系统的设计等等。

  为什么要隐藏?

  1. 隐藏复杂度:这样你就不用再去应付它,除非你要特别关注的时候;
  2. 隐藏变化源:这样当变化发生时,其影响就能被限制在局部范围内。复杂度的根源包括复杂的数据类型、文件结构、布尔判断以及晦涩的算法等等。

  例如:把具体调用的数字信息隐藏起来,写入一个常量中,如果需要更改常量的值,只需要改动一处即可。

  资料链接:https://blog.csdn.net/gongchuangsu/article/details/53895916

  Interface Design,Loose Coupling松耦合的目标是最小化依赖。松耦合这个概念主要用来处理可伸缩性、灵活性和容错这些需求。

    这两个概念是相辅相成的,后者是前者的目的,前者是后者的实现手段。面向接口编程是软件工程领域常用的设计手段,这对于一个团队而言,是非常重要的,在做一个团队项目时,有人可能负责领域模型M(Model),有人负责前台V(View),有人负责业务逻辑C(Controller),在这种MVC的设计模式驱动下,我们首先想到的就是:定义一套公共的接口,方便各个模块之间的通讯。面向接口的程序设计思想是一种有效的手段。比如一个做业务逻辑的Team,他们并不清楚业务数据的CURD实现,但他们只要通过面向于数据组提供的一整套接口进行编程即可,同时,数据组的开发可以并行进行,这样,不需要等待一个模块的完成就可以预先“使用”这个模块,极大的提高了团队的效率

    资料链接:https://www.cnblogs.com/magiccode1023/archive/2012/10/23/2736257.html

4)计算模块接口的设计与实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?

  总共设计了七个类:Algorithm  Algorithm1 Algorithm2 GUI JiSuan Panduan Yusuan

  其中GUI是主函数,也负责显示GUI界面,Algorithm  Algorithm1 Algorithm2 JiSuan是同级的class,分别负责计算既有乘除又有括号或者既没有乘除也没有括号,只有乘除,只有括号,计算上传文件中的运算式。这几个功能

  

5) 计算模块接口部分的性能改进。记录在改进计算模块性能上所花费的时间,描述你改进的思路,并展示一张性能分析图,并展示你程序中消耗最大的函数。  

  说句实话,自我感觉能完成这个项目就很不错了,还要什么性能优化呀。。。但是我们已经尽力优化性能了,比如挺高代码利用率了。比如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再一次查看,内存占用率明显减少,文件也都关闭了,但是仍有内存没释放,我们会继续改进的,性能分析结果如下。

  

6)计算模块部分单元测试展示。展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中。只需要测试命令行部分,且该部分覆盖率到90%以上,否则单元测试部分视作无效。

 

测试单元代码:

  

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 stub12         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%

7)计算模块部分异常处理说明。在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。

  

  异常处理一:就是对输入出题数、运算符个数、范围等进行判断,判断其是否合法或者超出其范围。(只展示了,出题数的代码,其他雷同)

     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位,其实不太合理,但是程序实现很简单。

    对应场景:

    

    

    

8)界面模块的详细设计过程。在博客中详细介绍界面模块是如何设计的,并写一些必要的代码说明解释实现过程。

  1.生成主页面包含出题数,数值范围,运算符个数,是否带乘除豪及括号,上传题目等基本条件

  2.点击出题按钮,依次跳转到随机生成的题目

    1)点击下一题按钮,显示下一题的情况

    2)点击提交按钮,生成新的界面,显示答题情况及用时

  3.点击上传文件按钮,跳转到选择本地文件的界面

    2)点击确定,生成本地文件中的题目,以随机出题的格式显示

9)界面模块与计算模块的对接。详细地描述UI模块的设计与两个模块的对接,并在博客中截图实现的功能。

   界面模块与计算模块的对接是通过监听器来实现的,监听器是通过对不同按钮的点击事件进行监听,调用不同的函数方法。例如点击

出题按钮,触发监听器,调用出题函数,在新的页面内生成随机运算式。点击下一题按钮,触发监听器,调用方法进行运算并且跳转到下一题等等。

10)描述结对的过程,提供非摆拍的两人在讨论的结对照片

  1.对于之前的个人作业进行总结与分析:虽然大家都写了四则运算的个人作业,但不同的模块有不同的长出,所以要将两个人的代码进行一个综合,取长补短,尽可能实现最优的算法

  2.对于新增模块进行设计规划与任务分配。比如新增加的GUI界面,先要进行功能的设计,再进行模块的实现。有效率的设计规划大大提高了作业的完成效率

  3.对于模块的总和。再分工做各自的任务后,要对项目进行一个总和,实现结对项目的基本功能。

  4.对项目进行一些基本的测试,修改一些潜在的bug

  5.对项目的进一步完善,比如一开始并没有实现中英文切换的功能,经过大家的交流与探讨,决定使用数组来完整中英文的切换这一功能。并对之前一些功能出现的bug进行测试。

  6.再进行测试,完成项目的收尾工作。

11.说明结对编程的优点和缺点。同时指出结对的每一个人的优点和缺点在哪里 (要列出至少三个优点和一个缺点)。

  下面是一些结对编程的优点:

  1. 程序员互相帮助,互相教对方,可以得到能力上的互补。
  2. 可以让编程环境有效地贯彻Design。
  3. 增强代码和产品质量,并有效的减少BUG。
  4. 降低学习成本。一边编程,一边共享知识和经验,有效地在实践中进行学习。
  5. 在编程中,相互讨论,可能更快更有效地解决问题。

  当然,结队编程也会有一些不好的地方:

  1. 对于有不同习惯的编程人员,可以在起工作会产生麻烦,甚至矛盾。
  2. 有时候,程序员们会对一个问题各执己见(代码风格可能会是引发技术人员口水战的地方),争吵不休,反而产生重大内耗。
  3. 两个人在一起工作可能会出现工作精力不能集中的情况。程序员可能会交谈一些与工作无关的事情,反而分散注意力,导致效率比单人更为低下。
  4. 结对编程可能让程序员们相互学习得更快。有些时候,学习对方的长外,可能会和程序员们在起滋生不良气氛一样快。比如,合伙应付工作,敷衍项目。
  5. 面对新手,有经验的老手可能会觉得非常的烦躁。不合适的沟通会导到团队的不和谐。
  6. 新手在面对有经验的老手时会显得非常的紧张和不安,甚至出现害怕焦虑的的精神状态,从而总是出现低级错误,而老手站在他们后面不停地指责他们导致他们更加紧张,出现恶性循环。最终导致项目进展效率低下,并且团队貌合神离。
  7. 有经验的人更喜欢单兵作战,找个人来站在他背后看着他可能会让他感到非常的不爽,最终导致编程时受到情绪影响,反而出现反作用。

  是否使用结对编程,需要具体问题具体分析,不可盲目。任何事手都有他的好与坏,结对编程也不例外,只有知道了好与坏,你才能更好的利用它。

  资料链接:https://kb.cnblogs.com/page/58732/

  成员优点:认真,上进,创造性思维强

    缺点:模块化思维欠缺


原文地址:https://www.cnblogs.com/lvgx/p/8733486.html