基于GUI的小学生四则运算系统

前言:首先在此感谢我的结对搭档,没有她的帮助和引导绝不会有现在的项目。很高兴和她一起结对完成这个项目。搭档真的是棒棒哒!

一、Coding.Net项目地址 https://git.coding.net/day_light/GUIszysLL.git

二、PSP计划表格

PSP

任务内容

计划需要时间(min)

Planning

计划

60

Estimate

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

60

Development

开发

32*60+50

Analysis

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

2*60

Design Spec

生成设计文档

20

Design Review

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

10

Coding Standard

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

20

Design

具体设计

3*60

Coding

具体编码

24*60

Code Review

代码复审

60

Test

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

2*60

Reporting

报告

60

Test Report

测试报告

30

Size Measurement

计算工作量

10

Postmortem & Process Improvement Plan

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

20

三、Information Hiding, Interface Design, Loose Coupling方法对接口进行设计

Information Hiding即信息隐藏,指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。也就是说,我们在编程的时候只需调用有关的方法,函数,知道它是干什么的而无需知道它是怎么具体实现的。

Interface Design,即接口设计,我的理解就是将模块化进行到底吧。通过接口可以实现不相关类的相同行为,而不需要了解对象所对应的类。从程序角度,简单理解,接口就是函数声明,类就是函数实现。需要注意的是同一个声明可能有很多种实现。我们在设计过程中也体会到了接口的好处。

Loose Coupling即松耦合耦合程度越高,模块与模块之间的联系性就更高,系统的灵活性就越低,报错率就更高。我们在设计过程中尽可能地让算式的产生和计算,优先级判断相互独立,但是我们目前使用的算法还可能出现性能方面的不稳定性(一般出现在加减乘除带括号运算的情况中)。

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

我们的项目一共有两个类,Command类与Lib2类,Command类是主类包含主函数,负责接收从命令行输入的参数。Lib2类一共有4个计算函数compute1,compute2,compute3,compute4。分别对应加减运算,加减乘除运算,加减带括号运算,加减乘除带括号运算。对应的进行算式的产生和运算。

流程图如下:

 

我们的代码并没有什么独到的地方,值得一提的或许是我们的代码不是很精但还算的上是清晰易懂吧。

五、计算模块接口部分的性能改进。

在计算模块性能的改进过程中,我们花费了将近一天的时间,有效时间大约为8小时左右。最后的实现方法是:当遇到除法的时候,我们尽可能随机产生被除数的因数,以减少代码随机生成的无效循环。当遇到乘法的时候,尽可能地减少乘数的大小,以保证在不超出用户范围的同时,可以产生较多的式子,来满足用户的需求,同时提高代码覆盖率。我们消耗最大的就是Lib2类,即算式生成,与计算模块。

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

在进行单元测试的时候,我们打算尽可能扩大参数的选择范围,尽可能的多出题目,多增加运算符号以测试程序的可用性。

以下是对计算类Lib2中四个运算函数compute1,compute2,compute3,compute4的单元测试代码及其覆盖率:

import static org.junit.Assert.*;
 
 import org.junit.Test;
 
 public class test {
     Lib2 lib = new Lib2();
     @Test
     public void test() {
         lib.compute1(1000, 10, 50, 1000);
         lib.compute2(1000, 10, 50, 1000);
         lib.compute3(1000, 10, 50, 1000);
         lib.compute4(1000, 10, 50, 1000);
         
     }
 
 }

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

样例1:n为非法字符(字母,符号等,这里以字母为例)。 

@Test
public void testn1command() 
{ String[] args
={"-n","e","-m","1","100"}; Command.main(args); }

样例2:n超出预计范围(n小于1或大于10000,这里以-9为例)。

@Test
public void testn2command() 
{ String[] args
={"-n","-9","-m","1","100"}; Command.main(args); }

 样例3:m1,m2超出预计范围(m1大于m2或者m1小于1大于100或者m2小于50大于1000,这里以m1为-8,m2为40为例)。

@Test
public void testm1command() 
{ String[] args
={"-n","10","-m","-8","40"}; Command.main(args); }

 样例4:m为非法字符(字母,符号等,这里以字母为例)。

