结对作业-小学四则运算

Coding克隆地址:https://git.coding.net/FrrLolix/CalGUI.git

伙伴博客:http://www.cnblogs.com/FrrLolix/p/8763072.html

目录:

一、前言

二、计划时间——PSP

三、接口设计

四、接口实现

五、性能分析

六、单元测试

七、异常处理

八、模块设计

九、模块对接

十、结对成员

十一、结对编程思考

十二、实际时间——PSP

 

一、前言

  首先我很感谢我的队友,谢谢他的努力,放弃自己休息的时间,我们才能做成这个项目,我对于这个完成这个项目的能力很是欠缺,通过这次的作业,提高团队合作力和代码能力。

二、PSP

 

PSP

任务内容

计划时间(min)

Planning

计划

30

     Estimate

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

30

Development

开发

35*60+25

    Analysis

    需求分析

60

    Design Spec

    生成文档

0

    Design Review

    设计复审

2*60

    Coding Standard

    代码规范

10

    Design

    具体设计

12*60

    Coding

    具体编码

2*8*60

    Code Review

    代码复审

4*60

    Test

    测试

15

Reporting

报告

5.5*60

    Test Report

    测试报告

60

    Size Measurement

    计算工作量

30

   Postmortem& ProcessImprovement Plan

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

4*60

三、接口设计

在《构建之法》书中没有找到有关信息,希望老师在设计要求的时候,可以告诉我们页数。我在网上查阅了资料。

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

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

Loose Coupling松耦合:系统通常是基于消息的系统,此时客户端和远程服务并不知道对方是如何实现的。客户端和服务之间的通讯由消息的架构支配。只要消息符合协商的架构,则客户端或服务的实现就可以根据需要进行更改,而不必担心会破坏对方。

本次作业采用的是网页制作,整体采用MVC模型MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。本次作业进行了模块化编程,运算模块和界面模块相对较独立,尽量做到了低耦合度。让判断正误和计时以及条件受限放到前端制作,减少服务器的负担。

四、接口实现

我们的项目中界面套界面。即是亮点又是污点,亮点在于方法简单,实现方便,容易掌握。同时这也是一个不好之处,导致程序无法分解,耦合度太高,后期维护困难。

讲真,这个项目对于我们来说,能完成已经是竭尽全力,在优化性能时尽管有些抵触,但也算尽力,尽量减少内存占用率,减少嵌套循环和数组过大带来的资源浪费。在生成计算式时,不符合要求的计算式需要舍弃,在数值较大时,十分容易造成资源的浪费,因此我们在数值较大时,尽量限制了乘法时数的大小,尽量避免连续多次弃用。

六、单元测试

测试Command类

设计思路:

  在main方法中实现了对输入参数的解析和对输入参数异常的报错,所以测试这个部分的函数最主要的就是构造不同的异常情况,同时也不要忘记测试参数正确时的情况,因为这也是代码的一部分(单元测试中第一次就是因此覆盖率较低)。

 

 

单元测试代码展示(测试Command.java):

复制代码
import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;


public class CommandTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testNewExpSome() {
        for(int i=0;i<6;i++){
            Command.expression(false, 200, 20, 6);
        }
        for(int i=0;i<24;i++){
            Command.expression1(true, 200, 20, 4);
            Command.exprission2(true, 200, 20, 4);
            Command.expression3(true, 200, 20, 4);
        }

        System.out.println("Command程序正常!");
    }

    @Test
    public void testDivideExactly() {

    }

}

CommandTest
复制代码

 

七、异常处理:

复制代码
if(radioButtonMenuItem01.isSelected()){flag='a';}
                        if(radioButtonMenuItem02.isSelected()){flag='b';}
                        if(radioButtonMenuItem03.isSelected()){flag='c';}
                        String n = JOptionPane.showInputDialog(
                                frame,
                                "输入题目的数量(1-1000):"
                        );
                        String m = JOptionPane.showInputDialog(
                                frame,
                                "输入数值范围(1-10000):"
                        );
                        String z = JOptionPane.showInputDialog(
                                frame,
                                "输入符号数量(1-10):"
                        );
                        if(n==null||n.equals("")&&m==null||m.equals("")&&z==null||z.equals("")){
                            textArea.append("取消生成,请检查数值\n");
                        }
