軟工網絡15結對編程練習

1、結對編程成員

201521123003
201521123005
html

2、題目要求:

一.現有代碼分析

(1)現有代碼來源java

本次結對編程,咱們選擇網絡14魏輝學長的程序代碼進行改進。
他的我的博客地址:http://www.cnblogs.com/weihui-01 ,他的源代碼:https://coding.net/u/weh/p/software-testing/git
(2)類圖
所選項目的類之間的關係以下:

(3)項目的不足
一、雖然項目有寫當被除數爲0的時候拋出異常,可是生成的題目就不可能存在這樣的狀況(下面會說到隨機題目樣式固定),異常代碼以下:git

package qq;

public class Yc extends Exception{
    public void Cs()
    {
        System.out.println("除數不爲0");
    }
}

二、隨機的低年級和高年級題目樣式固定
例如低年級隨機題目並計算結果代碼以下:程序員

char a[]={'+','-','×','÷'};
              int b=(int)(Math.random()*4);
              int c=(int)(Math.random()*100);
              int d=(int)(Math.random()*99+1);//排除了被除數爲0的狀況
              int f=(int)(Math.random()*100);
              if(a[b]==a[0])
              {
                  T2.setText(c+String.valueOf(a[b])+f+"/"+d);
                  sum=c+(float)f/d;
              }
              else if(a[b]==a[1])
              {
                  T2.setText(c+String.valueOf(a[b])+f+"/"+d);
                  sum=c-(float)f/d;
              }
              else if(a[b]==a[2])
              {
                  T2.setText(c+String.valueOf(a[b])+"("+f+"/"+d+")");
                  sum=c*((float)f/d);
              }
              else if(a[b]==a[3])
              {
                  T2.setText(c+String.valueOf(a[b])+"("+f+"/"+d+")");
                  sum=(float)c/((float)f/d);
              }

三、題目計時不合理
有關計時界面(拿低年級答題界面舉例):

運行時,作完一道題目後,按下題按鍵後並無中止計時,直到按開始鍵才結束計時
(5)邏輯泥球
一、低年級的三種語言隨機生成算式與計算答案的代碼是重複的代碼
二、高年級的三種語言隨機生成算式與計算答案的代碼是重複的代碼
(6)原項目中測試用例覆蓋

測試用例所測的功能是檢查四則運算計算答案的正確性編程

(7)原題目要求
http://www.cnblogs.com/happyzm/p/6472120.html
http://www.cnblogs.com/happyzm/p/6509116.html
http://www.cnblogs.com/happyzm/p/6558307.html數組

二、改進代碼相關內容

(1)完整代碼
改進代碼的碼雲地址:https://gitee.com/yangxueying/pair_programming

網絡

代碼規範:
app

(2)需求分析
一、已有功能
原有代碼實現多種語言功能

實現部分隨機生成運算
實現+、-、*、/計算
二、改進及添加
原有代碼沒有處理真分數計算的功能,沒有作到隨機題目的要求,增長括號操做符乘方,減小重複題目的功能
(3)設計分析

類圖:
dom

(4)代碼實現
1.支持括號優先級運算和乘方計算函數

