四则运算网页版

一、仓库地址:https://git.coding.net/q834934034/Project.git

二、PSP表格:

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

Planning

计划

60

· Estimate

· 估计这个任务需要多少时间

50

Development

开发

1050 

· Analysis

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

60

· Design Spec

· 生成设计文档

40

· Design Review

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

30

· Coding Standard

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

20

· Design

· 具体设计

60

· Coding

· 具体编码

660

· Code Review

· 代码复审

60

· Test

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

120

Reporting

报告

120 

· Test Report

· 测试报告

60

· Size Measurement

· 计算工作量

30

· Postmortem & Process Improvement Plan

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

30

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

三、接口设计

(1)Information Hiding:信息隐藏是结构化设计与面向对象设计的基础。在结构化中函数的概念和面向对象的封装思想都来源于信息隐藏。信息隐藏的特点:(1)不可感知性(2)鲁棒性(反映了信息隐藏技术的抗干扰能力)(3)隐藏容量(应用于隐蔽通信中时,为了提高通信的效率),同时在web页面程序开发中,运用到的实体类中的属性均运用private修饰,向外提供geter和seter方法,增强了信息的保护。

(2)Interface Design:接口中的方法是不能直接使用的而是要运用接口的实现类来实现的,运用接口编程,对出题模块和计算模块设计接口增强了程序的可扩展性,可维护性,其中最主要的就是扩张性。

(3)Loose Coupling:在程序设计中将出题模块、计算模块、运算符判断模块等均封装到不同的方法中,降低程序的耦合度。

 

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

1.类的组成

 

Command类:Command类:AlgorithmImpl类:

2.各个类的基本功能及包含的函数

Command类:包含主函数,主要扶着接收,判断和处理命令行输入的参数。通过该类从后台获取参数要求,并进行判断参数是否符合要求,若符合,则将通过调用接口产生符合要求的运算式。若不符合要求,则抛出异常,给出提示重新输入;

IsRight类:将从后台输入的自妇产进行解析,看是否符合生成运算式的要求,若符合,则将符合的参数返回到Command类,若不符合,则将提示参数不符合要求,重新输入

AlgorithmImpl类:Algorithm接口的具体实现。

3.接口

Algorithm接口:主要包含生成带括号的运算式和不带括号的运算式两个函数,还有在生成运算式过程中会用到的判断符号优先级和将代表运算符的数字转换为相应的字符的函数(0-"+",1-"-",2-"*",3-"÷");

类之间的关系如下:

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

我在运算模块的性能分析过程中,大约花费了5小时,首先我自己因为不了解,所以用了接近一半的时间向工作室的其他同学请教,并且观察他们做性能改进的过程,经过性能分析知道了我有些资源在使用结束后是没有回收的,经过排查后,我发现了是在写入文件后没有关闭输出流,导致了资源没有完全回收。发现这一问题后,我针对它进行了改进,关闭了输出流。使项目的性能得到了提高。在项目中消耗最大的函数isParenthesis和noParenthesis两个方法,由于限制条件太多,所以当题目数量过大时,函数消耗会很大。在分析过程中发现在运行过程中,没有对循环时产生的list清空,所以浪费很大空间,针对这些问题,我们也对代码进行了修改。以下是性能改进截图:

六、单元测试

单元测试主要分为Algorithm接口的实现AlogriyhmImpl类中的方法测试和IsRight类中的方法测试

AlgorithmTest类部分代码:

 1   @Test
 2     public void algorithm() throws Exception {
 3     Algorithm algorithm =new AlgorithmImpl();
 4         for(int i =0;i<12;i++){
 5             System.out.println(algorithm.algorithm(1,100,1,1));
 6             System.out.println(algorithm.algorithm(10,200,2,1));
 7             System.out.println(algorithm.algorithm(5,200,4,1));
 8             System.out.println(algorithm.algorithm(5,100,7,1));
 9             System.out.println(algorithm.algorithm(10,200,1,2));
10             System.out.println(algorithm.algorithm(10,100,2,2));
11             System.out.println(algorithm.algorithm(1,100,4,2));
12         }
13     }
14 
15     @Test
16     public void bracketsAlgo() throws Exception {
17         Algorithm algorithm =new AlgorithmImpl();
18 
19         for(int i =0;i<10;i++){
20             System.out.println(algorithm.BracketsAlgo(10,100,1,1));
21             System.out.println(algorithm.BracketsAlgo(1,100,5,1));
22             System.out.println(algorithm.BracketsAlgo(10,100,1,2));
23             System.out.println(algorithm.BracketsAlgo(5,200,4,2));
24         }
25     }

 


