作业源代码地址:https://git.coding.net/mal123/arithmetic.git
网页版测试地址:http://47.93.197.5:8080/mal_war_exploded/arithmetic?state=toHome
结对成员:马玲 2016012054 ;王雪 2016012013
1.开始实现程序之前,我们对 的
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 在项目中的应用:
1.)Information Hiding:信息隐藏。
信息隐藏是程序设计过程中的一种隔离原则,可以防止用户接触到一个类的某些部分。一个程序模块可以将它的信息隐藏起来,对外仅仅展现出一种接口。当这个模块的具体实现发生改变时,只要保证它的接口不发生变化,则就算不修改模块外的其他代码,程序依旧可以正确执行。对于面向对象的程序设计而言,信息隐藏是一种重要的软件开发手段,它与对象的封装(encapsulation)和模块化(modularity)密切相关,每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能。主要是封装完成之后,后面做项目用起来会很轻松,并且节约工作量和时间,减少错误以及避免代码的臃肿影响代码的可读性。
在这次的结对项目中,对于用户而言,只需要设置自己的参数,得到相应的题目,用户并不关心程序是怎么生成题目的,他只是调用这个方法,所以可以将生成题目这一模块设计成接口,计算这一模块也是同样的道理。在模块的优化过程中,保证接口不变,我们只需要修改接口的实现,并不需要对其他地方进行修改,程序也可以正常运行。
2.)
各个方法之间的关系:
计算题目模块的接口:
本次项目开发,我们采用的是我之前个人项目的代码,我们将之前生成题目和计算的功能分开,仍旧采用之前的算法生成题目,所以具体流程图就不再多做展示了。在之前算法的基础上加入上下界的限制,以及选择乘除法和括号的功能,具体代码写在接口的实现里。在业务逻辑层,获取用户的请求,调用对应的接口,做出响应。由于此次项目要求只需要生成符合要求的题目并不要求算出答案,计算也是对已有的题目直接进行计算,所以在计算题目这一功能的实现我们采用的是eval()函数,直接用于计算用户上传的题目。
4.
项目总体分析图:
CPU分析图:
性能分析:
在项目中消耗最大的函数isParenthesis方法,由于限制条件太多,所以当题目数量过大时,函数消耗会很大。在分析过程中发现在运行过程中,没有对循环时产生的list清空,所以浪费很大空间,针对这些问题,我们也对代码进行了修改。
5.
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.
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.
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 }
结对编程优点:
1.结对编程就是两个程序员互相审查的过程,在编程过程中能够尽早发现问题并解决问题,提高了编程效率。
2.编程过程中遇到瓶颈两个人相互鼓励,极大的提高了编程的积极性。
3.两个人在编程过程中不断磨合,相互学习,使双方的代码能力得到了一定程度上的增强,同时也有了合作意识。
结对编程缺点:
1.一个人独立钻研的时候,两个人思路会不同,编程方法也不同,需要时间来抉择用哪一个方法,需要磨合时间
马玲优点:
1.编程能力强,认真
2.对于模块独立化有独特的见解
3.逻辑思维能力强,编程严谨
马玲缺点:
1.不够细心,经常会忽略一些细节,考虑不够全面
王雪优点:
1.遇到bug有耐心解决
2.注重细节,努力
3.态度积极,乐于学习
王雪缺点:
1.编程经验不足,对程序把握不够
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 |