package Function;
import java.util.Stack;
public class Result {
    private static Stack<String> num = new Stack<String>();//存後綴表達式
        private static Stack<String> sign = new Stack<String>();//存入符號
        private static Stack<Double> result = new Stack<Double>();//放結果
        public static void getGroup(String line){//講字符串轉換爲後綴表達式
            for(int i=0; i<line.length(); i++){
                char c = line.charAt(i);
                if((int)c>=48 && (int)c<=57){//當遇到數字的時候,判斷是否是多位數,而後在push進num
                    int j = i+1;
                    while(j<line.length() && (line.charAt(j)>=48 && line.charAt(j)<=57)){
                        j++;
                    }
                    num.push(line.substring(i, j));
                    i = j-1;
                }else if(c == '('){//遇到左括號直接存進num
                    sign.push(String.valueOf(c));
                }else if(c == ')'){//遇到右括號從sign中pop棧頂元素push到num知道遇到'(',而後再pop掉'('
                    while(!sign.peek().equals("(")){
                        num.push(sign.pop());
                    }
                    sign.pop();
                }else{
                    int n = 0;
                    if(!sign.empty()){//若是sign中沒有元素,直接令n = 0
                        n = getNum(sign.peek().charAt(0));
                    }
                    int m = getNum(c);
                    if(m >= n){//若是當前元素的運算級別比棧頂元素運算級別要高,就直接push進sign
                        sign.push(String.valueOf(c));
                    }else{
                        while(m < n){//若是當前運算運算級別比sign棧頂元素運算級別要低,就將sign棧頂元素pop而且push進num,知道不符合條件
                            num.push(sign.pop());//輸入例子2*3+6/3的時候,這裏一直報錯
                            if(!sign.empty()){
                                n = getNum(sign.peek().charAt(0));
                            }else{
                                n = 0;
                            }
                        }
                        sign.push(String.valueOf(c));
                    }
                }
            }
            while(!sign.empty()){
                num.push(sign.pop());
            }
        }
        private static int getNum(char c){
            int n = 0;
            switch(c){
                case '+':
                case '-':
                    n = 1;
                    break;
                case '*':
                case '^':
                case '/':
                    n = 2;
                    break;
            }
            return n;
        }    

     private static void getResult(){//講獲得的後綴表達式反轉遍歷,遇到數字就加入result,遇到符號就從result中取出兩個數進行運算而後將結果加入result
            Stack<String> t = new Stack<String>();
            while(!num.empty()){
                t.push(num.pop());
            }
            String str = t.pop();
            while(str != null){
                if(str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/")||str.equals("^")){
                    double n = result.pop();
                    double m = result.pop();
                    double num = 0;
                    if(str.equals("+")) num = m+n;
                    if(str.equals("-")) num = m-n;
                    if(str.equals("*")) num = m*n;
                    if(str.equals("/")) num = m/n;
                    if(str.equals("^")) num = Math.pow(m, n);
                   result.push(num);
                }else{
                    result.push(Double.parseDouble(str));
                }
                if(!t.empty()){
                    str = t.pop();
                }else{
                    str = null;
                }
            }
        }
        public Double getAnswer(String timu) {
            getGroup(timu);
            getResult();
        return result.peek();
    }
    
}

2.程序生成的算式不重複
(如下代碼可能沒法達到預期,咱們也明白就是交換+號兩邊的數,可是實現很複雜,後來聽了嘉廉同窗的方法,能夠用樹解決,以爲本身仍是要多努力啊!)

package Function;


import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;


