小学四则运算结对项目报告

目录
一、仓库地址
二、PSP
三、接口设计
四、计算模块接口的设计与实现过程
五、计算模块部分单元测试展示

六、计算模块部分异常处理说明
七、界面模块的详细设计过程
八、界面模块与计算模块的对接
九、描述结对的过程
十、结对优缺点
一、仓库地址:https://git.coding.net/yanglq/Twork.git

 二、PSP

 

PSP2.1

任务内容

计划共完成需要的时间(h)

实际完成需要的时间(h)

Planning

计划

5

10

Estimate

估计这个任务需要多少时间,并规划大致工作步骤

2

1.5

Development

开发

30

40

Analysis

需求分析 (包括学习新技术)

10

15

Design Spec

生成设计文档

0

0

Design Review

设计复审 (和同事审核设计文档)

5

5

Coding Standard

代码规范 (为目前的开发制定合适的规范)

0.5

0.5

Design

具体设计

30

60

Coding

具体编码

8

12

Code Review

代码复审

 1

2

Test

测试(自我测试,修改代码,提交修改)

 1

4

Reporting

报告

2

2

Test Report

测试报告

0.5

 1

Size Measurement

计算工作量

 0.5

0.5

Postmortem & Process Improvement Plan

事后总结, 并提出过程改进计划

1

2

 

三、接口设计:

      我在构建之法中并没有找到这些接口说明,这些大多信息都是在网上查找的。

      Information Hiding信息隐藏:信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。

      Interface Design接口设计:是传统的后勤保障的一种要素也是一种后勤功能。

      Loose Coupling松耦合:系统通常是基于消息的系统,此时客户端和远程服务并不知道对方是如何实现的。客户端和服务之间的通讯由消息的架构支配。改变或者供应者或者服务的问题不能影响到用户.----或者用户的问题不应影响到供应者或者服务。

   这次的作业用Web网页 对模块进行划分,模块与模块之间则是通过接口设计将它们整合在一起的。此项目有三个模块计算模块,显示模块,控制模块。

四、计算模块接口的设计与实现过程

     我负责计算模块,计算模块创建了两个类,一个是User类,与Web页面交互生成要求的算式题目。一个是News类。User里包含expression方法产生四则运算式,toSuffix方法实现中缀转后缀,dealEquation对后缀表达式进行计算。

代码展示:

public LinkedList<String> expression(int n,int c,int b,int min,int max ){
        char[] operator=new char[]{'+','-','*','÷'};
        Random random=new Random();
        LinkedList<String> expression=new LinkedList<String>();
        int ope[]= operator(n,c); //产生的运算符的个数
        int[] number=new int[ope.length+1]; //运算数的个数,该数组存储运算数

        for(int j=0;j<=ope.length;j++){
            number[j]=random.nextInt(max-min)+min; //限制产生的数字在上下界之间
        }

        int bracketnum=random.nextInt(ope.length);
        if (b==1&&bracketnum>0) {
//	    	System.out.println("括号数:"+bracketnum);
            int [] lbracketloc=new int[bracketnum];
            int [] rbracketloc=new int[bracketnum];
            int [] leftnum=new int[ope.length+1];
            int [] rightnum=new int[ope.length+1];
            for (int i = 0; i <bracketnum; i++) {
                lbracketloc[i]=random.nextInt(ope.length);
                rbracketloc[i]=random.nextInt(ope.length)+1;
                if (rbracketloc[i]<=lbracketloc[i]) {
                    i--;
                }
            }

            for (int i = 0; i < bracketnum; i++) {  //利用桶函数的思想,记录每个运算数对应的括号的个数
                leftnum[lbracketloc[i]]++;
                rightnum[rbracketloc[i]]++;
            }

            for (int i = 0; i < ope.length+1; i++) {
                if (!(leftnum[i]==0||rightnum[i]==0)) {
                    while (!(leftnum[i]==0||rightnum[i]==0)) {
                        leftnum[i]--;
                        rightnum[i]--;
                    }
                }
            }

            int right=0;
            int left=0;
            for (int i = 0; i < ope.length; i++) {
                for (int j = 0; j < leftnum[i]; j++) {
                    expression.add("(");
                    left++;
                }

                expression.add(String.valueOf(number[i]));

                for (int j = 0; j < rightnum[i]; j++) {
                    expression.add(")");
                    right++;
                }

                expression.add(String.valueOf(operator[ope[i]]));
                if(ope[i]==3){
                    number[i+1]=decide(number[i],number[i+1]);
                }
            }
            expression.add(String.valueOf(number[ope.length]));
            for (int i = right; i < left; i++) {
                expression.add(")");
            }
        }
        else {
            for(int i=0;i<ope.length;i++){
                expression.add(String.valueOf(number[i]));
                expression.add(String.valueOf(operator[ope[i]]));
                if(ope[i]==3){
                    number[i+1]=decide(number[i],number[i+1]);
                }
            }
            expression.add(String.valueOf(number[ope.length]));
        }
        return expression;
    }

 

