结对作业

本次项目过程中,是我对javaweb有了更加深入的了解,以前总是自己看视频并没有自己组队尝试的机会,也没有很好的实践能力。这次结对项目使我对模块化的重要性以及效能分析有了深刻的认识,对我以后的学习有很大的帮助。在此十分感谢我的队友马玲,帮助我们上传到服务器上的马福孝同学,各位学长学姐以及我们的兄弟小组陈芳、柯招坤小组。

一、项目

源代码地址:https://git.coding.net/mal123/arithmetic.git

测试url:localhost:8080/arithmetic?state=toHome

网页版测试地址:http://140.143.62.245:8080/mal_war/arithmetic?state=toHome

结对成员: 马玲 2016012054   博客地址:http://www.cnblogs.com/malings/p/8751840.html

      王雪 2016012013

二、PSP展示

PSP

任务内容

计划时间(min)

Planning

计划

60

 Estimate

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

30

Development

开发

1200

Test

测试

90

Algorithm Optimization

算法优化

180

Interface Design

接口设计

150

Coding Standard

代码规范

240

Design

具体设计

120

Coding

具体编码

450

Code Review

代码复审

90

Test

测试

60

Reporting

报告

180

Test Report

测试报告

120

Size Measurement

计算工作量

30

Postmortem & Process Improvement Plan

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

120

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

1)关于Information Hiding:信息隐藏

对于面向对象的程序设计而言,信息隐藏是一种重要的软件开发手段,它与对象的封装与模块化相关。信息隐藏是开发整体程序结构时使用的法则,将每个程序的隐蔽或封装在一个单一的设计模块中,定义每一个模块时尽可能少地显露其内部的处理。把信息隐蔽用作模块化系统的一个设计标准,在后面项目调试过程中,编程人员的任务量能够得以减轻,提高代码可读性。

本次结对项目,我们将生成题目和计算两个模块设计成接口,用户只需在页面输入自己所想要的参数的值,点击提交,后台就会调用生成题目这个接口,将生成的题目输出出来。计算接口也是同样的调用,就会将结果与输入框中的结果进行核对正确性。在后期项目优化过程中,我们只需要修改接口中的方法来实现功能,不必修改其他地方,极大程度上减轻了我们的任务量。

2)Interface Design:接口设计

设计接口的时候,我们也有讨论接口该如何设计会更加合理。接口在设计的时候应当尽量的详细划分,使得每一个接口中方法应该尽量少,将功能实现在接口中,所以我们决定讲生成题目与计算功能分开,分成两个接口。在层与层之间调用接口,类之间通过接口访问。

3)Loose Coupling:降低耦合

模块与模块之间总会存在一些“联系”,这就会提升我们维护过程中的复杂度和任务量。松耦合通过接口的方式实现各个模块之间的调用,可以使模块在发生改变时,其他的部分可以保持不变,减少模块间的相互“联系”,降低耦合。

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

我们将生成题目和计算设计成了两个接口。

 

生成题目接口:

方法间的关系:

计算接口:

 

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

 我们用JProFiler对内存、ALL OBJECTS、CPU等方面进行了分析。以下是我们效能分析:

 项目总体分析图:

CPU分析图:

性能分析:

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

在单元测试中,我们首先对两个接口的基本功能进行了测试,在确保基本功能都可以正确实现之后,我们对Command类进行了单元测试。

  Command类测试代码如下:

import org.junit.Test;

import static org.junit.Assert.*;

public class CommandTest {
    @Test
    public void main() throws Exception {
        Command command = new Command();
        String[]  args1  = {"-m","3","800","-n","7"};//正确的参数类型(默认模式)
        String[]  args2  = {"-m","50","400","-n","100000"};//参数范围不合法
        String[]  args3  = {"-m","3","800","-n","7","-o","3","-b","-c"};//正确的参数范围(不默认)
        String[]  args4  = {"-m","3","800","-n","7","-o","你","-b","-c"};//参数类型错误
        String[]  args5  = {"-m","L","800","-n","7"};//参数类型错误
        String[]  args6  = {"-m","3","800","-n","、"};//参数类型错误
        String[]  args7 = {"-m","3","800","-n","7","M"};//输入参数不合法
        String[]  args8  = {"-m","3","800"};//缺少参数
        Command.main(args1);
        Command.main(args2);
        Command.main(args3);
        Command.main(args4);
        Command.main(args5);
        Command.main(args6);
        Command.main(args7);
        Command.main(args8);

    }

}

 代码覆盖率如下:

 接口类测试覆盖率:

 Command类的测试覆盖率:

 