public class GetChongFu {
    public static List<String> getChoufu(String timu)
    {
        List<String> chongti = new ArrayList<>();
        if(timu.contains("("))
        {
            
            List<String> num = new ArrayList<>();
            List<String> fuhao = new ArrayList<>();
            for(int i=0; i<timu.length(); i++)
            {
                char c = timu.charAt(i);
                if((int)c>=48 && (int)c<=57){//當遇到數字的時候,判斷是否是多位數,而後在push進num
                    int j = i+1;
                    while(j<timu.length() && (timu.charAt(j)>=48 && timu.charAt(j)<=57)){
                        j++;
                    }
                    num.add(timu.substring(i, j));
                }
                else
                {
                        fuhao.add(String.valueOf(c));
                        fuhao.add(String.valueOf(i));
                }

            }
            int cishu=0;
            int[] n;
            n=new int[3];
            for(int i=0;i<fuhao.size();i++)
            {
                if(fuhao.get(i).equals("+"))
                {
                    cishu++;
                    if(i==0)
                    {
                        String str=num.get(1)+"+"+num.get(0);
                        for(int j=2;j<fuhao.size();j++)
                        {
                            str=fuhao.get(j)+num.get(j+1);
                            if(fuhao.get(i).equals("+"))
                                j++;
                            
                        }
                        chongti.add(str);
                    }
                    if(cishu==2)
                    {
                        n[1]=Integer.valueOf(num.get(i+1));
                        chongti.add(timu.substring(0,n[0]-1)+"+"+timu.substring(n[1]+1,timu.length())+"+"+timu.substring(n[0]+1, n[1]-1));
                    }
                    if(cishu==3)
                    {
                        n[2]=Integer.valueOf(num.get(i+1));
                        chongti.add(timu.substring(0,n[1]-1)+"+"+timu.substring(n[2]+1,timu.length())+"+"+timu.substring(n[1]+1, n[2]-1));
                        chongti.add(timu.substring(0,n[0]-1)+"+"+timu.substring(n[2]+1,timu.length())+"+"+timu.substring(n[0]+1, n[2]-1));
                    }
                    n[0]=Integer.valueOf(num.get(i+1));
                    chongti.add(timu.substring(n[0]+1,timu.length())+"+"+timu.substring(0, n[0]-1));
                    
                }
                else 
                {
                    cishu=0;
                    if(fuhao.get(i).equals("*"))
                    {
                        if(i==0)
                        {
                            int d1=Integer.valueOf(num.get(i));
                            int d2=Integer.valueOf(num.get(i+1));
                            if(i+1<fuhao.size())
                            {                           
                            chongti.add(timu.substring(d1+1,d2-1)+"*"+timu.substring(0,d1-1)+timu.substring(d2, timu.length()));
                            }
                            else
                                chongti.add(timu.substring(d1+1,d2-1)+"*"+timu.substring(0,d1-1));
                        }
                        else if(i==(fuhao.size()-1))
                        {
                            int d3=Integer.valueOf(num.get(i-1));
                            String s=timu.substring(0,d3)+num.get(i/2+1)+"*"+num.get(i/2);
                            chongti.add(s);
                        }
                        else
                        {
                            int d1=Integer.valueOf(num.get(i-1));
                            int d2=Integer.valueOf(num.get(i));
                            int d3=Integer.valueOf(num.get(i+1));
                            String s=timu.substring(0,d1)+num.get(i/2+1)+"*"+num.get(i/2)+timu.substring(d3, timu.length());
                        }
                    }
                    
                    
                }
                i++;
            }
        }
    return chongti;
    }
}

3.隨機生成算式

package Function;

import java.util.Random;

public class RandomTimu {
    
    public static String DnjcalStringCreate(int r){
        char []c={'+','-','*','/'};//操做符數組
        Random random=new Random();
        StringBuffer str=new StringBuffer();
        int n= random.nextInt(3)+1;
        int num=random.nextInt(r-1)+1;
        str.append(num);
        for (int i = 0; i <n ; i++) {//在1到3範圍內隨機個數的運算符
            char c2=c[(int)(c.length* java.lang.Math.random())];//生成隨機操做符
            int num2=random.nextInt(r-1)+1;//生成大於0小於r的天然數
            str.append(c2);
            str.append(num2);
        }
        return str.toString();
        
    }
    public static String GnjcalStringCreate(int r){
        char []c={'+','-','*','/','^'};//操做符數組
        Random random=new Random();
        String timustr="";
        int n= random.nextInt(3)+1;
        int num=random.nextInt(r-1)+1;
        timustr=timustr+num;
        for (int i = 0; i <n ; i++) {//在1到3範圍內隨機個數的運算符
            char c2=c[(int)(c.length* java.lang.Math.random())];//生成隨機操做符
            int num2=random.nextInt(r-1);//生成大於0小於r的天然數
            if(c2=='^')
            {
                num2=random.nextInt(3);
            }
            if(c2=='/')
            {
                if(num2==0)
                num2=random.nextInt(r-1)+1;
            }
            timustr=timustr+c2;
            timustr=timustr+num2;
            if(random.nextInt(10)==0&&i<n-1)
            {
                timustr="("+timustr+")";
            }
        }
        return timustr;
    }
}

4.支持結果能夠存在分數