public static String toSuffix(String infix){
        List<String> queue = new ArrayList<String>();
        List<Character> stack = new ArrayList<Character>();

        char[] charArr = infix.trim().toCharArray();
        String standard = "*/+-()";
        char ch = '&';
        int len = 0;
        for (int i = 0; i < charArr.length; i++) {

            ch = charArr[i];
            if(Character.isDigit(ch)) {
                len++;
            }else if(Character.isLetter(ch)) {
                len++;
            }else if(ch == '.'){
                len++;
            }else if(Character.isSpaceChar(ch)) {
                if(len > 0) {
                    queue.add(valueOf(Arrays.copyOfRange(charArr, i - len, i)));
                    len = 0;
                }
                continue;
            }else if(standard.indexOf(ch) != -1) {
                if(len > 0) {
                    queue.add(valueOf(Arrays.copyOfRange(charArr, i - len, i)));
                    len = 0;
                }
                if(ch == '(') {
                    stack.add(ch);
                    continue;
                }
                if (!stack.isEmpty()) {
                    int size = stack.size() - 1;
                    boolean flag = false;
                    while (size >= 0 && ch == ')' && stack.get(size) != '(') {
                        queue.add(valueOf(stack.remove(size)));
                        size--;
                        flag = true;
                    }
                    while (size >= 0 && !flag && level.get(stack.get(size)) >= level.get(ch)) {
                        queue.add(valueOf(stack.remove(size)));
                        size--;
                    }
                }
                if(ch != ')') {
                    stack.add(ch);
                } else {
                    stack.remove(stack.size() - 1);
                }
            }
            if(i == charArr.length - 1) {
                if(len > 0) {
                    queue.add(valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1)));
                }
                int size = stack.size() - 1;
                while (size >= 0) {
                    queue.add(valueOf(stack.remove(size)));
                    size--;
                }
            }

        }
        return queue.stream().collect(Collectors.joining(","));
    }

 

 

public static String dealEquation(String equation){
        String [] arr = equation.split(",");
        List<String> list = new ArrayList<String>();

        for (int i = 0; i < arr.length; i++) {
            int size = list.size();
            switch (arr[i]) {
                case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(valueOf(a));     break;
                case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(valueOf(b));     break;
                case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(valueOf(c));     break;
                case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(valueOf(d));       break;

                default: list.add(arr[i]);     break;
            }
        }

        return list.size() == 1 ? list.get(0) : "运算失败" ;
    }

 

五、计算模块部分单元测试展示

   建立test对代码进行测试

代码如下:

 

