一、链接
-
201521123043 杨晨露 http://www.cnblogs.com/ycll/
-
201521123038 游舒婷 https://home.cnblogs.com/u/sakurai3104
-
结对编程码云地址: https://gitee.com/sakurai3104/pair_programming/commits/szys
二、代码
1. 需求分析:
- 现有代码实现简单的加减乘除算术出题运算,提供三种语言的切换,有复习,计时,判断正确率的功能
- 对现有代码进行分析,发现如下问题:
- (1)复习功能不完善,复习的按钮在初始界面,点击之后跳回初始界面,无法再进行下一步的点击
- (2)初始界面较为粗糙,界面出现在屏幕左上角,用起来很难受。语言切换非常不明显,整体布局也不太符合人体习惯
- (3)文档作用不明显,对于源代码的分析了解基本是我们从代码直接进行分析的。变量名设置比较随意,一些重要框架没有说清楚。
- (4)因为软件面向的对象定为小学生,所以两个数的加减乘除的数取值在100以内,混合运算的取值则在10以内,相对符合现在学生情况。
- (5)原本的“再一次”和“复习”功能存在bug,重新进行选择不会读取用户再一次输入的题目数量。另外“复习”部分只会弹出当此的题目,而不会从错题库中随机读取,比较不符合练习题的规范。
- (6)未对重复题目的出现进行判断
- 进行优化的部分:
- 更改初始界面,初始界面增加“复习”部分,语言选择改为菜单栏选项。在不对界面框架做大的更改的情况下,增加按键,修改布局,界面显示在电脑屏幕正中间。
- 优化界面显示和跳转,在第二个界面加上“结束”部分,优化用户手感问题。同时添加跳出所有正确答案功能,在希望结束的时候不用去点击右上角的,而是可以自己选择结束暂停。
- 新增平方和括号的计算,并在原来只针对分数的加减乘除的计算题扩大范围。
- 关于计算部分的优化,经过一定的搜索,现在的小学生混合运算主要偏向于能够快速化简的分数除法,我们的代码还暂时无法达到这个要求,这个也需要进一步的升级。
- 优化上述第五点的问题,实现了一个较为正常的“复习”功能和“再一次”的选择
- 优化上述第六点的问题,解决了对于历史题目重复出题的bug。但是对于一开始随机的出题的重复率判断,有尝试解决,结果发现了源代码更大的bug。在解决重复出题的过程中,这些bug都一一解决了,然而这个最开始的问题......还是凉了。详情见队友博客。
2. 程序设计:
2.1 码云提交记录
2.2 类图部分
2.3 覆盖率测试
其中覆盖率偏低的几个类,都存在或多或少的测试局限问题,比如下图,分母等于0的概率实在太低,太难触发
这部分是关于做题时长的测试,当做题时间过长才会出现
还有这里是对于历史存储的问题,因为有原文件的存在,所以没有触发
另外大部分的问题都在于代码的异常捕获,这个......真的挺难触发的
2.4 逻辑图部分,红色的表示我们做了优化或是新增的功能
2.5 内存分析优化
3. 代码展示:
public String fra_operation(){ //复杂运算
this.t1 = new Random().nextInt(10)%(10-1+1) + 1;
this.t2 = new Random().nextInt(10)%(10-2+1) + 2;
this.t3 = new Random().nextInt(10)%(10-1+1) + 1;
this.t4 = new Random().nextInt(10)%(10-2+1) + 2;
int fz=1,fm=t2*t4; //分子,分母
if(k==1)//除法
{
if(t2<t1||t4<t3||t2%t1==0||t4%t3==0)
{
astr=fra_operation();
return astr;
}
if(k1==0)
{
fz=t1*t4+t2*t3;
}
if(k1==1){
fz=t1*t4-t2*t3;
if(fz==0)
{
return astr=("0");
}
}
if(k1==2)
fz=t1*t3;
if(k1==3)
{
fz=t1*t4;
fm=t2*t3;
}
int f=common_divisor(fm,fz);
if(f>0){
fm=fm/f;
fz=fz/f;
}
if(f<0){
fm=-fm/f;
fz=-fz/f;
}
astr = (fz+"/"+fm);
if(astr.equals("1/1")) astr="1";
if(fm==1) astr = (fz+"");
}
else if(k==0)//乘法
{
fm=1;
if(k1==0)//加法
{
if(k2==3)
fz=t1*(t2+t3)*t4;
else fz=t1*t2+t3*t4;
}
if(k1==1)//减法
{
if(k2==3)
fz=t1*(t2-t3)*t4;
else fz=t1*t2-t3*t4;
}
if(k1==2)//乘法
{
fz=t1*t2*t3*t4;
}
if(k1==3)//除法
{
if(k2==1)//t1*t2/(t3*t4)
{
if(t1==0||t2==0) return astr=("0");
else if(t3==0||t4==0)
{
astr=fra_operation();
return astr;
}
else{
fz=t1*t2;
fm=t3*t4;
}
}
else //if(k2==0) t1*t2/t3*t4
{
if(t3==0)
{
astr=fra_operation();
return astr;
}
else if(t1==0||t2==0||t4==0) return astr=("0");
else{
fz=t1*t2*t4;
fm=t3;
}
}
int f=common_divisor(fm,fz);
if(f>0){
fm=fm/f;
fz=fz/f;
}
if(f<0){
fm=-fm/f;
fz=-fz/f;
}
astr = (fz+"/"+fm);
}
if(k1!=3) astr=fz+"";
if(fm==1) astr = (fz+"");
}
if(astr.equals("1/1")) astr="1"; //修改 bug 1
return astr;
}
//复习键
private void Re_ButtonMouseClicked(MouseEvent evt) throws FileNotFoundException {
if(Number.getText().matches("\\d*")){
Frame.hh.i = Integer.parseInt(Number.getText()); //获取输入题数
if(Frame.hh.i<=10&&Frame.hh.i>=1)
{
Frame.hs.Histroy_read();
for(int a=0;a<Frame.hh.i;a++){
int b = new Random().nextInt(Frame.hs.astrlist.size()-1);
Frame.hh.Answer.set(a, Frame.hs.astrlist.get(b));
Frame.hh.Qusetion.set(a, Frame.hs.qstrlist.get(b));
List<Integer> count=new ArrayList<Integer>(Arrays.asList(list));
if(count.contains(b)) a--;
else list[a]=b;
}
for(int a=0;a<(10-Frame.hh.i);a++){
Frame.hh.Answer.set(a+Frame.hh.i, "");
Frame.hh.Qusetion.set(a+Frame.hh.i, "");
}
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Frame(true).setVisible(true);
}
});
this.dispose();
i++;
try {
Frame.hs.History_num();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
public class QA_List {
public static int i=0;
public static List<String> Qusetion;
public static List<String> Answer;
public QA_List(){
Qusetion=new ArrayList<String>();
Answer=new ArrayList<String>();
for(int a=0;a<i;a++)
{
Runtime.getRuntime().gc();
boolean flag= new Random().nextBoolean();
Arithmetic hh = new Arithmetic(flag);
String int_str = hh.int_operation();
String fra_str = hh.fra_operation();
if(flag==true) //
{
Answer.add(int_str);
Qusetion.add(hh.toString());
}
if(flag==false) //
{
Answer.add(fra_str);
Qusetion.add(hh.toString());
}
System.out.println(Answer.get(a)+" "+Qusetion.get(a));
}
for(int a=0;a<(10-i);a++){
Answer.add("");
Qusetion.add("");
}
}
}
4. 程序运行:
- 由于在开发过程中我不做结果正确率的测试,所以截图里的正确率偏低。
5. 小结感受:
- 先说一点,,,我认为开发工具的统一十分重要。就比如我们使用的源代码的图形界面时在netbeans的环境下直接拖选的,netbeans会生成大量的无用代码以及框架比较难以更改。在此基础上,手动修改的难度就比较大。
- 回到正题,我认为结对编程可以带来1+1>2的效果。首先,每个人擅长的方向不一样,一个软件的开发是需要各方各面的功能的。一个人很难做到面面精通,所以通过合作,可以让开发效果,从技术水平上来说达到最好。
- 另外,一个人的思路总是狭窄的。比起两个人一起,一个人更容易钻牛角尖。比如我在调试一个界面的位置问题时,总是没法调整到想要的地方,也查不到能用的函数,队友换了个关键词一下子就查到了。我简直怀疑她和我用的不是同一个百度。就,总的来说,很多时候有个能讨论的人,在开发的时候不会太过于局限,不管是思路还是设计都会开阔很多。
- 在原本的代码框架上进行修改相对困难,但是好处是基础都有,只要优化就行了,不过也有不少功能需要把之前的方法推翻重来。
- 还有一点就是,结对编程对于水平稍微弱一点的人来说,其实是很好的。
分工合作愉快 队友身体不舒服一周了,挺艰难的- 以及......在思考的时候被打断,是真的需要全部重新思考的......我们深刻体会了这个道理
(亲身体验,真的)
三、 结对编程照片
由于两人非同宿舍,图书馆讨论不方便。再由于我们这一次的编程周期偏长,基本用了一周半的时间,时间也不能完全对的上,所以我们都是在QQ上互相交流和讨论的。比如我在外面的时候,她在编程,遇到的问题和一些地方都会提出来一起讨论。所以要两人非摆拍的一起讨论的照片......那是没有的。我们只提供得了聊天记录截图......(内容有点多......)