if(answer.contains("/"))
              {
                  
                  int length=answer.length();
                  for(int i=0; i<length; i++){
                    char c = answer.charAt(i);
                    if((int)c>=48 && (int)c<=57)
                    {//當遇到數字的時候,判斷是否是多位數
                        int j = i+1;
                        while(j<length && (answer.charAt(j)>=48 && answer.charAt(j)<=57)){
                            j++;
                        }
                        floatanswer=Float.parseFloat(answer.substring(i, j));
                        i = j-1;                        
                    }
                    else 
                    {
                        int j = i+1;
                        while(j<length && (answer.charAt(j)>=48 && answer.charAt(j)<=57)){
                            j++;
                        } 
                        float a1=Float.parseFloat(answer.substring(i+1, j));
                        floatanswer=floatanswer/a1;
                        break;
                    }                   
                   }
                  answer=String.valueOf(floatanswer);
                  if(Float.parseFloat(str)-floatanswer<0.00001)
                  {
                      T4.setText("恭喜你!答對了!");
                      dadui++;
                      T5.setText(String.valueOf(dadui));
                  }
                  else
                  {
                      T4.setText("真遺憾!答錯了!正確答案是"+Float.parseFloat(str));
                      dacuo++;
                      T6.setText(String.valueOf(dacuo));
                  }
              }

(5)迴歸測試的用例

package Function;

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class ResultTest {

    @Before
    public void setUp() throws Exception {
    }
    @Test
    public void testGetAnswer() {
        //原項目測試用例
        assertEquals(3.0, Result.getAnswer("1+4/2"),0.0);
        assertEquals(0.0, Result.getAnswer("1-1/1"),0.0);
        assertEquals(1.0, Result.getAnswer("1*1/1"),0.0);
        assertEquals(1.0, Result.getAnswer("1/1/1"),0.0);
        assertEquals(3.0, Result.getAnswer("1+1/1+1/1"),0.0);
        assertEquals(1.0, Result.getAnswer("1+1/1-1/1"),0.0);
        
        //新增功能測試用例
        assertEquals(6.0, Result.getAnswer("2*3"),0.0);
        assertEquals(-1, Result.getAnswer("2-3"),0.0);
        assertEquals(0.67, Result.getAnswer("2/3"),0.01);
        assertEquals(8.0, Result.getAnswer("2^3"),0.0);
        assertEquals(14.0, Result.getAnswer("2+3*4"),0.0);
        assertEquals(4.0, Result.getAnswer("2+3+(5-6)"),0.0);
        assertEquals(25.0, Result.getAnswer("(2+3)^2"),0.0);
        assertEquals(15.0, Result.getAnswer("((2+3)^2+5)/2"),0.0);
    }

}

(6)項目覆蓋


(7)效能分析結果



(8)關鍵模塊消耗最大的函數
主要是是個調用的包消耗大。

3、PSP

PSP2.1 我的開發流程 預估耗費時間(分鐘) 實際耗費時間(分鐘)
Planning 計劃 10 30
· Estimate 明確需求和其餘相關因素,估計每一個階段的時間成本 10 30
Development 開發 720 900
· Analysis 需求分析 (包括學習新技術) 60 90
· Design Spec 生成設計文檔 10 30
· Design Review 設計複審 10 20
· Coding Standard 代碼規範 30 35
· Design 具體設計 90 120
· Coding 具體編碼 400 365
· Code Review 代碼複審 60 120
· Test 測試(自我測試,修改代碼,提交修改) 60 120
Reporting 報告 100 170
· 測試報告 40 70
· 計算工做量 20 30
· 並提出過程改進計劃 40 70

4、小結感覺

本次結對編程不能說是第一次,由於以前java做業也有結對編程的任務。可是以前的結對編程是靠彼此默契,如今此次結對編程相對有方法。經過本次結對編程學會更好的規範代碼,學會預估等等。我認爲結對編程真的可以帶來1+1>2的效果。結對編程寫代碼時,想法能夠及時交流,有錯誤時能夠站在不一樣的角度去解決。相對於本身編程,結對編程的效率更高。

5、參考資料

參考 重構-靠譜程序員的必備技能: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 效能分析工具:http://www.oschina.net/p/jprofiler ,使用方法: http://www.cnblogs.com/bjlhx/p/6668888.html 參考教材P29-34 參照「效能測試,分析,改進,再效能測試」的流程,找出關鍵模塊消耗最大的函數,是否存在改進?

相關文章
相關標籤/搜索