IsRightTest测试类中的部分代码:

 1   @Test
 2     public void cTest() throws Exception {
 3         IsRight  isRight = new IsRight();
 4         String s[]={ "-n","12", "-m","1","100","-c","-o"};
 5         String s1[]={ "-n","12", "-m","1","100"};
 6         System.out.print(isRight.cTest(s));
 7         System.out.print(isRight.cTest(s1));
 8     }
 9 
10     @Test
11     public void mTest() throws Exception {
12         IsRight  isRight = new IsRight();
13         String s[]={ "-n","12", "-m","1","100","-c","-o"};
14         String s1[]={ "-n","12", "-m","1","100"};
15         String s2[]={ "-n","12", "-m","1","10000"};
16         String s3[]={ "-n","12", "-m","333","100"};
17         String s4[]={ "-n","12", "-m","60","100"};
18         String s5[]={ "-n","12", "-m","1","2"};
19         System.out.print(isRight.mTest(s));
20         System.out.print(isRight.mTest(s1));
21         System.out.print(isRight.mTest(s2));
22         System.out.print(isRight.mTest(s3));
23         System.out.print(isRight.mTest(s4));
24         System.out.print(isRight.mTest(s5));
25     }

 

构造测试数据的思路:尽可能多的把可能出现得情况列举出来,提高代码覆盖率。又因为产生的符号的随机数都是随机的,因此应该在测试时多测试几次,降低偶然性。

单元测试的测试覆盖率截图:

七、模块部分异常处理

在计算模块中,用户如果传入不合法参数,程序会捕获异常,显示异常类型并提示错误参数。由于我们的项目是用web实现的,对于不合法的参数(如汉字,符号)以及参数为空这些问题都会在前端进行判断,并提醒用户,所以在异常处理的得上设计中,只做了参数范围不合法一种异常类型,由于题目会有上下界的要求,但当上下界范围较小时,无法产生题目,因此我们设定当上下界只差小于30时,抛出异常,提示用户扩大范围。

当符号数量不在合理范围内时:

1 @Test
2     public void createCharacter() throws Exception {
3 
4         System.out.println(createArithmetic.CreateCharacter(56,true));
5 
6     }

当上下界不在合理范围时:

1 @Test
2     public void createNumber() throws Exception {
3         System.out.println(createArithmetic.CreateNumber(4,-9,800));
4     }

八、界面的设计

一共设置了5个页面,分别是出题需求,上传文件,上传成功与答题,输出结果和提示界面:

出题需求我们用到了form表单,设置文本输入框:

上传文件可以上传已经成的文件,点击做题按钮可以作答:

答题页面点击终止答题可以显示答题结果:

输出结果将把你做的题的正确答案输出来:

提示页面是你的输入参数错误进行提示:

下面是简单的代码:

<body>
<div class="main">
<form>
<p>请输入生成的题目数量:&nbsp;&nbsp;
<input type="number" name="" id="number" />
</p>
<p>请输入算式数值范围:&nbsp;&nbsp;
<input type="number" name="" id="range" />&nbsp;~
<input type="number" name="" id="range" />
</p>
<p>请输入题中最多包含的运算符数:&nbsp;&nbsp;
<input type="number" name="" id="" />
</p>
<p>题中是否包含乘除法:&nbsp;&nbsp;
是<input type="radio" name="check" id="" />
否<input type="radio" name="check" id="" />
</p>
<p>题中是否包含括号:&nbsp;&nbsp;
是<input type="radio" name="braket" id="" />
否<input type="radio" name="braket" id="" />
</p>
<button id="creat">点击生成题目文件</button>
<button id="upload"><a href="submit.html" id="a">上传文件</a></button>
</form>
</div>
</body>

/*背景*/
body{
background-image: url(../img/picture1.jpg);
}
/*主体样式*/
.main{
border: 1px solid #E0FFFF;
margin: 0 auto;
width: 520px;
height: 350px;
}
/*表单样式*/
form{
position: relative;
top: 60px;
left: 10px;
}
/*取值范围框的大小*/
#range{
width: 50px;
}
/*生成文件按钮位置*/
#creat{
position: relative;
top: 20px;
left: 75px;
}
/*生成文件按钮位置*/
#upload{
position: relative;
top: 20px;
left: 130px;
}
/*上传跳转链接样式*/
a:link,a:visited{
text-decoration: none;
color: black;
}

 

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt"%>
<html>
<head>
    <title>生成题目</title>
