结对项目博客
一、项目地址:
URL测试地址:http://47.93.197.5:8080/RCalculator/index.jsp
coding.net仓库地址:https://git.coding.net/aspirinone/RCalculator.git
结对伙伴:甘彩娈
二、预计各模块开发时间(PSP)
PSP |
任务内容 |
计划时间(min) |
完成时间(min) |
Planning |
计划 |
60 |
120 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
60 |
|
Development |
开发 |
2880 |
2880 |
Analysis |
需求分析 |
|
|
Design Spec |
生成文档 |
|
|
Design Review |
设计复审 |
|
|
Coding Standard |
代码规范 |
150 |
|
Design |
具体设计 |
200 |
200 |
Coding |
具体编码 |
1800 |
1800 |
Code Review |
代码复审 |
370 |
370 |
Test |
测试 |
120 |
120 |
Reporting |
报告 |
180 |
180 |
Test Report |
测试报告 |
120 |
120 |
Size Measurement |
计算工作量 |
20 |
20 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
40 |
40 |
三、接口设计
通过看书和查阅资料,我学习到:
信息隐藏(Information Hiding):信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。为什么要隐藏?一是为了隐藏复杂度,这样你就不用再去应付他,除非你要特别关注的时候;二是为了隐藏变化源,这样当变化发生时,其影响就能被限制在局部范围内。复杂度的根源包括复杂的数据类型、文件结构等。
接口设计(Interface Design):接口,在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口设计需要考虑哪些方面:1.接口的命名 2.请求参数 3.支持的协议 4.TPS、并发数、响应时长 5.数据存储、DB选型、缓存选型 6.是否需要依赖于第三方 7.接口是否拆分 8.接口是否需要幂等 9.防刷 10.接口限流、降级 11.负载均衡器支持 12.如何部署 13.是否需要服务治理 14.是否存在单点 15.接口是否用资源包、预加载还是内置 16.是否需要本地缓存 17.是否需要分布式缓存、缓存穿透怎么办 18.是否需要白名单
松耦合(Loose Coupling):很多复杂问题的解决都是通过增加中间层来实现的。系统集成、点对点的对接,系统间相互的依赖性太大,增加一个中间层实现松耦合性。开发语言上,想让对象与对象间松耦合,通过增加抽象类或者接口来做到。松耦合的目标是最小化依赖,但要付出使系统更加复杂的代价。
松耦合架构:
四、类与函数
类:
Command.java(核心):用于命令行测试生成运算式。
MakeText.java 和 ResultComeOut.java 相互调用用于生成符合的运算式,主要用于两个地方,命令行测试和实际网页生成运算式。
GetAnswer.java:生成算式答案。
函数:
Command.java中用到的函数:主函数(用于分析输入的参数),并调用了MakeText.java 和ResultComeOut.java
MakeText.java中用到的函数:
private static String doText( int lower , int upper , int operatorCount , String isMultiply , String isBracket) 通过参数解析、Random类形成随机数以及随机运算符形成符合参数要求的运算式的验证,并且调用ResultComeOut.java的方法判断运算式是否符合要求。
creat ( int expressionNum , int lower , int upper , int operatorCount , String isMultiply, String isBracket) 把创建的打印输出流赋给系统。
public static int [ ] index ( int n , int m )
ResultComeOut.java中用到的函数:
public int jisuan ( String ex , int lower , int upper ) 运用调度场算法和逆波兰表达式,用栈进行运算。
int calculate ( int a , int b , String tmp , int lower ,int upper ) 处理加减运算并排除与题目条件不符的式子。
五、接口部分的性能改进与性能分析图
记录了在改进计算模块性能上所花费的时间,简化代码的冗杂度,尽量模块化处理,其性能分析图如下:
六、单元测试及测试覆盖率截图
为了充分测试ResultComeOut.java,使用单元测试Test_ResultComeOut.java:
七、异常处理说明
前端部分:
限定只能输入正整数:判断是否符合正则表达式 ^\d+$ 。如果不符合,则报错。
限定只能输入小于10000的正整数:判断是否符合正则表达式 ^(?!00)(?:[0-9]{1,3}|1000)$ 。如果不符合,则报错。
默认是否包含乘除号和括号为否:<input type="radio" cheked="">,目的是为了防止空指针异常。
$("#num1").blur(function(){ var reg = /^(?!00)(?:[0-9]{1,3}|1000)$/; var regExp = new RegExp(reg); if(!regExp.test(this.value)||this.value==""){ var tip = "*小于1万的正整数"; $("#a").html(tip); } else{ $("#a").html(""); } })
后端部分:
在 MakeText.java 部分需要将生成的运算式打印成.txt文件:
try { PrintStream ps = new PrintStream("result.txt","UTF-8"); System.setOut(ps); ArrayList<String> ex = mt.create(n, lower, upper, o, c, b); for(String es:ex){ System.out.println(es); } } catch (Exception e) { // TODO: handle exception System.out.println("File Error!"); }
在Command.java中有大量的异常处理,提示参数不合法问题,具体形式以System.out.println(问题内容)呈现。
if (args[i].equals("-n")) { ifn = true; try { n = Integer.parseInt(args[i + 1]); } catch (Exception e) { // TODO: handle exception System.out.println("Please input interger betweeen 1 and 10000"); } if (n <= 0 || n > 10000) { ifrun = false; System.out.println("Please input interger betweeen 1 and 10000"); } if(i < args.length-1){ i++; }else{ System.out.println("after -n you need to input a interger, please try again"); } }
八、界面模块的详细设计过程:
项目含六个页面index.jsp、 problem.jsp、zuoti.jsp、grade.jsp、bgrade.jsp和login.jsp;所有页面均实现了多语言环境,可以中英文切换。index.html用于定制题目,并生成题目的txt文件,problem.html使用用户上传的文件,在页面上做题,给出答题时间与答题正确题数。index.jsp用于定制题目,可跳转至zuoti.jsp进行答题,用户可以看见答题时间与答题正确题数。problem.jsp使用用户上传的文件,在页面上做题,给出答题时间与答题正确题数。
login.jsp是用户登录界面;grade.jsp是显示所有用户的最好成绩排名;bgrade.jsp显示用户的做题记录。
1.前端页面组成
2.登陆/注册界面
3.首页:定制出题要求、上传计算文件
4.定制题目后出现答题界面
5.提交答案后用 js 局部刷新提示答题用时和正确率
判断正确率是通过对比用户答案的数组,与后台传到前台的答案数组对比,并显示出来。
6.点击右侧头像,出项“历史成绩”,可以显示所有用户的最好成绩
定时器的使用:
<script type="text/javascript"> var c=0 var t var r window.onload=timedCount() function timedCount() { document.getElementById('txt').value = c c=c+1 t=setTimeout("timedCount()",1000) } </script>
后端的界面设计:
九、界面模块与计算模块的对接
index.jsp:是用户输入参数与上传文档的界面。后台获取参数并运用 MakeText.java 中的doText() 解析参数,生成符合要求的式子后,用creat()方法把创建的打印输出流赋给系统。
problem.jsp:是用户使用上传的文档显示题目,并答题的界面。使用GetAnswer.java 中 的方法给出答案。前段将用户输入的值作为一个数组,与后台上传的答案数组进行比较,最后打印出用户做对的题目数量。
$("#show").click(function(){ var txt=$("#txt").val(); var answer=document.getElementByClassName("answer"); var ture=document.getElementByClassName("ture"); var but=document.getElementById("show") var yes=0; var no=0 for(i=0;i<answer.length;i++){ if(answer[i].value==ture[i].value){ yes++; } else{ no++; } } var txt1='<input style="border:none;outline:medium;box-shadow:0px 0px 0px;width:50px;">'+yes+'</input>'; $("#myDiv").hide(); $("#top").html('<p>您做题用时为'+txt+'秒<br>做对'+txt1+'题</p>'); })
十一、结对编程的优缺点,结对成员评价
结对编程优点:
1.在合作的过程中如果遇到问题,两个人一起解决会提高效率,更快发现解决问题的方法。
2.结对编程中可以互相鼓励,互相督促,不容易产生懈怠。
3.结对编程中可以互相学习彼此擅长的地方,有利于自身代码水平的提高。
4.结对编程有助于及时的代码复审。
结对编程的缺点:
1.结对编程要求两个人都有时间,这对两个人的时间协调有一定要求。
对结对队友的评价:
彩娈宝宝在做项目过程中很积极,从不懈怠;我们经常交流,每次都能听得进彼此的意见,合作得非常愉快;她在分工时从不偷懒,也不推脱任务;她遇到困难的时候能积极地去寻找方法,而不是烦躁和抱怨,她很有正能量。至于缺点,实在是没什么缺点了。
十二、各模块实际所用时间(PSP)
PSP |
任务内容 |
计划时间(min) |
完成时间(min) |
Planning |
计划 |
60 |
120 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
60 |
|
Development |
开发 |
2880 |
3000 |
Analysis |
需求分析 |
|
|
Design Spec |
生成文档 |
|
|
Design Review |
设计复审 |
|
|
Coding Standard |
代码规范 |
150 |
|
Design |
具体设计 |
200 |
200 |
Coding |
具体编码 |
1800 |
1920 |
Code Review |
代码复审 |
370 |
370 |
Test |
测试 |
120 |
120 |
Reporting |
报告 |
180 |
180 |
Test Report |
测试报告 |
120 |
120 |
Size Measurement |
计算工作量 |
20 |
20 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
40 |
40 |
十三、附加功能:中英文的切换、多用户的成绩记录
中文版
英文版:
韩文版:
记录所有用户中的最好成绩:
十三、总结
在不断改进代码的过程中,学到了很多新知识。结对编程也能督促我不断修正自己的代码,并纠正之前自己敲代码的一些陋习。总之,收获很多。