在单元测试中,每个类对应一个测试类,测试类中每个测试方法对应一个方法。构造测试数据时,根据方法中每个分支对应的情况,设置相应的参数,确保测试会进入到每一个分支,达到测试的目的。

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

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

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

 

@Test
    public void createCharacter() throws Exception {

        System.out.println(createArithmetic.CreateCharacter(56,true));

    }

 

 

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

 

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

 

 

当上下界范围太小时:

 

 @Test
     public void createFile() throws Exception {
         System.out.println(createArithmetic.createFile(-9,true,true,10,1000,4));
 
     }

 

 

当题目数量不在合理范围时:

 

@Test
     public void createFile() throws Exception {
         System.out.println(createArithmetic.createFile(-9,true,true,10,1000,4));
 
     }

 

 

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

 界面模块前端设计采用jsp和js结合完成,通过servlet完成前后端的交互。

  根据程序所要实现的功能,我们将设计四个页面用来展示并实现这些功能:

 

  1)home.jsp:四则运算的主页面,有生成题目和上传题目两个提交按钮

 

  2)create_arithmetic.jsp:生成题目的页面(1)通过form表单来获取用户输入的参数并生成相应题目,

                                                                         (2)可让用户下载生成的题目

                                                                         (3)利用JavaScript对输入框进行判空

<script language="javascript" type="text/javascript">
                function checkform(){
                    if(document.getElementById('ipt1').value.length==0){
                        alert('输入为空!');
                        document.getElementById('ipt1').focus();
                        return false;
                    }
                    if(document.getElementById('ipt2').value.length==0){
                        alert('输入为空!');
                        document.getElementById('ipt2').focus();
                        return false;
                    }
                    if(document.getElementById('ipt3').value.length==0){
                        alert('输入为空!');
                        document.getElementById('ipt3').focus();
                        return false;
                    }
                }
            </script>

 

  3)upload _arithmetic.jsp:上传文件的页面(1)用户可选择文件路径进行文件上传

                                                                           (2)用JS进行输入框的判空以及文件格式的正确性判断

 

<html>
<head>
    <title>上传题目</title>
</head>
<body style="margin-left:30px;margin-top:120px;background:url(../../img/bg.jpg)no-repeat ;background-position-x:55%;background-position-y:-10%;padding-top: 20px;font-size: 20px;">
<form  action="${website}/arithmetic?state=upload"  onsubmit="return checkform()" method="post" enctype="multipart/form-data">
    <table style="padding-top: 160px" align="center">
        <tr>
            <td colspan="2" align="center">
                <font style="color:#1e90ff" size="3">${msg}</font>
                <a href="${website}/arithmetic?state=toDoArithmetic" style="text-decoration: none "><font style="color:dodgerblue">${msg1}</font></a>
            </td>
        </tr>
        <tr style="height: 15px"></tr>
        <tr>
            <td><font color="#1e90ff" face="STHupo" size="4">选择一个文件:</font></td>
            <td><font color="#1e90ff" face="STHupo" size="4">
                <input type="file" name="uploadFile"  id="nu"/>
            </font>
            </td>
        </tr>
        <tr style="height: 25px">
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="上传" style="width: 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;" />
            </td>
            <td align="right">
                <a href="${website}/arithmetic?state=toHome" style="text-decoration: none ">
                    <input type="button" value="返回" style="width: 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;">
                </a>
            </td>
        </tr>
    </table>
</form>

<script language="javascript" type="text/javascript">
    function checkform(){
        if(document.getElementById('nu').value.length==0){
            alert('您还没有选择文件!');
            document.getElementById('nu').focus();
            return false;
        }
    }
</script>
</body>
</html>

4)do _arithmetic.jsp:用户答题页面(1)用户页面会显示题目总数和当前题目序号

                                                          (2)页面有下一题,结束,返回主页三个按钮可供用户选择

                                                          (3)答题结束页面会显示用户答题数目,答对的题目数量以及花费时间。

 

<html>
<head>
    <title>做题</title>
