• 四则运算结对作业


    一、Coding.Net项目地址:

     https://git.coding.net/qiuyuwutong/Operation2.git

      URL地址:

    二、PSP表格

    PSP2.1

    任务内容

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

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

    Planning

    计划

    30

    20

    ·        Estimate

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

    30

    20

    Development

    开发

    960

    940

    ·        Analysis

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

    30

    120

    ·        Design Spec

    ·         生成设计文档

    30

    50

    ·        Design Review

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

    30

    20

    ·        Coding Standard

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

    10

    10

    ·        Design

    ·         具体设计

    60

    60

    ·        Coding

    ·         具体编码

    600

    500

    ·        Code Review

    ·         代码复审

    100

    60

    ·        Test

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

    100

    120

    Reporting

    报告

    100

    190

    ·         Test Report

    ·         测试报告

    60

    150

    ·         Size Measurement

    ·         计算工作量

    30

    10

    ·         Postmortem & Process Improvement Plan

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

    10

    30

    三、接口设计

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

         接口设计( Interface Design

      耦合性是指模块间互相依赖的程度。松耦合(loose coupling)降低了不同模块间的依赖程度

    四、计算模块接口的设计与实现过程

      (一)设计Create类

        通过调用Create类里面的createExpression方法可以产生满足条件的运算式

      (二)设计Calculate类

            用来计算运算式的值,其中JS里面的eval()函数

    五、计算模块接口部分的性能改进

      Create.java

        问题一:是否产生括号

        设计思路:设计运算优先级,加减运算优先级小于乘除运算优先级,如果相邻两个运算符前面运算符优先级小于后面运算符的优先级,则在前面的运算式加上括号。代码如下:

    for(int j=1;j<=sumOfOperation-1;j++){
                    //System.out.println(bracketExist);
                    if(bracketExist&&priority(operatorCreate[j-1])<priority(operatorCreate[j])){
                        ex="("+ex+")"+operatorCreate[j]+String.valueOf(number[j+1]);
                    }
                    else{
                        ex+=operatorCreate[j]+String.valueOf(number[j+1]);
                    }
                    if(fractionExist(ex)){
                        break;
                    }
                }

                            问题二:实现至少生成两种运算符

             设计思路:要满足生成两种不同的运算符,只要让后一个产生的运算符不等于前一个产生的运算符即可。代码如下:

    number[0] = random.nextInt(scope_Upper-scope_Lower+1)+scope_Lower;
                for (int j = 1; j <= sumOfOperation; j++) {
                    number[j] = random.nextInt(scope_Upper-scope_Lower+1)+scope_Lower;
                    while(number[j]==number[j-1])
                        number[j] = random.nextInt(scope_Upper-scope_Lower+1)+scope_Lower;
    //                System.out.println(number[j]);
                }

         问题三:是否产生乘除

                               设计思路:运算符存放在一个数组char[] operator= new char[]{ '+' , '-' , '*' ,'/' }里,如果不产生乘除,随机产生的运算符范围在数组的前两个元素;如果产生运算符,就让随机产生的运算符     范围在整个数组。代码如下:

    for (int j = 0; j < sumOfOperation; j++) {
                    int op=0;
                    if(mul_Div)
                        op = random.nextInt(4);//是否有乘除法
                    else
                        op = random.nextInt(2);
                    operatorCreate[j]=operator[op];
                }

            问题四:是否在运算过程中产生分数

                                 设计思路:在运算过程中判断是否产生分数,如果产生分数,就让其重新生成运算式。代码如下:

    public static boolean fractionExist(String ex)
        { 
            double answer = Double.parseDouble(Calculate.calculateExpression(ex));
            if(Math.floor(answer)!=answer||answer<0||answer>9999){
                return true;
            }else{
                return false;
            }
        }

        Command.java

          问题一:怎么一次输入多个命令行参数,而且参数的前后顺序并非是固定的

            例如 java Command -m 1 50 -n 20 -c 

            设计思路:通过for循环来遍历命令行参数,通过switch语句来处理每次循环输入的命令行参数。代码如下:

    for (int i = 0; i < args.length; i++) {
                switch(args[i]){
                    case "-n"://题目的数量
                    case "-N":

         这里设置两个case "-n",case "-N",来解决大小写不区分这个问题。

         性能分析图:

    六、计算模块部分单元测试展示

        测试输入的参数是否合法时,预期值先给了一个合法值,再给一个非法值,分别进行测试。

      Command.Java

    //测试输入的参数是否合法
    @Test()
    public void testParameter1Error1(){
    String ex ="-n";
    assertEquals(true,new Command().parameter1Error(ex));
    }
    @Test()
    public void testParameter1Error2(){
    String ex ="-z";
    assertEquals(false,new Command().parameter1Error(ex));
    } 
    //测试输入的参数n是否合法
    @Test
    public void testScopeOfSumError1(){
    int num=-1;
    assertEquals(false, new Command().scopeOfSumError(num));
    }
    @Test
    public void testScopeOfSumError2(){
    int num=10;
    assertEquals(true, new Command().scopeOfSumError(num));
    }

        (一)parameter1Error函数

          作用:判断输入的参数是否是-n,-m等

    public static boolean parameter1Error(String ex){
    ArrayList<String> args = new ArrayList<String>(); 
    args.add("-n");args.add("-N");
    args.add("-m");args.add("-M");
    args.add("-o");args.add("-O");
    args.add("-c");args.add("-C");
    args.add("-b");args.add("-B");
    if(args.contains(ex)){
    return true;
    }
    else{
    return false;
    }
    } 

         (二)scopeOfSumError函数

                作用:测试输入的参数-n是否合法。

    public static boolean scopeOfSumError(int num){
    if(num<=0||num>10000)
    return false;
    else{
    return true;
    }
    }

      CalculateJava

        (一)calculateExpression函数

          作用:接收的是一个表达式,返回的是表达式的结果,以下是calculateExpression函数:

    public static String calculateExpression(String ex){
    try { 
    return String.valueOf(engine.eval(ex));
    } catch (ScriptException e) { 
    e.printStackTrace();
    return null; 
    } 
    }

                以下是calculateExpression函数的单元测试:

    @Test
    public void test() { 
    String ex ="3*4-6/2"; 
    assertEquals("9",new Calculate().calculateExpression(ex));
    }

      测试覆盖率截图:

    七、计算模块部分异常处理说明

      (一) 判断输入的参数的格式是否正确

        比如,用户输入-z,-t等参数,就会提示用户错误。

        如下图所示:

        测试样例:

      (二)判断输入的参数-n、-m的格式是否正确

        例如,输入-n t就会报错

        如下图所示:

        测试样例:

       (三)判断参数n、m、o的参数范围是否正确

        如下图所示:

          测试样例:

    八、界面模块的详细设计过程

        界面分三个版块,第一个版块为出题,第二个版块为答题,第三个版块为答题结果。支持两种语言,中文与English。用到的前端技术有HTML、CSS、JavaScript、bootstrap。

      (一)出题版块:选用bootstrap框架

          点击打印题目就跳转到答题板块

          

        

        (二)答题界面

          用js写了计时器计时,答题结束后不归0,便可方便的得知答题所用最终时间。界面如下图所示:

        (三)答题结果

          显示答对多少题和共答题多少

        代码展示:

          1.中英文切换:

    <select class="selectLanguage" class="form-control"   language=javascript onchange= " location.href=this.value">
     <option  value ="中文">中文</option>
     <option value="CalEnglish.html">English</option>
                </select>

          2.计时器:

            HTML代码:

    <ul style="position: absolute;bottom: 380px; left: 160px; list-style-type: none">            
                        
                                <input type="button" name="btn" class="btn-lg btn-info" onclick="startclock() "  value="开始答题">
                                <input type="button" name="btn" class="btn-lg btn-info" value="暂停答题" onclick="pauseclock()">
                                <input type="button" name="btn" class="btn-lg btn-info" onclick="stopclock()" value="停止答题">
                                <input class="btn"  name="showtime" style="color:#ff0000;200px;height: 48px;font-size: 20px;" id="showtime" type="text" value="0时0分0秒">
                        </ul>

            JS代码:

    <script language="javascript">
        var se,m=0,h=0,s=0,ss=1;
        function second(){
        if((ss%100)==0){s+=1;ss=1;}
        if(s>0 && (s%60)==0){m+=1;s=0;}
        if(m>0 && (m%60)==0){h+=1;m=0;}
        t=h+"时"+m+"分"+s+"秒"+ss+"毫秒";
        document.getElementById("showtime").value=t;
        ss+=1;
        document.getElementById("one").value=h;
        document.getElementById("two").value=m;
        document.getElementById("three").value=s;
    }
    function startclock(){se=setInterval("second()",10);}
    function pauseclock(){clearInterval(se);}
    function stopclock(){clearInterval(se);ss=1;m=h=s=0;}
    </script>

    九、界面模块与计算模块的对接

      在界面模块我们用Form表单进行提交,将前台接受到的参数传到了Cal2.jsp,在这一界面我们调用在计算模块的接口,循环生成给定数目的表达式,并让用户输入自己计算的结果,然后当用户点击提交后,会在跳转到realAnswer.jsp页面,在这页面会计算用户答对的题数。
     

    十、描述结对的过程

      我们两个刚开始着手做项目的那个下午一起初步完成了计算模块,之前两个人的项目均没有加上括号,一起通过学习加上了括号,但是当时没有解决两个问题。第一:不知如何设定是否有乘除法;第二、不知如何确保一次输入多个参数,而且参数可以任意顺序。最后解决了这个问题。具体解决方案前面有详细说明,这里不再赘述。第一天非常顺利。

      第二天计划完成异常处理模块,但是却花费了很长时间完善第一个计算模块,之前大概实现了,但是有一些细节没有考虑到(如参数的大小写问题)。完善计算模块后开始着手做异常模块,但因为两个人对异常都掌握的不太好,花费了很长时间学习自定义异常等等,最终完成了异常模块。整体还算顺利,耗费的时间主要是因为对异常的掌握程度不够。

      第三天尝试做单元测试,也比较顺利,但是那时不明白对异常进行单元测试,请教了学姐之后解决了问题。当天,我们完成了前端界面的设计图。

      完成了设计图后,敲出了前台界面,本以为一切很顺利了,但是没想到是更难的阶段,前后端交互的时候遇到了很多问题。项目在两个人的电脑上导过来导过去,就报了很多莫名其妙的错误,两个人都重新配了好几次环境。之后花了很多的时间调代码,在完成后两个人一起写了博客,对这次的作业进行了总结。

    十一、结对编程优缺点及个人优缺点

      (一)结对编程优点

        结对编程是两个人的智慧,两个人的思考,看待问题肯定会更全面一些。就例如我们,两个人都没有完成括号,两个人在一起很容易就加上了括号。遇到Bug也没有那么恐惧,自己思考过后总习惯问一句:“**你怎么看呢?”一般这种时候,我们总会想出一个比较完美的解决方案,然后非常非常开心,感觉解决一个Bug比自己纯敲一段代码都要快乐得多。

          两个人在一起编程时有时候会避免一些低级错误,有时候可能只是因为字母打错了,就导致工程止步不前,两个人编程,加上眼镜八只眼睛在盯着,避免犯一些低级错误。

        我们两个每次一起编程最少在五个小时,一个人的精力是有限的,有时候编着编着就会特别累,这个时候就会换一下位置,让自己的身体和大脑都有个缓冲。

      (二)结对编程缺点

          有时候对于同一个问题,我们有不同的思考,有时候就会有些分歧。编程习惯也有些不同,可能一个人习惯的编程方式恰好是另一个人最讨厌的方式,不过总归是要磨合的。

      (三)个人优缺点

        1、颜超一

            优点:认真,严谨,考虑全面,耐心,逻辑能力强

            缺点:太过于追求细节

           2、丁小帅

            优点:能吃苦、耐心、热情、思考能力不错

            缺点:不注重细节

         

  • 相关阅读:
    Sublime安装package control的操作
    Sublime的简单操作
    C# 泛型方法
    C# 数组的讲解(ArrayList 与List的区别)
    免费的天气API
    bootstrapValidator的验证
    sqlServer 多行合并为一行
    bootstrap的安装注意
    SQL数据库中把一个表中的数据复制到另一个表中
    JavaScript的误区
  • 原文地址:https://www.cnblogs.com/yanchaoyi/p/8763578.html
Copyright © 2020-2023  润新知