</head>
<center>
<body style="margin-top:13%;margin-left:1%;background:url(../../img/bg.jpg)no-repeat ;background-position-x:55%;background-position-y:-10%;padding-top: 20px;font-size: 20px;">
            <font style="color:#1e90ff" size="3">${msg}</font>
            <form method="post" action="${pageContext.request.contextPath}/arithmetic?state=download&path=${path}">
                <c:if test="${fileName != null}">
                    <input type="text" name="fileName" value="${fileName}" style="border-style:none;width: 60px">
                    <input type="submit" value="下载" />
                </c:if>
            </form>
<form name="create" method="post" onsubmit="return checkform()" action="${pageContext.request.contextPath}/arithmetic?state=create">

  

复制代码
import myException.MyException;
import util.Calculation;
import util.CreateArithmetic;
import util.Impl.CalculationImpl;
import util.Impl.CreateArithmeticImpl;

public class Command {

    public  static void main(String [] args) throws Exception {

        CreateArithmetic arithmetic = new CreateArithmeticImpl();

        int num = 0;
        boolean isParenthesis = false;
        boolean isMulAndDiv = false;
        int lownum = 0;
        int upnumber = 0;
        int chaNum = 1;
        String msg = "";
        boolean flag = true;
        try {
            for(int i = 0; i < args.length ;i++){
                switch (args[i]) {
                    case "-n":
                        if(args[i+1].matches("[0-9]+") && i < args.length-1){
                        num = Integer.parseInt(args[i+1]);
                        i++;
                        }else {
                            msg = "参数类型错误";
                            flag = false;
                        }
                        break;
                    case "-m":
                        if((args[i+1].matches("[0-9]+")) && (args[i+2].matches("[0-9]+")) && i < args.length-2){
                            lownum = Integer.parseInt(args[i+1]);
                            upnumber = Integer.parseInt(args[i+2]);
                            i += 2;
                        }else {
                            msg = "参数类型错误";
                            flag = false;
                        }
                        break;
                    case "-o":
                        if((args[i+1].matches("[0-9]+")) && i < args.length-1){
                            chaNum = Integer.parseInt(args[i+1]);
                            i++;
                        }else {
                            msg = "参数类型错误";
                            flag = false;
                        }
                        break;
                    case "-c":
                        isMulAndDiv = true;
                        break;
                    case "-b":
                        isParenthesis = true;
                        break;
                    default:
                        msg = " 输入参数不合法参数";
                        flag = false;
                    }

                if(flag == false){
                    System.out.println(msg);
                    break;
                }
        }
            if(num == 0 || lownum == 0 || upnumber == 0){
                System.out.println("缺少参数");
            }else {
                if(flag){
                    arithmetic.createFile(num,isParenthesis,isMulAndDiv,lownum,upnumber,chaNum);
                     System.out.println("文件创建成功!");
                }
            }
        }catch (MyException e){
            System.out.println("参数范围不合法!");
        }
    }
}
复制代码

十、结对过程

因为我和我的队友是室友,所以我们合作起来非常方便,在修改代码和BUG的时候也很有默契,能够做到优势互补;

十一、结对编程的优缺点

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

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

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

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

  我的优点:比较细心、代码能力较强、对问题的分析能力强

  我的 缺点:有时容易沉不住气、遇到困难解决效率比较低

  郑栋的优点:遇到难题能沉得住气,这也是和我互补的一个地方、协作能力很好、有耐心

  郑栋的缺点:容易犯低级错误

十二、实际PSP表格

PSP

任务内容

实际时间(min)

Planning

计划

50

 Estimate

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

30

Development

开发

1610

Test

测试

130

Algorithm Optimization

算法优化

220

Interface Design

接口设计

180

Coding Standard

代码规范

60

Design

具体设计

200

Coding

具体编码

660

Code Review

代码复审

60

Test

测试

150

Reporting

报告

120

Test Report

测试报告

100

Size Measurement

计算工作量

30

Postmortem & Process Improvement Plan

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

60

十三、总结

对于这次作业,更多的还是依赖于工作室的同学的帮助,这也反应了我和郑栋的技术还是太LOW,如果以后这样的作业经常有,我们总不能一直借鉴别人的代码,所以还是得提高自身的技术水平;

JAVA真的超级强大!虽然我的JAVA不好,但是我看了其他同学的博客,尤其是做的GUI形式的作业,我就感觉到JAVA的全面性,最后希望自己能够多主动一点去学习提高自身技术,希望在下次的

作业能全靠自己完成

posted @ 2018-04-10 08:12  默羽明  阅读(246)  评论(1编辑  收藏  举报