</head>
<center>
<body style="margin-top:15%;margin-left:1%;background:url(../../img/bg.jpg)no-repeat ;background-position-x:55%;background-position-y:-10%;padding-top: 20px;font-size: 20px;">

<form  id="doform"  onsubmit="return checkform()" action="${website}/arithmetic?state=do&i=${i}&count=${count}" method="post">
    <table style="padding: 20px" align="center">

        <c:if test="${flag != 0}">
        <tr style="border: hidden;height: 50px">
            <td style="border: none">
                <font style="color:#1e90ff" size="4">共${list.size()}题/第${i+1}题&nbsp;&nbsp;&nbsp;&nbsp;</font>
            </td>
            <td style="border-radius:5px;border: double; border-color: dodgerblue" >
                <font size="4">${list.get(i)}</font>
            </td>
            <td style="border: none">
                &nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;
            </td>
            <td style="border-radius:5px;border: double;border-color: dodgerblue">
                <input type="text" name="answer"  id="nu" value="0" onfocus="javascript:if(this.value=='0')this.value='';" style="border-style:none;width: 60px;height: 50px"/>
            </td>
        </tr>

      <tr style="height: 30px"></tr>

        <tr style="border: hidden;">
            <c:if test="${i < list.size()-1}">
            <td colspan="2" align="center" style="border: none">
                <input type="submit" value="下一题"  style="width: 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;" />
            </td>
            </c:if>

            <td colspan="2" align="center" style="border: none">
                <input type="button" value="结束"  onclick="return over();" style="width: 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;"/>
            </td>
        </tr>
        </c:if>
        <tr style="height: 60px"></tr>
        <font style="color:#1e90ff;margin-top: 15%" size="5" >${msg1}</font>
        <tr>
            <td colspan="4" align="left">
                <a href="${website}/arithmetic?state=toHome" style="text-decoration: none ">
                    <input type="button" value="返回" style="width: 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;">
                </a>
            </td>
        </tr>
    </table>
</form>

<script type="text/javascript">
    function over(){
        if(document.getElementById('nu').value.length==0){
            alert('请输入答案');
            document.getElementById('nu').focus();
            return false;
        }else {
            document.forms.doform.action="${website}/arithmetic?state=end&i=${i}&count=${count}";
            document.forms.doform.submit();
        }

    }

        function checkform(){
            if(document.getElementById('nu').value.length==0){
                alert('请输入答案');
                document.getElementById('nu').focus();
                return false;
            }
        }
</script>
</body>
</center>
</html>

5)login.jsp:用户登录页面

6)register.jsp:用户注册页面

7)record.jsp:记录用户答题数目,正确率,时间等

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

项目的前后端交互我们使用jsp和servlet来实现,用户发送请求,后台从jsp页面获取到用户所输入的参数,在servlet页面对参数进行处理,调用生成题目接口生成题目到前端页面,答题时调用计算接口中的方法对客户端做出响应。

