软件工程网络15结对编程作业

201521123036  曾艺佳 博客
201521123039  王兴    博客
码云地址:四则运算
选择改进的代码地址:
个人博客地址2:http://www.cnblogs.com/belong033
源代码:https://coding.net/u/Belong033/p/java-third/git


需求分析:针对现有代码的改进分析,新开发功能的分析。

检查大部分主要类之间的关系,画出类图

此博主博客里的界面程序的类图

给出的代码的类图

浏览所有代码考虑代码质量和测试覆盖率

这次我们所用到的代码包括老师给的控制台的代码,还有博主的一份较完整的GUI的代码,所以两者相结合,保留并修改原来的方法。
原先的覆盖率

确定当前设计的一个弱点,通过重构,确保在这个地方已有测试覆盖并保证重构没有改变已有的功能

当前设计只能有一个操作符,随机式子的生成只有两位数,比较简单。整数与分数的运算无法实现。

好的测试是重构的根本。检查已有代码的测试,看测试用例是否足够覆盖原代码,如果不足,请添加测试用例

测试用例不足够覆盖源代码,增加

第一位为负数的情况,例如:

整数和分数相加减的情况,例如:

修改代码后,检查代码覆盖,看单元测试是否需要修改?测试用例是否需要增加?



程序设计:针对新开发功能做设计,建议使用思维导图。

功能改进与扩展

生成多个操作符的算式,因为原先的函数有两个数的加减乘除函数,所以增加运算符是在原来的基础上再建函数调用,对模块结构没有多大改变。
增加括号操作符。



代码展示:展示每个功能的核心代码。

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
原文地址:https://www.cnblogs.com/zyjjj/p/8617513.html