标签:tps 避免 .class 方法 code 命令 tst 启动 分析
目录
1.仓库地址
2.开始前PSP展示
3.接口的设计
4.计算模块接口的设计与实现过程
5.计算模块接口部分的性能改进
6.计算模块部分单元测试展示
7.计算模块部分异常处理说明
8.界面模块的详细设计过程
9.界面模块与计算模块的对接
10.结对过程
11.结对编程优缺点
12.实际的PSP
1. 仓库地址: https://git.coding.net/jiapwy/newfouroperation.git
队友:胡雅馨
队友的博客地址:http://www.cnblogs.com/huyaxin/p/8776113.html
这次作业对我而言难度很大,所以十分感谢我的队友在这次结对编程中对我的帮助。通过这次作业,我也深深地意识到了自己的不足,希望接下来能学到更多知识和技能。
2.开始前PSP展示
|
PSP |
任务内容 |
计划共完成需要的时间(min) |
|
Planning |
计划 |
30 |
|
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
30 |
|
Development |
开发 |
1100 |
|
Analysis |
需求分析 (包括学习新技术) |
60*5 |
|
Design Spec |
生成设计文档 |
30 |
|
Design Review |
设计复审 (和同事审核设计文档) |
10 |
|
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
5 |
|
Design |
具体设计 |
60 |
|
Coding |
具体编码 |
600 |
|
Code Review |
代码复审 |
20 |
|
Test |
测试(自我测试,修改代码,提交修改) |
30 |
|
Reporting |
报告 |
40 |
|
Test Report |
测试报告 |
30 |
|
Size Measurement |
计算工作量 |
10 |
|
Postmortem& ProcessImprovement Plan |
事后总结, 并提出过程改进计划 |
60*5 |
3.接口的设计
基本概念
Information Hiding:信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。
Interface Design:面向接口编程是软件工程领域常用的设计手段
Loose Coupling:基于面向接口编程,松耦合度是接口设计的目的,接口设计是松耦合度的实现手段
对于面向对象的程序设计而言,信息隐藏是一种重要的软件开发手段,它与对象的封装与模块化密切相关。在我看来,信息隐藏使得一个类把复杂的、敏感的、一旦被外界捕获可能会引起不良后果的内容封装在自身内部,这个类以外的代码得不到此类信息(通过反射等手段可能对得到),以提高程序的安全性与健壮性。
关于interface design与loose coupling
我个人感觉,这两个概念是相辅相成的,后者是前者的目的,前者是后者的实现手段。
面向接口编程是软件工程领域常用的设计手段,在这次结对作业中,我们深切体会到它的一大优点:我们只需要面向接口进行编程,代码就完美的融入了整个程序中。虽然我们刚开始并不清楚整个测试程序的工作原理与架构,但我们专注于实现它的功能,就能够达到调度的目的。
这对于一个团队而言,是非常重要的,在做一个团队项目时,有人可能负责领域模型,有人负责前台,有人负责业务逻辑,在这种MVC的设计模式驱动下,我们首先想到的就是:定义一套公共的接口,方便各个模块之间的通讯。面向接口的程序设计思想是一种有效的手段。开发可以并行进行,这样,不需要等待一个模块的完成就可以预先“使用”这个模块,极大的提高了团队的效率
5个经典的设计原则检查(SOLID)。其中的SRP(Single Responsibility Principle)要求每个模块都只有一个明确的职责。因为模块职责多,就意味着逻辑难以封闭,容易受到外部因素变化而变化,导致该模块不稳定。在本项目中,我们把涉及到计算数据的生成和求解功能提出来,形成一个独立的模块。其他的控制输入、数据可视化等功能也形成各自的模块,再通过接口把它们联系起来,这样各模块间就做到了松耦合(即修改一个模块时不需要更改其他的模块),同时也实现了不同模块间的信息隐藏(即每个模块只访问自己感兴趣的数据来实现自己负责的功能)。
??
4.计算模块接口的设计与实现过程
我们小组的计算模块接口由两个类组成
Main类:模块的主类,负责接收命令行的参数并启动程序
test类:生成符合命令行参数要求的题目
test类里有
num方法:负责随机产生定制的算式
result方法:输出文件
calculator方法:负责筛选运算过程中符合要求的式子,并计算答案
nibolan方法:中缀表达式转后追表达式
5.计算模块接口部分的性能改进
见下图



6.计算模块部分单元测试展示
测试输入是有错误的

测试分母是0

代码覆盖率:

public void testMain() {
String[] args = {"-n","10","-m","1","100","-o","5","-c","-b"};
String[] args1 = {"-o"};
String[] args2 = {"-n","-m","1","100"};
String[] args3 = {"-n","100000","-m","100"};
String[] args4 = {"-m","1000","44","-n"};
String[] args5 = {"-o","100"};
String[] args6 = {"-m","-3","1"};
new Command();
Command.main(args);
Command.main(args1);
Command.main(args2);
Command.main(args3);
Command.main(args4);
Command.main(args5);
Command.main(args6);
}
7.计算模块部分异常处理说明
我们共设计了四种异常处理,分别是出题数量异常处理,数值左边界异常处理,数值右边界异常处理和运算符数量异常处理。
(1)出题数量异常处理
当用户输入的出题数量的数值不在范围内时,提醒用户当前输入的数值不合法,要求用户重新输入。
try {
n1 = Integer.parseInt(n.getText());
if (n1 <= 0 || n1 > 10000) {
n.setText("请输入合法参数");
return;
}
flag0 = 1;
} catch (Exception a) {
n.setText("格式不正确,请重新填写!");
}
(2)数值左边界异常处理
当用户输入的出题数值左边界不在范围内时,提醒用户当前输入的数值不合法,要求用户重新输入。
try {
m11 = Integer.parseInt(m1.getText());
if (m11 <= 0 || m11 > 100) {
m1.setText("请输入合法参数");
return;
}
flag1 = 1;
} catch (Exception a) {
m1.setText("格式不合法,请重新填写!");
}
(3)数值右边界异常处理
当用户输入的出题数值右边界不在范围内时,提醒用户当前输入的数值不合法,要求用户重新输入。
try {
m22 = Integer.parseInt(m2.getText());
if (m22 < 50 || m22 > 1000) {
m2.setText("请输入合法参数");
return;
}
flag2 = 1;
} catch (Exception a) {
m2.setText("格式不合法,请重新填写!");
}
(4)运算符数量异常处理
当用户输入的运算符数量不在范围内时,提醒用户当前输入的数值不合法,要求用户重新输入。
try {
o1 = Integer.parseInt(o.getText());
if (o1 <= 0 || o1 > 10) {
o.setText("请输入合法参数");
return;
}
flag3 = 1;
} catch (Exception a) {
o.setText("格式不合法,请重新填写!");
}
8.界面模块的详细设计过程
(1)欢迎界面
在开始时,我们对GUI的理解十分少,对基本的语句功能实现都非常困难,例如GUI的Button事件都不能实现,设计也十分不美观,下面是最开始的失败界面。

在尝试了很多之后,通过不断的学习,我们改进了界面,终于做的可以看了,并且实现了一部分功能,下面附上代码和图片。

public class Main
{
public static JTextField jtf =new JTextField(5); //文本框
public Main()
{
JMenuBar jmb=new JMenuBar(); //菜单栏
JFrame jf=new JFrame(); //窗口
final JLabel jlb =new JLabel(); //标签
final JButton jb =new JButton(); //按钮
JPanel jp =new JPanel(); //容器
JPanel jp1 =new JPanel();
jlb.setText("出题数量");
jtf.getText();
jb.setText("生成题目 ");
jf.setLayout(new BorderLayout()); //布局
jf.setSize(500, 400);
jf.setTitle("欢迎使用四则运算界面");
JMenu jm=new JMenu("语言选择"); //菜单
JMenuItem mi1=new JMenuItem("中文"); //菜单项
JMenuItem mi2=new JMenuItem("");
JMenuItem mi3=new JMenuItem("英文"); //实现选择语言功能
jm.add(mi1);
jm.add(mi2);
jm.add(mi3);
jmb.add(jm);
jp.add(jlb);
jp.add(jtf);
jp1.add(jb);
ImageIcon img = new ImageIcon("src/test2/2PAA~5DRU_W_ZJG]3$R(9LN銆俻ng");
jf.add(jp,BorderLayout.NORTH);
jf.add(jp1,BorderLayout.CENTER);
jf.setJMenuBar(jmb);
jf.setVisible(true);
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jlb.setText("出题数量");
jtf.getText();
jb.setText("生成题目");
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jlb.setText("出题数量");
jtf.getText();
jb.setText("go");
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jlb.setText("please input the number of questions you want");
jtf.getText();
jb.setText("generate tests"); //完成英文版
}
});
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
methodjb();
}
});
} //完成最初界面
public static void methodjb(){
new MainFrame(Integer.parseInt(jtf.getText()));
}
public static void main(String args[]) {
new Main(); //主函数调用
}
}
答题页面
当填写完出题数量后,再点击生成题目时,会出现另一个界面,页面包括所有生成的题目,以及结果的输入处,包括计时功能的完成,而语言选择项仍然存在,最后是生成题目按钮,当你点击按钮,运算的结果,时间就会传递给后台,而接下来的页面会进行相应判断的显示。下面附上对应代码。
最终页面
当你在题目页面点击了提交按钮,你的题目和答案会一起提交到后台,后台的计时器会停止计时,并且后台会对你的题目进行分析判断,最后提交给你一份答案页面,以及你答题所用的时间信息,还有你错误的题目的正确答案。下面附上图片和代码。

jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i=0;i<n;i++)
{
strarr[3*i+1]=jt[i].getText();
}
timer.stop();
JMenuBar jmb=new JMenuBar(); //菜单栏
JFrame jf=new JFrame(); //窗口
JPanel jp =new JPanel();
jp.setLayout(new GridLayout(n+1,2));
jf.setSize(400, 400);
jf.setTitle("四则运算");
JMenu jm=new JMenu("Language"); //菜单
JMenuItem mi1=new JMenuItem("中文简体"); //菜单项
JMenuItem mi2=new JMenuItem("中文繁体");
JMenuItem mi3=new JMenuItem("英文");
jm.add(mi1);
jm.add(mi2);
jm.add(mi3);
jmb.add(jm);
jf.setJMenuBar(jmb);
jf.setVisible(true);
final JButton jbt=new JButton("记录");
jbt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File file = new File("F:/result.txt");//形成文件
String line =null;
try {
BufferedReader br = new BufferedReader(new FileReader(file));
try {
while((line = br.readLine()) != null){
String[] num = line.split("#");
zheng1=Integer.parseInt(num[1]);
cuo1=Integer.parseInt(num[3]);
}} catch (IOException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException ex) {
keep();
}
keep();
}
private void keep() {
FileOutputStream fop = null;
File file;
String content = "正确#"+(n-MainFrame.cuowu+zheng1)+"#错误#"+(MainFrame.cuowu+cuo1)+"#";
try {
file = new File("D:/result.txt");
fop = new FileOutputStream(file);
if (!file.exists()) {
file.createNewFile();
}
byte[] contentInBytes = content.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fop != null) {
fop.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}//将正确错误题目数量都输入到文件中
});
for(int i=0;i<n;i++)
{
JLabel jb=new JLabel();
jb2[i]=new JLabel();
jb.setText(strarr[3*i]+strarr[3*i+1]);
if(strarr[3*i+1].equals(strarr[3*i+2]))
{
jb2[i].setText("正确");
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i=0;i<n;i++)
{
if(jb2[i].getText().equals("正确")||jb2[i].getText().equals("正确")||jb2[i].getText().equals("right"))
jb2[i].setText("正确");
else
jb2[i].setText("错误,答案是:"+strarr[3*i+2]);
}
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i=0;i<n;i++)
{
if(jb2[i].getText().equals("正确")||jb2[i].getText().equals("正确")||jb2[i].getText().equals("right"))
jb2[i].setText("正确");
else
jb2[i].setText("错误,答案是"+strarr[3*i+2]);
}
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i=0;i<n;i++)
{
if(jb2[i].getText().equals("正确")||jb2[i].getText().equals("正确")||jb2[i].getText().equals("right"))
jb2[i].setText("right");
else
jb2[i].setText("wrong,the answer is :"+strarr[3*i+2]);
}
}
});//计算正确答案
}
else
{
jb2[i].setText("错误,答案是:"+strarr[3*i+2]);
cuowu+=1;
}
jp.add(jb);
jp.add(jb2[i]);
}//出现错误答案
JPanel jp1=new JPanel();
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jbt.setText("记录");
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jbt.setText("记录");
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jbt.setText("record");
}
});//产生记录
jp1.add(jbt);
jp.add(jp1);
final JLabel lbl1 = new JLabel();
lbl1.setText("用时 :"+lbl.getText());
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lbl1.setText("用时:"+lbl.getText());
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lbl1.setText("用时:"+lbl.getText());
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lbl1.setText("time :"+lbl.getText());
}
});
jp.add(lbl1);
jf.add(jp);
}
});//累计用时的方法
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
}
public static void main(String args[]) {
new Main();
}
} //调用函数
整体实现过程