上传文件:

 

 public void upload(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        RequestDispatcher rd = null;
        if(isMultipart){
            FileItemFactory factory=new DiskFileItemFactory();
            ServletFileUpload upload=new ServletFileUpload(factory);
            Iterator items;
            try{
                items=upload.parseRequest(request).iterator();
                while(items.hasNext()){
                    FileItem item=(FileItem) items.next();
                    if(!item.isFormField()){
                        String name=item.getName();
                        String fileName=name.substring(name.lastIndexOf('\\')+1,name.length());
                        String path=request.getRealPath("file")+File.separatorChar+fileName;

                        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);

                        if (suffix.equals("txt") || suffix.equals("doc"))
                        {
                            File uploadedFile=new File(path);
                            item.write(uploadedFile);
                            response.setContentType("text/html");
                            response.setCharacterEncoding("gb2312");
                            rd = request.getRequestDispatcher("/arithmetic?state=read&path="+path);
                            rd.forward(request,response);
                        }else{
                            request.setAttribute("msg","请上传txt类型的文件");
                            rd = request.getRequestDispatcher("/arithmetic?state=toUpload");
                            rd.forward(request,response);
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

 

读取文件内容:

   public void read(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{

        RequestDispatcher rd = null;
        response.setContentType("text/html");
        response.setCharacterEncoding("GBK");
        PrintWriter out=response.getWriter();
        String realPath= request.getParameter("path");
        List<String> list = new ArrayList<>();
        File file=new File(realPath);
        if(file.exists()){
            FileReader reader=new FileReader(file);
            BufferedReader bufferedReader=new BufferedReader(reader);
            String line =null;
            while((line=bufferedReader.readLine())!=null)
            {
                list.add(line);
            }
            reader.close();
            bufferedReader.close();
        }else{
            out.print("file is not exist!");
            out.close();
        }
        request.getSession().setAttribute("list",list);
        System.out.println();
        request.setAttribute("msg1","题目上传成功,点击这里开始答题!");
        rd = request.getRequestDispatcher(WebContents.UPLOAD);
        rd.forward(request,response);
    }

结束运算:

public void end(HttpServletRequest request,HttpServletResponse response) throws ServletException,Exception,IOException {
        RequestDispatcher rd = null;
        Calculation calculation = new CalculationImpl();

        Date day=new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowDate = df.format(day);

        int count = Integer.parseInt(request.getParameter("count"));
        int i  = Integer.parseInt(request.getParameter("i"));
        List<String> list = (List<String>) request.getSession().getAttribute("list");
        int answer  = Integer.parseInt(request.getParameter("answer"));
        String temp = list.get(i);

        if(i < list.size()){
            if(temp.contains("÷")){
                temp = temp.replace('÷','/');
            }
            int result = calculation.Calculation(temp);
            if(result == answer){
                count++;
            }
            i++;
        }
        String strTime = (String) request.getSession().getAttribute("time");
        long time = (df.parse(nowDate).getTime() - df.parse(strTime).getTime())/1000;
        long seconds = (time%3600)%60;
        long min = (time%3600)/60;
        long hour = time/3600;
        request.setAttribute("flag",0);
        request.setAttribute("msg1","本次共答"+i+"题,答对"+count+"题!用时"+hour+"时"+min+"分"+seconds+"秒!" );
        rd = request.getRequestDispatcher(WebContents.DO);
        rd.forward(request,response);
        request.getSession().invalidate();

    }
}

 

 

实现的功能:

 

附加功能:

       

上传过程中的文件类型应该为.txt

十、描述结对的过程

本次作业,我们两个人在工作室完成结对编程的。本次编程过程中,我们两个人都有明确的分工,一人负责一个模块,过程虽然有点困难,但是我们也充分的感受到了合作的重要性。尤其是在编程过程中,明白了自己设计的东西要简单易懂,让人能一眼看懂。

      

十一、说明结对编程的优点和缺点

结对编程优点: 1.结对编程就是两个程序员互相审查的过程,在编程过程中能够尽早发现问题并解决问题,提高了编程效率。

        2.编程过程中遇到瓶颈两个人相互鼓励,极大的提高了编程的积极性。

        3.两个人在编程过程中不断磨合,相互学习,使双方的代码能力得到了一定程度上的增强,同时也有了合作意识。

结对编程缺点: 1.一个人独立钻研的时候,两个人思路会不同,编程方法也不同,需要时间来抉择用哪一个方法,需要磨合时间

马玲优点: 1.编程能力强,认真

      2.对于模块独立化有独特的见解

      3.逻辑思维能力强,编程严谨

马玲缺点: 1.不够细心,经常会忽略一些细节,考虑不够全面

王雪优点: 1.遇到bug有耐心解决

      2.注重细节,努力

      3.态度积极,乐于学习

王雪缺点: 1.编程经验不足,对程序把握不够

 

十二、总结

 

作业延长的时间里,我们对项目进行了完善,添加了用户的注册和登录功能,并对用户所答问题有所记录。同时我们也对效能测试这一部分重新进行了尝试,进一步完善。

 

但我们的项目在前端页面设计方面我们有所欠缺,相较于其他掌握的较好同学来说,差距仍很大,在以后的学习中会不断完善。

 

十三、PSP表格

PSP

任务内容

实际时间(min)

Planning

计划

50

 Estimate

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

30

Development

开发

1560

Test

测试

110

Algorithm Optimization

算法优化

200

Interface Design

接口设计

160

Coding Standard

代码规范

60

Design

具体设计

160

Coding

具体编码

600

Code Review

代码复审

60

Test

测试

150

Reporting

报告

120

Test Report

测试报告

100

Size Measurement

计算工作量

30

Postmortem & Process Improvement Plan

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

150

转载于:https://www.cnblogs.com/BoscoJK/p/8761314.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值