• 结对作业(web)


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

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

    结对成员:马玲 2016012054 ;王雪 2016012013

    1.开始实现程序之前,我们对程序的各个模块开发上耗费时间估计如下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

    2.关于Information Hiding, Interface Design, Loose Coupling在项目中的应用:

      1.)Information Hiding:信息隐藏。

            信息隐藏是程序设计过程中的一种隔离原则,可以防止用户接触到一个类的某些部分。一个程序模块可以将它的信息隐藏起来,对外仅仅展现出一种接口。当这个模块的具体实现发生改变时,只要保证它的接口不发生变化,则就算不修改模块外的其他代码,程序依旧可以正确执行。对于面向对象的程序设计而言,信息隐藏是一种重要的软件开发手段,它与对象的封装(encapsulation)和模块化(modularity)密切相关,每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能。主要是封装完成之后,后面做项目用起来会很轻松,并且节约工作量和时间,减少错误以及避免代码的臃肿影响代码的可读性。

             在这次的结对项目中,对于用户而言,只需要设置自己的参数,得到相应的题目,用户并不关心程序是怎么生成题目的,他只是调用这个方法,所以可以将生成题目这一模块设计成接口,计算这一模块也是同样的道理。在模块的优化过程中,保证接口不变,我们只需要修改接口的实现,并不需要对其他地方进行修改,程序也可以正常运行。

       2.)Interface Design:接口设计。

             关于接口的设计,我们也阅读了一些资料,其中有一篇我觉得很有用:https://www.jianshu.com/p/580b943d68e2 在设计接口的过程中,不仅要解决当前问题还有保证程序的可扩展性,命名要做到见名知意。对于本次项目来说,我们采用的是mvc模式开发,所以在不同的层都会用到设计的接口,所以命名一定要规范,能够让队友清楚地理解每一个方法所实现的功能,若涉及到多人的项目中,则更应该写一个详细的接口文档来说明。

       3.)Interface Design:松耦合。

             接口的设计要满足的一个原则就是松耦合,松耦合的接口设计使得程序设计的可拓展性大大增强。新设计的类通过实现某个接口,可以轻轻松松地替换当前的某个类,而无需修改调用这些接口的类。所以我们在设计过程中要尽可能减少模块之间的依赖,达到松耦合。

    3.计算模块接口的设计与实现过程

      对于本次的项目,我们会设计两个接口分别实现生成题目和计算题目的功能。具体设计见下图:

           生成题目模块的接口:

        

         

       各个方法之间的关系:

          

      计算题目模块的接口:

         

      本次项目开发,我们采用的是我之前个人项目的代码,我们将之前生成题目和计算的功能分开,仍旧采用之前的算法生成题目,所以具体流程图就不再多做展示了。在之前算法的基础上加入上下界的限制,以及选择乘除法和括号的功能,具体代码写在接口的实现里。在业务逻辑层,获取用户的请求,调用对应的接口,做出响应。由于此次项目要求只需要生成符合要求的题目并不要求算出答案,计算也是对已有的题目直接进行计算,所以在计算题目这一功能的实现我们采用的是eval()函数,直接用于计算用户上传的题目。

    4. 计算模块接口部分的性能改进

      我们用JProFiler对内存、ALL OBJECT、Record Object等方面进行了分析:

    项目总体分析图:

    CPU分析图:

    性能分析:

      在项目中消耗最大的函数isParenthesis方法,由于限制条件太多,所以当题目数量过大时,函数消耗会很大。在分析过程中发现在运行过程中,没有对循环时产生的list清空,所以浪费很大空间,针对这些问题,我们也对代码进行了修改。

    5.计算模块部分单元测试展示

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

      Command类测试代码如下:

     1 import org.junit.Test;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import static org.junit.Assert.*;
     7 
     8 public class CommandTest {
     9     @Test
    10     public void main() throws Exception {
    11         Command command = new Command();
    12         String[] args1 = {"-m", "3", "800", "-n", "7"};//正确的参数类型(默认模式)
    13         String[] args2 = {"-m", "50", "400", "-n", "100000"};//参数范围不合法
    14         String[] args3 = {"-m", "3", "800", "-n", "7", "-o", "3", "-b", "-c"};//正确的参数范围(不默认)
    15         String[] args4 = {"-m", "3", "800", "-n", "7", "-o", "你", "-b", "-c"};//参数类型错误
    16         String[] args5 = {"-m", "L", "800", "-n", "7"};//参数类型错误
    17         String[] args6 = {"-m", "3", "800", "-n", "、"};//参数类型错误
    18         String[] args7 = {"-m", "3", "800", "-n", "7", "M"};//输入参数不合法
    19         String[] args8 = {"-m", "3", "800"};//缺少参数
    20 
    21         List<String[]> list = new ArrayList();
    22         list.add(args1);
    23         list.add(args2);
    24         list.add(args3);
    25         list.add(args4);
    26         list.add(args5);
    27         list.add(args6);
    28         list.add(args7);
    29         list.add(args8);
    30 
    31         for (int i = list.size() - 1; i >= 0; i--)
    32             Command.main(list.get(i));
    33     }
    34 
    35 }

      代码覆盖率如下:

          接口类测试覆盖率:

          

      Command类的测试覆盖率:

           

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

     6.计算模块部分异常处理说明

      在计算模块中,用户如果传入不合法参数,程序会捕获异常,显示异常类型并提示错误参数。由于我们的项目是用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     }

      当上下界范围太小时:

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

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

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

    7. 界面模块的详细设计过程

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

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

      1)home.jsp:主页。有生成题目和上传题目两个按钮,点击不同的按钮进入不同页面,进行相应操作

      2)create_arithmetic.jsp:生成题目页面。页面通过form表单,获取用户输入的参数,生成相应题目,并可供用户下载生成的题目。页面显示每个参数的输入框,提示参数范围,并对必填输入框进行判空;有生成题目和返回(返回主页)两个按钮。

      3)upload _arithmetic.jsp:上传文件页面。用户选择文件上传,上传成功之后点击答题,进入答题页面开始答题。页面显示输入框,用户可选择文件,实现输入框的判空以及文件格式的判断;有上传和返回(返回主页)两个按钮。

      4)do _arithmetic.jsp:答题页面。用户在这个页面可以进行答题。页面会显示题目总数和当前题目序号;显示题目,用户做答;页面有下一题,结束,返回(返回主页)三个按钮,用户可以选择继续答题或结束答题;当做到最后一题时,隐藏下一题的按钮。结束答题之后,页面会显示用户答题数目,答对的题目数量以及花费时间。

      答题页面代码的展示:

     1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     2 <%--
     3   Created by IntelliJ IDEA.
     4   User: 芋头
     5   Date: 2018/4/2
     6   Time: 20:49
     7   To change this template use File | Settings | File Templates.
     8 --%>
     9 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    10 <html>
    11 <head>
    12     <title>上传题目</title>
    13 </head>
    14 <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;">
    15 <form  action="${website}/arithmetic?state=upload"  onsubmit="return checkform()" method="post" enctype="multipart/form-data">
    16     <table style="padding-top: 160px" align="center">
    17         <tr>
    18             <td colspan="2" align="center">
    19                 <font style="color:#1e90ff" size="3">${msg}</font>
    20                 <a href="${website}/arithmetic?state=toDoArithmetic" style="text-decoration: none "><font style="color:dodgerblue">${msg1}</font></a>
    21             </td>
    22         </tr>
    23         <tr style="height: 15px"></tr>
    24         <tr>
    25             <td><font color="#1e90ff" face="STHupo" size="4">选择一个文件:</font></td>
    26             <td><font color="#1e90ff" face="STHupo" size="4">
    27                 <input type="file" name="uploadFile"  id="nu"/>
    28             </font>
    29             </td>
    30         </tr>
    31         <tr style="height: 25px">
    32             <td></td>
    33             <td></td>
    34         </tr>
    35         <tr>
    36             <td>
    37                 <input type="submit" value="上传" style=" 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;" />
    38             </td>
    39             <td align="right">
    40                 <a href="${website}/arithmetic?state=toHome" style="text-decoration: none ">
    41                     <input type="button" value="返回" style=" 80px;height: 40px;border: none;background-color: skyblue;box-shadow: 2px 2px 2px #FFD700;border-radius: 5px;color: white;font-weight: 600;">
    42                 </a>
    43             </td>
    44         </tr>
    45     </table>
    46 </form>
    47 
    48 <script language="javascript" type="text/javascript">
    49     function checkform(){
    50         if(document.getElementById('nu').value.length==0){
    51             alert('您还没有选择文件!');
    52             document.getElementById('nu').focus();
    53             return false;
    54         }
    55     }
    56 </script>
    57 </body>
    58 </html>

    8. 界面模块与计算模块的对接

      项目中前后端交互采用servlet实现。当用户发送一个请求,会进入到相应的servlet方法中,在servlet方法中获取对应的参数,调用接口中的方法,并对客户端做出响应。为了提高代码的安全性,jsp页面放在了web-INF目录下面,因此只有通过servlet才能访问到页面。servlet中包含了上传文件,下载文件,读取文件,生成题目,答题以及各个页面之间跳转的方法。其中,在生成题目的方法中会调用CreateArithmetic的接口,在答题的方法中会调用Calculation的接口。

      这里展示部分代码:

     1 /**
     2      *读取文件内容
     3      * @param request
     4      * @param response
     5      * @throws ServletException
     6      */
     7     public void read(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
     8 
     9         RequestDispatcher rd = null;
    10         response.setContentType("text/html");
    11         response.setCharacterEncoding("GBK");
    12         PrintWriter out=response.getWriter();
    13         String realPath= request.getParameter("path");
    14         List<String> list = new ArrayList<>();
    15         File file=new File(realPath);
    16         if(file.exists()){
    17             FileReader reader=new FileReader(file);
    18             BufferedReader bufferedReader=new BufferedReader(reader);
    19             String line =null;
    20             while((line=bufferedReader.readLine())!=null)
    21             {
    22                 list.add(line);
    23             }
    24             reader.close();
    25             bufferedReader.close();
    26         }else{
    27             out.print("file is not exist!");
    28             out.close();
    29         }
    30         request.getSession().setAttribute("list",list);
    31         System.out.println();
    32         request.setAttribute("msg1","题目上传成功,点击这里开始答题!");
    33         rd = request.getRequestDispatcher(WebContents.UPLOAD);
    34         rd.forward(request,response);
    35     }

      实现的功能:

    生成题目  上传题目

    答题  详情显示

    9.描述结对的过程

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

    讨论照片展示:

      

    10.结对编程的优缺点

      结对编程优点:

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

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

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

      结对编程缺点:

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

      马玲优点:

      1.编程能力强,认真

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

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

      马玲缺点:

      1.不够细心,经常会忽略一些细节,考虑不够全面

      王雪优点:

      1.遇到bug有耐心解决

      2.注重细节,努力

      3.态度积极,乐于学习

      王雪缺点:

      1.编程经验不足,对程序把握不够

    11.实际花费的时间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

     12.总结与修改

        在后面老师给的时间段里,我们两个人在之前的代码基础上修改了一些功能。在效能分析这一模块中,我们做了更近一步的完善,在博客中做了相应的补充。在项目功能这一模块,我们加入了用户登录和注册,实现了用户可以查看自己答题记录的功能。但我们的项目中也存在很多不足,对于前端展示页面,由于我们这方面知识的欠缺,所以完成的并不是很好,以后的作业中我们会不断完善,改进自己的不足。

       增加的功能展示:

      

       

  • 相关阅读:
    20160729noip模拟赛zld
    20160728noip模拟赛zld
    20160727noip模拟赛zld
    20160725noip模拟赛“Paodekuai” alexandrali
    20160723数据结构节alexandrali
    20160722noip模拟赛alexandrali
    洛谷 [P2594] 染色游戏
    洛谷 [P3480] KAM-Pebbles
    UVA 1378 A Funny Stone Game
    SPOJ 4060 A game with probability
  • 原文地址:https://www.cnblogs.com/malings/p/8751840.html
Copyright © 2020-2023  润新知