public class MainFrame
{
Date now = new Date();
JTextField[] jt=new JTextField[100];
String[] strarr=new String[100];
JLabel[] jb2 =new JLabel[100];
public static int cuowu=0;
int zheng1=0,cuo1=0;
public MainFrame(final int n)
{
JMenuBar jmb=new JMenuBar(); //菜单栏
JFrame jf=new JFrame(); //窗口
JPanel jp =new JPanel();
jp.setLayout(new GridLayout(n+1,3));
jf.setSize(400, 400);
jf.setTitle("四则运算");
JMenu jm=new JMenu("Language"); //菜单
JMenuItem mi1=new JMenuItem("中文简体"); //菜单项
JMenuItem mi2=new JMenuItem("中文繁体");
JMenuItem mi3=new JMenuItem("英文");
jm.add(mi1);
jm.add(mi2);
jm.add(mi3);
jmb.add(jm);
jf.setJMenuBar(jmb);
jf.setVisible(true);
for(int i=0;i<n;i++)
{
jt[i]=new JTextField();
jt[i].getText();
Random rand = new Random();
JLabel jbi=new JLabel();
int ra=rand.nextInt(2)+1;
zhengshu zsi=new zhengshu();
fenshu fsi=new fenshu();
fsi.main(null);
zsi.main(null);
if(ra==1)
{
jbi.setText(zsi.suanshi);
strarr[3*i]=zsi.suanshi;
strarr[3*i+1]=jt[i].getText();
strarr[3*i+2]=zsi.z;
}
else
{
jbi.setText(fsi.suanshi);
strarr[3*i]=fsi.suanshi;
strarr[3*i+1]=jt[i].getText();
strarr[3*i+2]=fsi.z;
}
JLabel jb=new JLabel();
jb.setText(" ");
jp.add(jbi);
jp.add(jt[i]);
jp.add(jb);
}
final JLabel lbl = new JLabel();
now.setHours(0);
now.setMinutes(0);
now.setSeconds(0);
final Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Date now2 = new Date(now.getTime() + 1000);
now = now2;
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
lbl.setText(formatter.format(now));
}
});
timer.start();
final JButton jb=new JButton("提交");
JPanel jp1=new JPanel();
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jb.setText("提交");
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jb.setText("提交");
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jb.setText("commit");
}
});
jp1.add(jb);
jp.add(jp1);
jp.add(lbl);
jf.add(jp);
9.界面模块与计算模块的对接
我们在这次结对项目中,通过设计了GUI类,即使用了图形用户界面来进行UI模块的设计,至于这些各种不同UI模块之间的对接,则是通过事件监听器接口来实现的。
参数传递功能
String n = JOptionPane.showInputDialog(
frame,
"输入题目的数量(1-1000):"
);
String m = JOptionPane.showInputDialog(
frame,
"输入数值范围(1-10000):"
);
String z = JOptionPane.showInputDialog(
frame,
"输入符号数量(1-10):"
);
下面附上具体实现功能截图:




10.结对过程
因为工作量较大,我和我的结对小伙伴一早就定下了分工,虽然中间经历了一个小假期,但是我们也不时都在为这个作业而思考,在作业过程中我们遇到了很多困难,有时候一筹莫展,但好在我们一直在努力寻找解决方法,而且沟通良好,两人之间不存在任何嫌隙,最终也都如愿以偿得到了让我们比较满意的结果。下面附上我们的结对照片。

11.结对编程优缺点
优点:在结对编程中,深刻地体会到了1+1>2的含义,与个人单独编码相比,结对更加的高效,而代码变得更加有质量。当你在敲代码时,有另外一个人在不断提醒监督着你,这让自己克制了一些单独编码时不免会犯的错误,比如惰性和一些基础性的错误,同样,两个人的共进退让我们充满斗志,突破了困难局限,最终完成一项让我们自己满意的项目。
缺点:对于结对编程来说,沟通磨合是非常重要的,一旦没有有效的沟通,那结对编程便很难进行下去,而沟通一直是人与人之间的难题,我想这也算是结对编程所不可避免的缺点吧。另外,每个人编程都有自己的习惯和风格,所以当两个人在一起工作时,难免会产生矛盾就和摩擦,这也是不太容易解决的问题。
各人优缺点:
|
|
周紫伊 |
胡雅馨 |
|
优点 |
认真细心,有耐心
|
积极,上进,善于学习,平易近人
|
|
缺点 |
基础知识薄弱,不善于沟通交流 |
缺点:基础知识不扎实,偶尔懒散 |
12.实际的PSP
PSP
|
PSP |
任务内容 |
实际完成需要的时间(min) |
|
Planning |
计划 |
20 |
|
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
50 |
|
Development |
开发 |
2900 |
|
Analysis |
需求分析 (包括学习新技术) |
40 |
|
Design Spec |
生成设计文档 |
30 |
|
Design Review |
设计复审 (和同事审核设计文档) |
2 |
|
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
20 |
|
Design |
具体设计 |
60 |
|
Coding |
具体编码 |
1200 |
|
Code Review |
代码复审 |
20 |
|
Test |
测试(自我测试,修改代码,提交修改) |
1200 |
|
Reporting |
报告 |
180 |
|
Test Report |
测试报告 |
120 |
|
Size Measurement |
计算工作量 |
25 |
|
Postmortem& ProcessImprovement Plan |
事后总结, 并提出过程改进计划 |
60*5 |
标签:tps 避免 .class 方法 code 命令 tst 启动 分析
原文地址:https://www.cnblogs.com/zhouzy539/p/8776238.html