201521123036 曾艺佳 博客
201521123039 王兴 博客
码云地址:四则运算
选择改进的代码地址:
个人博客地址2:http://www.cnblogs.com/belong033
源代码:https://coding.net/u/Belong033/p/java-third/git
需求分析:针对现有代码的改进分析,新开发功能的分析。
检查大部分主要类之间的关系,画出类图
此博主博客里的界面程序的类图
给出的代码的类图
浏览所有代码考虑代码质量和测试覆盖率
这次我们所用到的代码包括老师给的控制台的代码,还有博主的一份较完整的GUI的代码,所以两者相结合,保留并修改原来的方法。
原先的覆盖率
确定当前设计的一个弱点,通过重构,确保在这个地方已有测试覆盖并保证重构没有改变已有的功能
当前设计只能有一个操作符,随机式子的生成只有两位数,比较简单。整数与分数的运算无法实现。
好的测试是重构的根本。检查已有代码的测试,看测试用例是否足够覆盖原代码,如果不足,请添加测试用例
测试用例不足够覆盖源代码,增加
第一位为负数的情况,例如:
整数和分数相加减的情况,例如:
修改代码后,检查代码覆盖,看单元测试是否需要修改?测试用例是否需要增加?
- 参考
- 重构-靠谱程序员的必备技能:https://mp.weixin.qq.com/s/23a8BY_fP168GWLrGLJzrw
- JUnit单元测试:http://www.cnblogs.com/happyzm/p/6482886.html
- Java覆盖率统计:http://www.cnblogs.com/happyzm/p/6530384.html
程序设计:针对新开发功能做设计,建议使用思维导图。
功能改进与扩展
生成多个操作符的算式,因为原先的函数有两个数的加减乘除函数,所以增加运算符是在原来的基础上再建函数调用,对模块结构没有多大改变。
增加括号操作符。
代码展示:展示每个功能的核心代码。
public String ca(String s){
String a,na=null;
while(s.indexOf("(")>-1){
int inner = s.lastIndexOf("(");
a = s.substring(inner+1, s.indexOf(")",inner));
s=s.replace("("+a+")", cal(a));
}
return cal(s);
}
public int minIndex(String s,int i){ //乘或除计算后位数的位置
int min=0;
if(s.charAt(i)==45) i=i+1;
List<Integer> index = new ArrayList<Integer>();
if(s.indexOf("+", i)>0) index.add(s.indexOf("+", i));
if(s.indexOf("-", i)>0) index.add(s.indexOf("-", i));
if(s.indexOf("*", i)>0) index.add(s.indexOf("*", i));
if(s.indexOf("÷", i)>0) index.add(s.indexOf("÷", i));
if(index.isEmpty()) min=s.length()-1;
else min= Collections.min(index)-1;
return min;
}
public String cal(String s){
while(s.contains("*")||s.contains("÷")){ //替换乘除运算
int b,x=0;
if(s.indexOf("*")<0) b=s.indexOf("÷");
else if(s.indexOf("÷")<0) b=s.indexOf("*");
else b=s.indexOf("*")>s.indexOf("÷")?s.indexOf("÷"):s.indexOf("*");
if(s.substring(0,b).contains("+")||s.substring(0,b).contains("-")){
x=(s.lastIndexOf("+",b)>s.lastIndexOf("-", b)?s.lastIndexOf("+",b):s.lastIndexOf("-", b))+1; //上一位
}
int y=minIndex(s,b+1); //下一位
s=s.replace(s.substring(x,y+1), calc(s.substring(x,y+1)));
}
if(s.contains("+-")) s=s.replaceAll("[+][-]", "-");
if(s.contains("--")) s=s.replaceAll("--", "+");
while(!(s.startsWith("-") &&s.substring(1).indexOf("+")==-1&&s.substring(1).indexOf("-")==-1)){
//计算单纯加减法
String p=null;
String[] authors = s.split("[+]");
if(s.indexOf("+")<-1) authors[0]=s;
for (int i = 0; i < authors.length; i++) {
int a=0;
if(authors[i].contains("-")){
if(authors[i].startsWith("-")) {a=1;authors[i]=authors[i].substring(1);}
String[] newa = authors[i].split("-");
if(a==1) s="-"+calc(newa[0]+"+"+newa[1]); //-1-2情况
else s=calc(newa[0]+"-"+newa[1]);
for (int j = 2; j < newa.length; j++) {
if(s.contains("-")) s="-"+calc(s+"+"+newa[j]); //被减数为负数
else s=calc(s+"-"+newa[j]);
}
//if(s.contains("-")) {t=1;p=s;s="0";}
authors[i]=s;
}
}
if(authors.length>1){ //计算单纯加法
for (int i = 1; i < authors.length; i++) {
if(authors[i].contains("-")&&!authors[0].contains("-")) authors[0]=calc(authors[0]+"-"+authors[i].substring(1));
else if(authors[0].contains("-")&&!authors[1].contains("-")) authors[0]=calc(authors[1]+"-"+authors[0].substring(1));
else authors[0]=calc(authors[0]+"+"+authors[i]);
}
s=authors[0];
}
else {s=authors[0];
break;}
}
return s;
}
生成表达式:
public static String createAc(int operator_no) {
// 表达式
String ac = "";
String[] operator=new String[]{"+","-","*","÷"};
Random rand = new Random();
// 括号标记数
int bracket = 0;
// 括号对数
int bracket_no = 0;
for (int i = 1; i <= operator_no + 1; i++) {
// 判断是否存在"(",若存在,判断是否加上")",bracket=0时不加
if (bracket_no != 0 && (bracket = rand.nextInt(3)) != 0
&& ac.charAt(ac.length() - 1) != '(') {
ac = ac + createNum() + ")" + operator[rand.nextInt(4)];
bracket_no--;
}
// 最后生成的数不加括号
else if (i != operator_no + 1) {
// 判断是否生成括号
bracket = rand.nextInt(3);
// backet=0时,不生成括号
if (bracket == 0) {
ac = ac + createNum() + operator[rand.nextInt(4)];
}
// bracket=1时,在表达式前方生成括号,bracket_no+1
else if (bracket == 1) {
ac = "(" + ac + createNum() +operator[rand.nextInt(4)];
bracket_no++;
}
// bracket=2时,在表达式后后方加括号,bracket_no+1
else {
ac = ac + "(" + createNum() + operator[rand.nextInt(4)];
bracket_no++;
}
} else {
ac = ac + createNum() + operator[rand.nextInt(4)];
}
}
// 是否存在未配对的"(",存在就补上
if (bracket_no != 0) {
ac = ac.substring(0, ac.length() - 1);
for (int i = 0; i < bracket_no; bracket_no--) {
ac = ac + ")";
}
}
// 去除多余的运算符
else {
ac = ac.substring(0, ac.length() - 1);
}
return ac;
}
public static String createNum() {
String num="";
Random rand = new Random();
int flag = rand.nextInt(2);
if(flag==0){
num=String.valueOf(rand.nextInt(30)+1);
}
else{
num=createFraction();
}
return num;
}
public static String createFraction(){ //随机组成真分母 博客
Random rand = new Random();
int[] fraction=new int[2];
int fraction1 = rand.nextInt(8)+1;//避免分子出现零
int fraction2 = rand.nextInt(8)+1;//避免分母出现零
if(fraction1==fraction2){ //避免出现分子分母相同
return createFraction();
}else{
if(fraction1<fraction2){ //避免出现假分数
fraction[0]=fraction1;
fraction[1]=fraction2;
}else{
fraction[0]=fraction2;
fraction[1]=fraction1;
}
return fraction[0]+"/"+fraction[1];
}
}
程序运行:程序运行及每个功能的使用截图。
新功能(多个操作符,增加括号):
回归测试
在开发新功能时避免损坏旧的功能,以确保新的功能不与原有功能冲突
语言转换:
计时:
效能分析
- 参考
小结感受:结对编程真的能够带来1+1>2的效果吗?通过这次结对编程,请谈谈你的感受和体会。
感受:可能比之前好一点吧。结对编程比较能找出自己编程时忽略的细节,独自编程时自己检查很容易跟着之前编程的思路走,所以不容易发现漏洞。
结对编程时遇到了问题,两个人可以一起去找解决办法,事半功倍。通过两人的沟通默契会逐渐提升。
但是有时时间安排上可能还有点问题。
描述结对的过程,提供非摆拍的两人在讨论、细化和编程时的结对照片。
码云提交记录
要求必须增量式开发-提交到码云地址,码云上要能看到多次commit的记录,同时必须有两个人各自的commit记录。
因为队友的eclipse多次尝试连接不了远程仓库,所以都是同一账号提交
此次结对作业的PSP
在开始实现程序之前,请使用以下PSP表格,在第3列填上自己对每个环节的估计时间(单位:分钟)
在做每个环节的过程中,请在第4列填上对应环节的实际消耗时间(单位:分钟)
PSP2.1 | 个人开发流程 | 预估耗费时间(分钟) | 实际耗费时间(分钟) |
---|---|---|---|
Planning | 计划 | 15 | 10 |
Estimate | 明确需求和其他相关因素,估计每个阶段的时间成本 | 8 | 5 |
Development | 开发 | 150 | 188 |
Analysis | 需求分析 (包括学习新技术) | 6 | 10 |
Design Spec | 生成设计文档 | 10 | 0 |
Design Review | 设计复审 | 8 | 10 |
Coding Standard | 代码规范 | 3 | 3 |
Design | 具体设计 | 10 | 12 |
Coding | 具体编码 | 36 | 21 |
Code Review | 代码复审 | 15 | 11 |
Test | 测试(自我测试,修改代码,提交修改) | 15 | 20 |
Reporting | 报告 | 10 | 8 |
· | 测试报告 | 3 | 2 |
· | 计算工作量 | 10 | 6 |
· | 并提出过程改进计划 | 10 | 15 |