复制代码
复制代码
if(arithExpress.isEmpty()){
                            JOptionPane.showMessageDialog(
                                    frame,
                                    "没有读取到默认题库,请先生成或者打开本地题库",
                                    "消息标题",
                                    JOptionPane.WARNING_MESSAGE
                            );
复制代码

 

八、模块设计

整体思路:

 

 

导航页和获得出题参数页使用了同种方式来生成用户界面,代表导航页和出题参数页的类继承了JFrame类,在内部类中加入页面需要的各种组件,并将这个内部类的对象加入到外部类的实例中,在这里以计算页的代码为例展示这种方式(因代码太长所以只展示一部分):

 

public void generateExpressionA(int num,int m,int z){
        char[] operator=new char[]{'+','-','*','÷'};
        ArrayList<String> expression=new ArrayList<String>();
        for(int i=0;i<num;i++){
            int n=z; //3-5个运算符
            int[] number=new int[n+1];
            for(int j=0;j<=n;j++){
                number[j]=random.nextInt(m)+1; //4-5个数字
            }
            String ex=new String();
            for(int j=0;j<n;j++){
                int s=random.nextInt(4);//随机选择某个运算符
                ex+=String.valueOf(number[j])+String.valueOf(operator[s]);///5+4/
            }
            ex+=String.valueOf(number[n]);
            String result=calculate.solution(ex);

            if(decideNegDiv(Float.parseFloat(result))){
                expression.add(ex+="="+Float.parseFloat(result));
            }else{
                i--;
            }
        }
        doFile.WriteToFile("result.txt",expression);
    }

    /**
     * 生成带括号运算结果非负,非小数的运算式
     * @param num
     */
    public void generateExpressionB(int num,int m,int z){
        char[] operator=new char[]{'+','-','*','÷'};
        ArrayList<String> expression=new ArrayList<String>();
        for(int i=0;i<num;i++){
            int n=z; //3-5个运算符
            int[] number=new int[n+1];
            for(int j=0;j<=n;j++){
                number[j]=m; //4-5个数字
            }
            String ex=new String();
            int c=random.nextInt(3);
            for(int j=0;j<n;j++){
                switch(c){
                    case 0:
                        if(j==0){//(6-
                            ex+='('+String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        if(j==1){
                            ex+=String.valueOf(number[j])+')'+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        else{
                            ex+=String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                    case 1:
                        if(j==1){//3-(4-
                            ex+='('+String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        if(j==2){
                            ex+=String.valueOf(number[j])+')'+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        else{
                            ex+=String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                    case 2:
                        if(j==2){//5-6-(7-
                            ex+='('+String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        if(j==3){//5-6-(7-5)-
                            ex+=String.valueOf(number[j])+')'+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                        else{
                            ex+=String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
                            break;
                        }
                }
                ex+=String.valueOf(number[j])+String.valueOf(operator[random.nextInt(4)]);///5+4/
            }
            ex+=String.valueOf(number[n]);
            if(ex.indexOf('(')!=-1){
                if(ex.indexOf(')')==-1){
                    ex+=")";
                }
            }
            String result=calculate.solution(ex);
            if(decideNegDiv(Float.parseFloat(result))){
                expression.add(ex+="="+Float.parseFloat(result));
            }else{
                i--;
            }
        }
        doFile.WriteToFile("result.txt",expression);
    }

九、模块对接

读取文件的类:

 public ArrayList<String> ReadFile(String path)
    {
        ArrayList<String> tempList=new ArrayList<String>();
        try {
            BufferedReader br = new BufferedReader(new FileReader(path));
            String line;
            while((line=br.readLine())!=null){
                tempList.add(line);
            }
            br.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return tempList;
    }

    /**
     * 读取文件最后N行
     * 根据换行符判断当前的行数,
     * 使用统计来判断当前读取第N行
     * @param path 待文件路径
     * @param numRead 读取的行数
     * @return List<String>
     */
    public ArrayList<String> readLastNLine(String path, long numRead)
    {
        File file=new File(path);
        ArrayList<String> result = new ArrayList<String>();
        long count = 0;
        if (!file.exists() || file.isDirectory() || !file.canRead()){
            return null;
        }
        RandomAccessFile fileRead = null;
        try{
            fileRead = new RandomAccessFile(file, "r");
            long length = fileRead.length();
            if (length == 0L){
                return result;
            }
            else{
                long pos = length - 1;
                while (pos > 0){
                    pos--;
                    fileRead.seek(pos);
                    if (fileRead.readByte() == '\n'){
                        String line = fileRead.readLine();
                        result.add(line);
                        count++;
                        if (count == numRead){
                            break;
                        }
                    }
                }
                if (pos == 0){
                    fileRead.seek(0);
                    result.add(fileRead.readLine());
                }
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
        finally{
            if (fileRead != null){
                try{
                    fileRead.close();
                }
                catch (Exception e){
                }
            }
        }
        return result;
    }

 

 

十、结对成员

 

 

1、樊融:优点:技术强;聪明;乐观。缺点:做事不认真。

2、王玥莹:优点:认真,上进,创造性思维强。缺点:模块化思维欠缺。

 

十一、对编程思考

结对编程有好处:

一、结对编程可以相互学习互相鼓励

二、分工明确,可以提高做事效率

三、增强两个人的关系,增强合作能力、增强代码理解能力。

四、在出现错误时,伙伴可以及时发现并且指出,少走弯路

结对编程有坏处:

一、需要大量的交流,如果交流沟通不到位,项目将寸步难行。

二、可能会出现思路的分歧,导致两人代码出现分歧,难以结合。

三、两人分工的不均匀,有可能出现技术强带技术弱做项目的情况。

 

十二、PSP

 

PSP

任务内容

完成时间(min)

Planning

计划

60

     Estimate

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

60

Development

开发

45*60

    Analysis

    需求分析

45

    Design Spec

    生成文档

0

    Design Review

    设计复审

3*60

    Coding Standard

    代码规范

15

    Design

    具体设计

12*60

    Coding

    具体编码

3*8*60

    Code Review

    代码复审

4*60

    Test

    测试

60

Reporting

报告

9*60

    Test Report

    测试报告

0

    Size Measurement

    计算工作量

60

   Postmortem& ProcessImprovement Plan

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

8*60

 

posted @ 2018-04-10 08:46  wyyue  阅读(249)  评论(1编辑  收藏  举报