结对作业(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类测试代码如下:
import org.junit.Test; import java.util.ArrayList;
import java.util.List; 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"};//缺少参数 List<String[]> list = new ArrayList();
list.add(args1);
list.add(args2);
list.add(args3);
list.add(args4);
list.add(args5);
list.add(args6);
list.add(args7);
list.add(args8); for (int i = list.size() - 1; i >= 0; i--)
Command.main(list.get(i));
} }
代码覆盖率如下:
接口类测试覆盖率:
Command类的测试覆盖率:
在单元测试中,每个类对应一个测试类,测试类中每个测试方法对应一个方法。构造测试数据时,根据方法中每个分支对应的情况,设置相应的参数,确保测试会进入到每一个分支,达到测试的目的。
6.计算模块部分异常处理说明
在计算模块中,用户如果传入不合法参数,程序会捕获异常,显示异常类型并提示错误参数。由于我们的项目是用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 createNumber() throws Exception {
System.out.println(createArithmetic.CreateNumber(4,50,60));
}
当题目数量不在合理范围时:
@Test
public void createFile() throws Exception {
System.out.println(createArithmetic.createFile(-9,true,true,10,1000,4)); }
7. 界面模块的详细设计过程
界面模块我们采用jsp结合js完成前端页面的设计,通过servlet完成前后端的交互。
根据程序所要实现的功能,我们将设计四个页面用来展示并实现这些功能:
1)home.jsp:主页。有生成题目和上传题目两个按钮,点击不同的按钮进入不同页面,进行相应操作
2)create_arithmetic.jsp:生成题目页面。页面通过form表单,获取用户输入的参数,生成相应题目,并可供用户下载生成的题目。页面显示每个参数的输入框,提示参数范围,并对必填输入框进行判空;有生成题目和返回(返回主页)两个按钮。
3)upload _arithmetic.jsp:上传文件页面。用户选择文件上传,上传成功之后点击答题,进入答题页面开始答题。页面显示输入框,用户可选择文件,实现输入框的判空以及文件格式的判断;有上传和返回(返回主页)两个按钮。
4)do _arithmetic.jsp:答题页面。用户在这个页面可以进行答题。页面会显示题目总数和当前题目序号;显示题目,用户做答;页面有下一题,结束,返回(返回主页)三个按钮,用户可以选择继续答题或结束答题;当做到最后一题时,隐藏下一题的按钮。结束答题之后,页面会显示用户答题数目,答对的题目数量以及花费时间。
答题页面代码的展示:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 芋头
Date: 2018/4/2
Time: 20:49
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<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>
8. 界面模块与计算模块的对接
项目中前后端交互采用servlet实现。当用户发送一个请求,会进入到相应的servlet方法中,在servlet方法中获取对应的参数,调用接口中的方法,并对客户端做出响应。为了提高代码的安全性,jsp页面放在了web-INF目录下面,因此只有通过servlet才能访问到页面。servlet中包含了上传文件,下载文件,读取文件,生成题目,答题以及各个页面之间跳转的方法。其中,在生成题目的方法中会调用CreateArithmetic的接口,在答题的方法中会调用Calculation的接口。
这里展示部分代码:
/**
*读取文件内容
* @param request
* @param response
* @throws ServletException
*/
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);
}
实现的功能:
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.总结与修改
在后面老师给的时间段里,我们两个人在之前的代码基础上修改了一些功能。在效能分析这一模块中,我们做了更近一步的完善,在博客中做了相应的补充。在项目功能这一模块,我们加入了用户登录和注册,实现了用户可以查看自己答题记录的功能。但我们的项目中也存在很多不足,对于前端展示页面,由于我们这方面知识的欠缺,所以完成的并不是很好,以后的作业中我们会不断完善,改进自己的不足。
增加的功能展示:
结对作业(web)的更多相关文章
- 结对作业——web四则运算
目录: 一.Coding.net项目地址 二.PSP 三.接口设计 四.接口实现 五.性能分析 六.单元测试 七.异常处理 八.模块设计 九.模块对接 十.结对 十一.思考 十二.PSP 网站:htt ...
- 结对作业1----基于flask框架的四则运算生成器
011.012结对作业 coding地址:https://coding.net/u/nikochan/p/2nd_SE/git 一.作业描述 由于上次作业我没有按时完成,而且庞伊凡同学编程能力超棒,所 ...
- 软件工程第三次作业-结对作业NO.1
第一次结对作业 结对人员: 潘伟靖 170320077 张 松 170320079 方案分析 我们对所供的资料进行分析,如下: 从提供的资料可以看出,需要解决的问题以及满足的需求主要有两类目标用户,各 ...
- 第6次结对作业--郑锦伟&古维城
第6次结对作业 在线英语学习平台客户端原型 1.结对成员 郑锦伟 2015034643034 古维城 2015034643033 2.原型设计工具实现-Photoshop 3.需求分析 使用NABCD ...
- [2019BUAA软件工程]结对作业
Tips Link 作业链接 [2019BUAA软件工程]结对作业 GitHub地址 WordChain PSP表格 psp2.1 预估耗时(分钟) 实际耗时(分钟) Planning 计划 60 ...
- [BUAA软工]第一次结对作业
[BUAA软工]结对作业 本次作业所属课程: 2019BUAA软件工程 本次作业要求: 结对项目 我在本课程的目标: 熟悉结对合作,为团队合作打下基础 本次作业的帮助:理解一个c++ 项目的开发历程 ...
- 软工实践——结对作业2【wordCount进阶需求】
附录: 队友的博客链接 本次作业的博客链接 同名仓库项目地址 一.具体分工 我负责撰写爬虫爬取信息以及代码整合测试,队友子恒负责写词组词频统计功能的代码. 二.PSP表格 PSP2.1 Persona ...
- 第四,五周——Java编写的电梯模拟系统(结对作业)
作业代码:https://coding.net/u/liyi175/p/Dianti/git 伙伴成员:石开洪 http://www.cnblogs.com/shikaihong/(博客) 这次的作业 ...
- 结对作业——随机生成四则运算(Core 第7组)
结对作业 ——随机生成四则运算(core第7组) 吕佳玲 PB16060145 涂涵越 PB16060282 GITHUB地址 https://github.com/hytu99/homework_2 ...
- 结对作业(1.0版)(bug1已修复)
import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing ...
随机推荐
- php判断是否为时间戳
判断值是否为时间戳 function is_timestamp($timestamp) { if(strtotime(date('m-d-Y H:i:s',$timestamp)) === $t ...
- 运行第一个ruby程序
0x00 安装 首先需要安装一个ruby的环境,ruby分为win.linux.macOS版本.不用系统安装方法略有差异,不在这进行讲解. 0x01 运行第一个ruby程序 我这里是win环境,打开命 ...
- c语言数组放在main函数里面和外面的区别
最近a算法题的时候碰到一道题:一个数列前三项都为1,之后每项的值等于前三项之和,求第20193024项的最后4位数字.一开始写的代码如下: 结果一直爆 Terminated due to signal ...
- Caffe中Layer注册机制
Caffe内部维护一个注册表用于查找特定Layer对应的工厂函数(Layer Factory的设计用到了设计模式里的工厂模式).Caffe的Layer注册表是一组键值对(key, value)( La ...
- 25-[jQuery]-事件
重点:jQuery事件绑定on().bind()与delegate() 方法详解 1.jquery的事件 <!DOCTYPE html> <html lang="en&qu ...
- 05-session-会话跟踪技术
1.session简介 Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie Session是服务器端技 ...
- 【BZOJ1046】[HAOI2007]上升序列
[BZOJ1046][HAOI2007]上升序列 题面 bzoj 洛谷 题解 \(dp\)完之后随便搞一下即可,注意不要看错题 代码 #include <iostream> #includ ...
- 回顾下TCP/IP协议
首先要知道什么是TCP/IP协议,从字面意思来看TCP是“Transmission Control Protocol”的缩写,也就是传输控制协议.IP是“Internet Protocol”的缩写,即 ...
- ubuntu下Open vSwitch安装
ubuntu下Open vSwitch安装 有关Open vSwitch的安装,网上有各种的教程资料,但一些已经过时,按照网上的教程,花费了大量时间,都没能安装成功.于是,通过查阅官方安装教程以及综合 ...
- 1042 Shuffling Machine
一.题目描述 Shuffling is a procedure used to randomize a deck of playing cards. Because standard shufflin ...