@org.junit.Test
    public void testCore(){//测试产生随机式、中缀转后缀和计算后缀表达式
        LinkedList<String> list=makeQuestion.expression(5, 0, 1, 2, 99);
        LinkedList<String> list1=makeQuestion.expression(10, 1, 0, 2, 99);
        Iterator<String> it=list.iterator();
        StringBuilder sd=new StringBuilder();
        while (it.hasNext()) {
            sd.append(it.next()).append(" ");
        }
        String[] ss=sd.toString().split(" ");

        Iterator<String> it1=list1.iterator();
        StringBuilder sd1=new StringBuilder();
        while (it1.hasNext()) {
            sd1.append(it1.next()).append(" ");
        }
        String[] ss1=sd1.toString().split(" ");


        makeQuestion.toSuffix("test.txt");
        makeQuestion.dealEquation("test.txt");


        makeQuestion.toSuffix("test.txt");
        makeQuestion.dealEquation("test.txt");


    }

 

 

 

@org.junit.Test
public void testIsOpe(){
assertThat(makeQuestion.isOperator("5"), org.hamcrest.CoreMatchers.is(false));
assertThat(makeQuestion.isOperator("+"), org.hamcrest.CoreMatchers.is(true));
assertThat(makeQuestion.isOperator("-"), org.hamcrest.CoreMatchers.is(true));
assertThat(makeQuestion.isOperator("*"), org.hamcrest.CoreMatchers.is(true));
assertThat(makeQuestion.isOperator("÷"), org.hamcrest.CoreMatchers.is(true));
assertThat(makeQuestion.isOperator("("), org.hamcrest.CoreMatchers.is(true));
assertThat(makeQuestion.isOperator(")"), org.hamcrest.CoreMatchers.is(true));
}
 

 

 

六、计算模块部分异常处理说明

User类:

News类中

 

 

七、界面模块的详细设计过程

界面设计大致用户进入页面进行选择提交后,开始出题。用户开始答题,提交后跳转到有正确答案的页面。

 

八、界面模块与计算模块的对接

          

               

 

九、描述结对的过程

在刚开始结对完成作业的时候,我们两个还比较迷茫,对于结对应该怎么做?怎样合作?都存在着些许疑问,但在阅读《构建之法》第四章之后便豁然开朗。首先我们对作业进行讨论并进行任务的分配,估计我们将在程序的各个模块的开发上耗费的时间并制作PSP表格;在完成作业的过程中,我们两个一起讨论、一起设计、一起编码、一起单元测试、一起编写文档等,具有非常强额解决问题的能力也提高了代码效率和质量。这是一个非常棒的体验!以下图片见证我们的pair:

十、结对优缺点

 

优点:

①可以每时每刻都处在代码复审的状态

②一对程序员可以平等地、互补地进行开发工作

③在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力

④对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带啦更高的满足感

⑤结对编程能相互督促,在心理上,能够更好地监督自身和更好地提高自身的技术能力

⑥在企业管理层次上,结对能更有效地交流,互相学习和传递经验,能更好地处理人员流动

⑦结对编程能得到更高的投入产出比(Return of Investment)

⑧结对编程在一定程度上避免了个人英雄主义,能够帮助建立集体拥有代码的意识

缺点:

①在高速度中完成任务,任务有较高的技术要求,任务失败的代价很高

②开发人员需要时间来适应这种新的开发模式,刚开始的结对编程效率可能不见得比单独开发效率高

③结对编程要求两个人协调一致,每个人的作息时间需要同步。当有一人出现情况另一人不得不等待

④结对编程不能像单独开发一样自主和自由

⑤结对编程中两个人的职责是相同的,可以减小每一个人的压力,但又容易造成缺乏责任感

结对中的你我:

YLQ:在这次结对作业中她连续几天熬夜查阅各种资料、学习知识来攻克这次的作业,非常地认真尽职,但因为遇到一些难题而变得比较焦躁,写代码时bug较多。总的来说她是个非常棒的结对partner。

ZST:这次结对作业过程中她能比较耐心地尽力完成每一部分,但同时也遇到非常多不懂的知识面,通过查阅各种资料并学习攻克。虽然她掌握的技能和知识较为匮乏,但能努力学习并补足,也是个值得结对的pair。

 

posted @ 2018-04-10 07:27  yanglqa  阅读(247)  评论(2编辑  收藏  举报