@Test
public void testm2command()
{ String[] args
={"-n","10","-m","8","e"}; Command.main(args); }

 样例5:m,n不存在。

@Test
public void testmncommand() 
{ String[] args
={}; Command.main(args); }

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

我们的项目是用GUI来实现的用户界面,大体思路如下:

 

以出题界面部分代码展示为例:

public GUI() {
        mybutton=new ActionFrame().getButton();
        JPanel p1 = new JPanel(new GridLayout(0, 2));
        JPanel p3 = new JPanel(new GridLayout(0, 2));
        p1.add(new JLabel("请输入题目数 "));
        p1.add(n);
        p1.add(new JLabel("运算符个数上限"));
        p1.add(o);
        p1.add(new JLabel("数值范围下界 "));
        p1.add(m1);
        p1.add(new JLabel("数值范围上界 "));
        p1.add(m2);
        p3.add(A);
        p3.add(B);
        //p3.add(mybutton);
        JPanel p2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        p2.add(mybutton);
        
        p2.add(jbtBeginCompute);
        add(p1, BorderLayout.CENTER);
        add(p2, BorderLayout.SOUTH);
        add(p3, BorderLayout.EAST);
        ButtonListener listener = new ButtonListener();
        jbtBeginCompute.addActionListener(listener);
        A.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                c = 1; // 是否有乘除
            }
        });
        B.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b = 1; // 是否有括号
            }
        });
    }

 

九、界面模块与计算模块的对接。

UI在上一个模块中已经展示过了,下面说一说两模块对接的问题。我们在设计过程中通过定制题目界面接受用户选择的参数,再通过用户参数的限制选择相应的生成算式的模式,然后是调用计算模块。用户的输入和系统的算式生成与计算是两个相互独立的系统,互不干扰。

界面展示:

定制出题

错题库:

上传题目:

命令行测试:

十、结对照片

十一、结对编程的优点和缺点。

结对编程的优点:

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

2)两个程序员之间可以相互教对方,进行优劣势的互补。

结对编程的缺点:

1)两个人在一起工作可能会出现工作精力不能集中的情况。程序员可能会交谈一些与工作无关的事情,反而分散注意力,导致效率比单人更为低下。

2)有时候,程序员们会对一个问题各执己见(代码风格可能会是引发技术人员口水战的地方),争吵不休,反而产生重大内耗。

搭档的优缺点:温柔,超级好说话沟通无障碍,彼此都能懂。可以实现互帮互助,一起学习,有时候,会对一个问题很坚持,缺少变通性。

我的优缺点:细致,耐心,计划性强,但偶尔会开小差。

十二、PSP实际表格

PSP

任务内容

实际需要时间(min)

Planning

计划

60

Estimate

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

60

Development

开发

2738

Analysis

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

5*60

Design Spec

生成设计文档

20

Design Review

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

8

Coding Standard

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

10

Design

具体设计

300

Coding

具体编码

1800

Code Review

代码复审

120

Test

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

180

Reporting

报告

82

Test Report

测试报告

60

Size Measurement

计算工作量

7

Postmortem & Process Improvement Plan

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

15

十三、总结

这个项目对我来说,难度不小,甚至可以说是很大。我接触到了很多新的东西,比如说,怎么进行单元测试,怎么做效能分析(虽然现在还是有点懵),怎么看代码覆盖率,性能的改进等等。这让我明白了编程不仅仅是按要求敲完代码就好了的事情。

什么是好的代码?我想好的代码就是尽可能满足用户要求的,代码覆盖率高的,系统性能好的,效能合理的,通俗易懂的吧。我们为什么要敲好的代码?因为我们需要好的代码。为什么需要?因为提升了性能,就是增大了系统在极端情况下的可用性,减少出现bug的概率,给用户更好的使用体验,并且还可以提升自己项目的核心竞争力。同时,通俗易懂的代码可以减少因熟悉代码而浪费的不必要的时间,提高整体的效率。

结对,是让两个人的思想,方法,习惯,性格进行的碰撞,这是一场美好的体验,最后还是要感谢我的搭档和帮助过我们的小哥哥小姐姐们。

原文地址:https://www.cnblogs.com/2016SE_NENU/p/8761426.html