• 结对编程-四则运算(二)


    写在前面

    经历了两周的结对编程,我和王旌含在相互帮助中学到了不少,进步了不少。但我们认为这还不是我们理想中结对编程—我们起初当定义过自己在结对编程中角色,但在结对过程中却发生了改变,就像是在玩跷跷板,一个胖子和一个瘦子一起玩必定是索然无味的。唯有体重相差不大的人才能体会。有时候我们都想当瘦子,有时候我又成了大胖子,不断催促他个瘦子。对此我们询问了班上其他的结对对象,发现他们也陷入了此类问题,也许他们的编程速度比我们快,但其实并没有体现出结对编程,只是个人写个人的类,做自己的单元测试,自己修改,到最后只是将自己的类的作用解释给同伴。因为我们两人的能力不同,为了都能在结对编程中体现价值,在这周我们做了以下决定:

    并不是跷跷板胖瘦不同的人就不能玩了,我们决定不再关注两人的编程能力是否一样。
    我们决定不是所有的任务都采用结对编程的模式。
    对于程序中的重要类我们决定不断“复审”,我们开始“强迫”两人交流,开始根据能力的不同进行角色分工和互换

    代码重构

    • 这周我们刚的第一件事就是一起将我们生成题目的类进行升级重构
    public class Project {
        Random in = new Random();
        int a = in.nextInt(10)+1;
        int b = in.nextInt(10)+1;
        int c = in.nextInt(10)+1;
        int num = in.nextInt(4);
        int num2 = in.nextInt(4);
        String [] Operator = {"*","+","-","/"};
        public String HighPro(){
            int a = in.nextInt(6)+5;
            int b = 2*a+1;
    
            StringBuilder result = new StringBuilder(100);
            for (int i = 0;i<b;i++){
                int num3 = in.nextInt(10);
                int num4 = in.nextInt(4);
    
                if (i%2==0){
                    result.append(num3);
                }
                if(i%2!=0){
                    result.append(Operator[num4]);
                }
            }
            return String.valueOf(result);
        }
    }
    

    这是我起初编写的生成题目的代码,她有以下个问题

    • 没有排除除数为零的情况
    • 没有添加函数的方法
    • 代码不规范不整洁

    对此我们改变了生成题目的方式

        /*例子:1+(2+3)*4+5
        将此类题目分成三部分
        前部:1+
        中部:(2+3)
        后部:*4+5
        最后将几个部分结合
        */
    

    这是之后的代码

    import java.util.Random;
    
    /**
     * Created by asus on 2017/5/18.
     */
    public class NewProject extends SetNum{
        public String Front(){
            String result;
            switch (getC()){
    
                case 0:
                    result = getA()+Operator[getB()];
    
                    break;
                case 1:
                    result = getA()+Operator[getB()]+getA()+Operator[getB()];
    
                    break;
                default:
                    result = getA()+Operator[getB()]+getA()+Operator[getB()]+getA()+Operator[getB()];
            }
            return result;
        }
        public String Middle(){
            String result;
            switch (getC()){
                case 0:
                    result = getA()+"";
                    break;
                case 1:
                    result ="("+getA()+Operator[getB()]+getA()+")";
                    break;
                    default:
                        result = "("+getA()+Operator[getB()]+"("+getA()+Operator[getB()]+getA()+")"+Operator[getB()]+getA()+")";
            }
            return result;
        }
        public String End(){
            String result;
            switch (getC()){
                case 0:
                    result = Operator[getB()]+getA();
                    break;
                case 1:
                    result = Operator[getB()]+getA()+Operator[getB()]+getA();
                    break;
                    default:
                        result =  Operator[getB()]+getA()+Operator[getB()]+getA()+Operator[getB()]+getA();
            }
            return result;
        }
        public String Allpart(){
            String result;
            switch (getC()){
                case 0:
                    result = Front()+Middle();
                    break;
                case 1:
                    result = Middle()+Front();
                    default:
                        result = Front()+Middle()+End();
            }
            return result;
        }
        public String JudgeAllpart(){
            String result =Allpart();
            for(int i = 0;i<result.length();i++){
                if ((result.charAt(i)=='/')&&(result.charAt(i+1)=='0')){
                    result = Allpart();
                }
            }
            return result;
        }
    
    }
    
    import java.util.Random;
    
    /**
     * Created by asus on 2017/5/18.
     */
    public class SetNum {
        Random in = new Random();
        int a;
        int b;
        int c;
    
        public int getC() {
            setC();
            return c;
        }
    
        public void setC() {
            this.c = in.nextInt(3);
        }
    
        String [] Operator = {"+","-","*","/"};
    
        public int getB() {
            setB();
            return b;
        }
    
        public void setB() {
            this.b = in.nextInt(4);
        }
    
        public void setA() {
            this.a = in.nextInt(10);
        }
    
        public int getA() {
            setA();
            return a;
        }
    }
    
    

    当然以上代码是我们对其重构后的结果,中间代码因为重构了没有保留源
    具体重构如下:

    • 原代码并没有gettrt and setter而是每次都要使用随机数生成造成代码重复很多
      于是我们将其添加gettrt and setter,为了是每次调用都随机产生数,于是在get中在调用set
    • 我们考虑的其他类的编写中都会用到相同范围的随机数,于是定义SetNum类来作为父类,要使用的子类只需要继承即可,避免代码重复
    • 第二件事情是我们继续上周未能完成的Junit测试
      我们主要测试的是修改后的postfix类是否能继续胜任她的工作
        public void testCount() throws Exception {
        //TODO: Test goes here...
        String line;
        BufferedReader rdr = new BufferedReader(new FileReader("testdata.txt"));
        while ((line = rdr.readLine()) != null) {
            if (line.startsWith("#")) {
                continue;
            }
            StringTokenizer st = new StringTokenizer(line);
            if (!st.hasMoreTokens()) {
                continue;
            }
            String val = st.nextToken();
            String expected = val;
    
            LinkedList<String> argument_list = new LinkedList();
            while (st.hasMoreTokens()) {
                argument_list.add(st.nextToken());
            }
            Postfix a = new Postfix();
            a.transferToPostfix(argument_list);
            assertEquals(expected, a.transferToPostfix(argument_list));;
        }
    }
    

    因为用到大量测试数据,我们考虑用到一个独立的数据文件来储存这些测试数据,然后让单元测试读取该文件

    数据文件的格式是:第一个数字是想要运算的结果,后面是所要运算的题目,用空格隔开;
    用井号#表示所在行是注释
    自动忽略空行


    这是我们的成果

    我的感悟

    这次的结对编程我们学到了不少,代码在两个人的不断重构和复审之间变得更完美,但也有不好的地方就是当结对人员变得懒散时你不得不督促他。我认为这是不好的,结对编程要求投入,你尽可以偷懒,因为你的工作伙伴可以完成,但这不是我想要的结对编程,因为我们从中得不到任何好处,不会提高效率,更不会有所成长。

    当这个统计结果出来之后是难以置信的,在具体编码的用时上我们两人花了将近10个小时在写各自的代码,之所以是各自的代码(无论复杂简单)是因为我们回头反思发现在做具体的需求分析,具体设计是没能合理安排,在一开始阶段没能达成统一,导致我写代码他不懂,他的代码我不知怎么用,我们之间没有复审与重构,更没有角色的交换;其次,伙伴对于单元测试能力的欠缺导致在测试上也花了不少时间,可能比统计的多。总之这次的结对效果很是不理想,设计的程序不是很能说明问题,因为一个人做也能做出来。我们跟很多结对者有过交流,发现我们的结对编程还是有一定效果的,这给了我们很大信心。说句实话话,我并不是很赞成结对编程,因为相比结对,我更喜欢一个人编代码,因为在某些问题上我不需要跟别人解释。但既然结对编程了,我们是真心想要做好,拭目以待。

  • 相关阅读:
    Identity Server 4 原理和实战(完结)_建立Angular 客户端
    Identity Server 4 原理和实战(完结)_为 MVC 客户端刷新 Token
    Identity Server 4 原理和实战(完结)_Authorization Code Flow 实例
    Identity Server 4 原理和实战(完结)_Resource Owner Password Credentials 授权实例
    ASP.NET Core会议管理平台实战_2、基本概念的理解
    ASP.NET Core会议管理平台实战_汇总贴
    ASP.NET Core会议管理平台实战_1、开篇介绍
    Identity Server 4 原理和实战(完结)_建立Identity Server 4项目,Client Credentials 授权实例
    Identity Server 4 原理和实战(完结)_----选看 OpenId Connect 简介
    Identity Server 4 原理和实战(完结)_----选看 OAuth 2.0 简介(下)
  • 原文地址:https://www.cnblogs.com/wbiao21/p/6882067.html
Copyright © 2020-2023  润新知