• 结对作业


    组员:吕国馨  夏江华

    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/

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

        缺点:模块化思维欠缺

    
    
  • 相关阅读:
    Java8 Time
    Java8 Stream
    Java8 Lambda
    Thinking in java 阅读
    String 中的 split 进行字符串分割
    Kubernetes 学习(九)Kubernetes 源码阅读之正式篇------核心组件之 Scheduler
    Kubernetes 学习(八)Kubernetes 源码阅读之初级篇------源码及依赖下载
    Golang(八)go modules 学习
    SQLAIchemy(二)ORM 相关
    SQLAIchemy 学习(一)Session 相关
  • 原文地址:https://www.cnblogs.com/lvgx/p/8733486.html
Copyright © 2020-2023  润新知