前言:
四则运算结对项目成果展示,动手实现之前困惑忐忑,开发过程中劳累又收获,项目完成后满足又成长许多。
|
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间 (min) |
Planning |
计划 |
30 |
* |
· Estimate |
·估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
* |
Development |
开发 |
1250 |
* |
·Analysis |
·需求分析 (含有学习新技术) |
300 |
* |
·Design Spec |
·生成设计文档 |
20 |
* |
·Design Review |
·设计复审 (和同事审核设计文档) |
10 |
* |
·Coding Standard |
·代码规范 (为目前的开发制定合适的规范) |
15 |
* |
·Design |
·具体设计 |
30 |
* |
·Coding |
·具体编码 |
600 |
* |
·Code Review |
·代码复审 |
30 |
* |
·Test |
·测试(自我测试,修改代码,提交修改) |
200 |
* |
Modular |
模块 |
600 |
* |
·Computing module | 计算模块 | 400 | * |
·Timing module | 计时模块 | 200 | * |
Reporting |
报告 |
490 |
* |
·Test Report |
·测试报告 |
420 |
* |
·Size Measurement |
·计算工作量 |
40 |
* |
·Postmortem & Process Improvement Plan |
·事后总结, 并提出过程改进计划 |
30 |
* |
是信息隐藏,指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。为什么要隐藏?首先可以隐藏复杂度:这样你就不用再去应付它,除非你要特别关注的时候;其次隐藏变化源:这样当变化发生时,其影响就能被限制在局部范围内。复杂度的根源包括复杂的数据类型、文件结构、布尔判断以及晦涩的算法等等。信息隐藏的价值:信息隐藏有着独特的启发力,它能够激发出有效的设计方案。信息隐藏同样有助于设计类的公开接口。在设计的所有层面上,都可以通过询问隐藏什么的方式达到好的设计决策。
: 把类内数据误认为全局变量:为了避免全局数据可能带来的问题,可能会把类内数据误认为是全局数据并避免使用它,我们把Expression.java的answer变量由最初的全局变量变为类内数据,因为Judge.java里面有一个answer变量,为了避免Judge.java使用Expression.java的answer,我们把Judge.java的answer变量改为了ans变量名。其实只要Expression.java的answer变量的位置处于局部变量的位置就可以避免了。
通过参数传值,类间调用等实现模块的对接(主要是Command类和Expression类)。
读取和写入用户使用四则运算的计算结果,还包含用户答题正确数量。
1.random()函数,生成随机数
1 Random random=new Random(); 2 int s=random.nextInt(op); //随机选择某个运算符
2.eval()函数,计算字符串内的运算式
1 double result=0;
2 try {
3 result = Double.parseDouble(String.valueOf(engine.eval(ex)));//字符型变为整型
4 } catch (ScriptException e) {
5 e.printStackTrace();
6 }
3.createExp()函数,产生并返回计算表达式
1 public String createExp() {
2
3 char[] operator=new char[]{'+','-','*','/'};
4 Random random=new Random();
5 int[] number=new int[Four.jtf1Num+1];
6 String ex=new String();
7 for(int j=0;j<=Four.jtf1Num;j++){
8 number[j]=random.nextInt(Four.jpfMNum-Four.jpfNum+1)+Four.jpfNum; //运算数
9 }
10 int q=0;
11 for(int j=0;j<Four.jtf1Num;j++){
12 int op=0;
13 if(Four.jpf1Num!=0)
14 op=4;
15 else
16 op=2;
17 int s=random.nextInt(op); //随机选择某个运算符
18 while(s==q) //至少两种运算符
19 s=random.nextInt(op);
20 q=s;
21 ex+=String.valueOf(number[j])+String.valueOf(operator[s]);
22 if(s==3){number[j+1]=decide(number[j],number[j+1],Four.jpfMNum,Four.jpfNum);}//避免出现小数
23 }
24 ex+=String.valueOf(number[Four.jtf1Num]);
25 double result=0;
26 try {
27 result = Double.parseDouble(String.valueOf(engine.eval(ex)));//字符型变为整型
28 } catch (ScriptException e) {
29 e.printStackTrace();
30 }
31
32 if(Math.floor(result)==result&&result>0&&result<99999) {
33 return ex;
34 }else{
35 return createExp();
36 }
37
38 }
4.trim()函数,返回调用字符串对象的一个副本,删除起始和结尾的空格
1 Four.jtfNum = Integer.parseInt(this.jtf.getText().trim());//运算式个数
2 Four.jpfNum = Integer.parseInt(this.jpf.getText().trim());//lower
3 Four.jpfMNum = Integer.parseInt(this.jpfM.getText().trim());//upper
4 Four.jtf1Num = Integer.parseInt(this.jtf1.getText().trim());//sumOfOperation
5 Four.jpf1Num = Integer.parseInt(this.jpf1.getText().trim());//有无乘数法
5.decide()函数,产生整数,防止出现分数
1 private int decide(int x,int y,int max,int min){
2 Random random=new Random();
3 if(x%y!=0){
4 y=random.nextInt(max-min+1)+min;
5 return decide(x,y,max,min);
6 }
7 else{
8 return y;
9 }
10 }
6.start()方法,thread类的方法,真正实现了多线程运行,无需等待。run()方法必须是public访问权限,返回值类型为void。
1 thread.start(); // 计数线程一直运行
7.run()方法,thread类的方法,放有需要并行处理的代码,相当于普通方法的方式调用,程序顺序执行。
1 public void run() { 2 while (true) { 3 if (!stopped) { 4 long elapsed = System.currentTimeMillis() - programStart; 5 label.setText(format(elapsed)); 6 } 7 try { 8 sleep(1); // 1毫秒就更新1次 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 System.exit(1); 12 } 13 } 14 }
1 public class Command extends JFrame { 2 private static final long serialVersionUID = 1L; 3 // 定义登录界面的组件 4 JButton jb1, jb2, jb3 = null; 5 JPanel jp1, jp2, jp3, jp4,jp5,jp6= null; 6 JTextField jtf = null; 7 JTextField jpf = null; 8 9 JTextField jpfM = null; 10 11 JTextField jtf1 = null; 12 JTextField jpf1= null; 13 14 JLabel jlb1, jlb2,jlb3, jlb4= null; 15 ButtonGroup bg = null; 16 static int exepresionNum = 0; 17 18 static int exepresionRangeNum; 19 20 static int jtfNum = 0; 21 static int jpfNum = 0; 22 23 static int jpfMNum = 0; 24 25 static int jtf1Num = 1; 26 static int jpf1Num = 0; 27 28 public static void main(String[] args) { 29 new Command(); 30 } 31 32 // 构造函数 33 public Command() { 34 // 创建组件 35 jb1 = new JButton("确认"); 36 jb2 = new JButton("刷新"); 37 jb3 = new JButton("退出"); 38 // 设置监听 39 jb1.addActionListener(new ActionListener() { 40 41 @Override 42 public void actionPerformed(ActionEvent e) { 43 OK(); 44 } 45 }); 46 jb2.addActionListener(new ActionListener() { 47 48 @Override 49 public void actionPerformed(ActionEvent e) { 50 clear(); 51 } 52 }); 53 jb3.addActionListener(new ActionListener() { 54 55 @Override 56 public void actionPerformed(ActionEvent e) { 57 System.exit(0); 58 } 59 }); 60 61 jp1 = new JPanel(); 62 jp2 = new JPanel(); 63 jp3 = new JPanel(); 64 jp4 = new JPanel(); 65 jp5 = new JPanel(); 66 jp6 = new JPanel(); 67 68 jlb1 = new JLabel("生成题目个数:"); 69 jlb2 = new JLabel("题目数值范围:"); 70 jlb3 = new JLabel("操作符个数:"); 71 jlb4 = new JLabel("乘除法 0无1有:"); 72 73 jtf = new JTextField(10); 74 jpf = new JTextField(4); 75 76 jpfM = new JTextField(4); 77 78 jtf1 = new JTextField(10); 79 jpf1 = new JTextField(10); 80 // 加入到JPanel中 81 jp1.add(jlb1); 82 jp1.add(jtf); 83 84 jp2.add(jlb2);//jpfM是最大值 85 jp2.add(jpf); 86 jp2.add(jpfM); 87 88 89 jp5.add(jlb3); 90 jp5.add(jtf1); 91 92 jp6.add(jlb4); 93 jp6.add(jpf1); 94 95 jp4.add(jb1); 96 jp4.add(jb2); 97 jp4.add(jb3); 98 // 加入JFrame中 99 this.add(jp1); 100 this.add(jp2); 101 this.add(jp5); 102 this.add(jp6); 103 this.add(jp3); 104 this.add(jp4); 105 106 107 // 设置布局管理器 108 jlb1.setFont(new java.awt.Font("Dialog", 0, 20)); 109 jlb2.setFont(new java.awt.Font("Dialog", 0, 20)); 110 jlb3.setFont(new java.awt.Font("Dialog", 0, 20)); 111 jlb4.setFont(new java.awt.Font("Dialog", 0, 20)); 112 jtf.setFont(new Font("宋体", Font.PLAIN, 20)); 113 jpf.setFont(new Font("宋体", Font.PLAIN, 20)); 114 115 jpfM.setFont(new Font("宋体", Font.PLAIN, 20)); 116 117 jtf1.setFont(new Font("宋体", Font.PLAIN, 20)); 118 jpf1.setFont(new Font("宋体", Font.PLAIN, 20)); 119 Font f = new Font("华文行楷", Font.BOLD, 20); 120 jb1.setFont(f); 121 jb2.setFont(f); 122 jb3.setFont(f); 123 this.setLayout(new GridLayout(4, 1)); 124 // 给窗口设置标题 125 this.setTitle("小学生四则运算界面"); 126 // 设置窗体大小 127 this.setSize(600, 300); 128 // 设置窗体初始位置 129 this.setLocation(700, 330); 130 // 设置当关闭窗口时,保证JVM也退出 131 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 132 // 显示窗体 133 this.setVisible(true); 134 this.setResizable(true); 135 }
打印在result.txt文件中如下:
通过参数传值,类间调用等实现模块的对接(主要是Commandl类和Expression类)。参考Frofile教程,学习软件用了约三小时,内存消耗如图:分析可知相对稳定。
最初由项目的Command。java右键Profile As,进入性能分析,其次打开JVM虚拟机(可以用教程的密码破解Frofile软件)。然后进入Live memory,最初消耗变化如图:
等待两分钟后,出现红色绿色并存现象:
1 public static boolean scope(int num){ 2 if(num<=0||num>=10001) 3 return false; 4 else{ 5 return true; 6 } 7 8 }
1 try { 2 num = Integer.parseInt(args[++i]); 3 } catch (NumberFormatException e) { 4 e.printStackTrace(); 5 return; 6 }
第一个界面是选题要求,输入后进入答题模块:
第二个界面是答题计时界面,输入答案后进入判断界面:
第三个界面是反馈界面,判断有三种,分别是输入为空,输入答案正确,输入答案错误,还有记忆正确数量的功能(WriteReader类):
输入为空:
输入答案错误:
输入答案正确:
结对编程整体有如下的好处:
(1)在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力。
(2)对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
(3)在心理上, 当有另一个人在你身边和你紧密配合, 做同样一件事情的时候, 你不好意思开小差, 也不好意思糊弄。
(4)在企业管理层次上,结对能更有效地交流,相互学习和传递经验,能更好地处理人员流动。因为一个人的知识已经被其他人共享。
(5) 结对编程的过程也是一个互相督促的过程,每个人的一举一动都在别人的视线之内,所有的想法都要受到对方的评价。由于这种督促的压力,使得程序员更认真地工作。
(6) 程中驾驶员和领航员的互换可以让程序员轮流工作,从而避免出现过度思考而导致观察力和判断力下降。
结对编程对我和队友具体有如下的好处:遇到问题可以更好更快的解决,而且对一些细节可以进行分工,加快我们的实现进程。总之,如果运用得当,结对编程能得到更高的投入产出比(Return of Investment)。
结对编程有如下的缺点:
(1)并不是所有的项目都适合结对编程。
例如:1)处于探索阶段的项目,需要深入地研究,在这种情况下,一个人长时间的独立钻研是有必要的。
2)在做后期维护的时候,如果维护的技术含量不高,只需要做有效的复审即可,不必拘泥于形式,硬拉一个人来结对唱二人转。
3)处于探索阶段的项目,需要深入地研究,在这种情况下,一个人长时间的独立钻研是有必要的。
4)在做后期维护的时候,如果维护的技术含量不高,只需要做有效的复审即可,不必拘泥于形式,硬拉一个人来结对唱二人转。
5)如果验证测试需要运行很长时间,那么两个人在那里等待结果是有点浪费时间。
6)如果团队的人员要在多个项目中工作,不能充分保证足够的结对编程时间,那么成员要经常处于等待的状态,反而影响效率。
7)关键是如何最大限度地发挥“领航员”的作用,如果用处不大,也就无需结对。
结对编程对我和队友具体有如下的缺点:我们在结对的过程中彼此的想法会产生分歧,这有时也会浪费许多时间来达成共识。
采用汉堡包的方法对队友和自己评价:
卫小琼:优点:类间调用关系清晰;Debag能力不错,逻辑辨析能力出色;同学关系好,解决不了的问题能找到人帮忙
缺点:太过于追求细节,项目经验缺乏。
陈双林:优点:脾气好,能坚持,有上进心。
缺点:基础薄弱,编码能力弱。
|
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间 (min) |
Planning |
计划 |
30 |
40 |
· Estimate |
·估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
10 |
Development |
开发 |
1250 |
2375 |
·Analysis |
·需求分析 (含有学习新技术) |
300 |
400 |
·Design Spec |
·生成设计文档 |
20 |
30 |
·Design Review |
·设计复审 (和同事审核设计文档) |
10 |
20 |
·Coding Standard |
·代码规范 (为目前的开发制定合适的规范) |
15 |
20 |
·Design |
·具体设计 |
30 |
60 |
·Coding |
·具体编码 |
600 |
1500 |
·Code Review |
·代码复审 |
30 |
45 |
·Test |
·测试(自我测试,修改代码,提交修改) |
200 |
300 |
Modular |
模块 |
600 |
750 |
·Computing module | 计算模块 | 400 | 450 |
·Timing module | 计时模块 | 200 | 300 |
Reporting |
报告 |
490 |
850 |
·Test Report |
·测试报告 |
420 |
780 |
·Size Measurement |
·计算工作量 |
40 |
40 |
·Postmortem & Process Improvement Plan |
·事后总结, 并提出过程改进计划 |
30 |
30 |
尾言:
在结对项目中,长时间的交流和编写使我们学到很多,成长很快,很幸运有这样一次锻炼自己的机会。
博客1 https://blog.csdn.net/zhoufoxcn/article/details/1700018
博客2
博客3