四则运算结对作业

一、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、丁小帅

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

        缺点:不注重细节

     

原文地址:https://www.cnblogs.com/yanchaoyi/p/8763578.html