UI第三组总结 PB16150206朱池苇+PB16070837刘鼎乾

项目简介

    这次软件工程结对项目为制作一个给小学生用的四则运算出题软件,我们分配到的是UI组,也就是负责人机交互使用Core组封装好模块。

    GitHub地址:https://github.com/Ignoramus0817/Calculation-GUI

 

需求分析

  •  对上述各属性参数(生成题目的数量,操作数的数量,题目及答案中的数值的范围……)进行设置
  •  调用Core模块得到题目和运算结果,显示题目,接受输入,并能判断答案是否正确
  •  增加倒计时功能,每个题目必须在20秒内完成,否则,得0分并进入下一题
  •  增加错题记录功能,对于答错的题,将其保存下来,当下次进行复习时,增大错题在练习题中的概率
  •  增加历史纪录功能,把用户做题的成绩纪录下来并可以展现历史纪录
  •  增加成绩分享功能,生成成绩单,想一想成绩单里要展现什么,仅仅是最后的得分吗?错题的类型及数量?帮用户分析其薄弱的环节,提出合理的学习建议?
  •  对所有Core组的模块进行测试

团队分工

     结对编程作业大部分的时间都是采取共同编写代码的方式,即“一个做驾驶员,一个做领航员,驾驶员负责敲键盘,领航员在一侧提供建议、检查错误或帮忙搜索相关的资料。

     就这次团队项目而言,合作比较愉快。清明节的后两天两人一起学习了Qt。由于朱池苇对Qt比较熟悉,所以大部分程序都是朱池苇同学作为驾驶员,而刘鼎乾同学则作为领航员,与朱池苇同学对问题进行讨论,查找资料,检查错误等。博客则由两人共同完成。

 

PSP 表格

PSP2.1任务内容计划完成需要的时间(min)实际完成需要的时间(min)
Estimate 估算 15 15
Analysis 需求分析(包括学习) 135 200
Design Spec 设计文档 15 15
Coding Standard 代码规范 10 10
Design 具体设计 60 120
Coding 具体编码 300 480
Code Review 代码复审 --(包含在编码过程中)  
Test 测试 120 300
Record Time Spent 记录用时 10 10
Test Report 测试报告 20 40
Size Measurement 计算工作量 20 10
Postmortem 总结改进 180 180
Summary 合计 885 1380

 

代码规范

 

一、命名风格

 

1、文件名:一律小写。

 

2、类名:一律使用UpperCamelCase。

 

3、变量名、对象名、方法名(函数名):一律使用lowerCamelCase。

 

 

 

二、代码风格

 

1、4空格缩进

 

2、左花括号换行

 

3、不同模块代码之间空行

 

4、预处理命令:

 

​ 文件包含:类和头文件分别集中,并且模块之间空格

 

​ 宏定义:宏名一律大写

 

 

 

三、其他

 

1、程序所有内容全部为英文,禁止出现中文和拼音,包括注释和UI界面文字。(博客下方展示代码块中注释是另外添加,程序中不含中文注释)

 

 

代码架构与具体实现

 

     UI界面布局设计由Qt Designer完成,而复杂逻辑则由Qt Creator完成。

 

     UI界面非常简单,由于使用qStackedWidget来实现翻页和题目的刷新,整个UI仅分为三个部分:主窗口CalGUI,存档对话框SaveSuccess,以及历史记录对话框History。绝大部分的功能都在主窗口上实现,存档对话框以及历史记录对话框仅有显示功能,因此着重介绍主窗口的结构和实现。

 

     主窗口上添加StackedWidget控件,分成三页:

 

     第一页:初始化生成条件

 

     本页主要由各种数字输入框(SpinBox)和选项按钮(CheckBox、RadioButton)构成,用SpinBox::valueCheckBox::isCheckedRadioButton::isChecked获取用户输入的值,而通过设定默认值和输入范围的方法,可以限制非法输入。

 

     本页包含两个按钮(PushButton),Next和Cancel,Cancel顾名思义是退出,而Next则是说明已经设定完毕,可以开始做题,因此,Next的槽中调用了Core中的Setting接口。当用户按下Next时,各个参数已经设置完毕。

 

     第二页:显示题目和题号、输入答案、倒计时

 

     本页有两个按钮Start和Next,分别实现“开始”和“下一题”,Next按钮初始状态为隐藏,当Start被按下时显示。Start按钮使第一个题目显示在一个文本浏览框TextBrowser中,并使计时器开始倒计时。

 

     倒计时的实现:

//添加在Start按钮按下信号的槽函数中
void CalGUI::on_startButton_clicked()
{
    QTimer *timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,&CalGUI::timerUpdate);
    timer->start(1000);
}

//刷新时间的函数
void CalGUI::timerUpdate()
{
    int a=ui->restTime->value();
    if(a>0)
        ui->restTime->display(a-1);
    else
        ui->qNext->clicked();  //如果时间耗尽,发出Next按钮按下的信号,自动跳转至下一题。
}

//timer的信号函数设置为空
void CalGUI::timeOut()
{
}

     Next按钮控制界面的刷新(重新向控件中写入数据即可)以及对错的判断,判断正误,获取LineEdit中字符串,和答案字符串比较即可。若正确,做对的题目加一,若错误,存储至错题部分。

     将Timer的时间耗尽和Next的按下两个信号连接在一起,即可方便地实现时间耗尽自动跳转的功能,由于判断正误由Next控制,因此将两者合并不会造成误判。

     用两个QLabel分别显示当前题号和总题数。在Next槽函数中比较两个QLabel对应数字的大小(Qt提供了相关转换函数,非常方便),当前者大于后者时,进入显示结果页面。

     第三页:显示结果,存档和查看历史记录

     结果显示即为前面做题时存储的正确题目数量、错题、正确率的显示。

     存档按钮控制生成.txt存档文件(由于没有掌握对话框数据传递,偷了个懒不让用户自行输入文件名),历史记录按钮控制查看往期记录(包括时间、正确题目数、总题目数、正确率、错题、错误答案和正确答案)。比较简单。

 

测试结果

 

参数设置页面

 

 

开始答题前

 

开始答题后

 

结果(太难无法口算因此全错)

 

结果2(为了展示错题和正确率统计故意错一半)

 

历史记录对话框

BUG记录与分析

 

    1、LNK2019 无法解析的外部命令

 

     这是编写UI和对接过程中遇到最多的一个BUG。

 

     如果是在编写UI本身过程中遇到,一般是给出了函数声明,但是没有具体实现所导致的,在.h+.cpp这种类定义和成员函数定义分离的情况下,此类错误极易出现。我认为较好的方法是,声明后立刻在cpp文件中撰写函数定义,如果暂且不需要写,可以用花括号留空。

 

     如果是在对接过程中遇到,不可能是相关函数core组同学没有定义。则一般是lib文件没有正常加载,或者是dll文件的属性(位数x86还是x64、debug还是release)与编译环境的属性不匹配所导致的。合理地发布SDK就能解决这种问题,所谓合理,指的是发布时分类,并且指明相应SDK的属性。

 

 

 

    2、无法打开xxxx.lib文件

 

    这是库文件没有正常加载导致的,Qt Creator中.lib文件的加载方式和VS中有所不同,需要在.pro文件中新增格式如下的代码:

LIBS +=-L$$quote(D:\zhu\Software Engineering\2018-SE-Course\Calculator GUI\CalGUI\untitled\Core15\x64) -lCore15
或
LIBS +=-LD:\zhu\SoftwareEngineering\2018-SE-Course\CalculatorGUI\CalGUI\untitled\Core15\x64 -lCore15

     其中-L后接.lib文件的绝对路径,-l后接.lib文件不加拓展名的文件名。如果路径中含有括号,应该使用$$quote()将路径括起。

     值得注意的是,假如需要将源代码发给他人,此处绝对路径需要修改为相对路径,否则无法正常加载。

     许多组发布SDK时仅仅注明了Qt for VS的使用方法,而忽略了Qt Creator的使用方法。

 

    3、函数参数表无法将xxx转换为xxx

     这种BUG本是函数传入的参数和参数表不一致导致的,是编程时出现的失误,为何要在此处列出呢?因为Qt虽然支持部分C++库和语法,但两者仍然有区别。

     比如Qt中的字符串类为QString,而C++中类为string(std::string),需要经过QString::fromStdString转换,才可以使用。

     这种差异的存在导致对接过程中此类BUG大量出现,小心一些即可避免。

 

在与第七组对接后的BUG和解决方案:

 

    1、显示结果页面正确率和正确题数显示不正常(由于计时器信号未阻塞,会导致正确题目数量不断增加,又由于正确率为实时计算,因此正确率也会不断增加),跳至结果页面后,阻塞计时器信号即可解决。

 

 

    2、分辨率问题,控件无法自适应窗口大小和分辨率。修改UI布局可以解决(推荐刚开始编写UI时就考虑这个问题,否则会产生巨大的工作量)。

 

 

 

 

    3、运行时有命令行(见上图),修改Qt设置文件,将CONFIG += console改为CONFIG += release即可。

 

由编程得出的一些建议

     1、发布SDK时一定要根据编译环境和平台分类。

     2、勤于写README,并且在写README时要考虑各种用户的需求(比如VS用户和Qt Creator用户)。

     3、接口越少越好(接口数和参数数量折中)。

 

工作时刻

 

结对编程的意义相关 

  • 一个人编写代码,总是有种灯下黑的现象。一些非常简单的错误,由驾驶员自己是很难检查出来的,旁观者清,领航员则能够较为轻易地发现。
  • 结对编程相当于在编写代码的同时,进行复审,这可以使驾驶员能够“朝着目标方向”前进,代码规范、算法思想、以及最重要的,概念完整性,可以得到保障。
  • 可以不断从别人那里学习,提高自己的水平。在他人的监督下写代码有利于形成良好的代码风格,清晰的编码思路,以及熟练的调试技巧等
  • 两个人的知识结构可以互补,比如驾驶员拥有稳重的编程风格和严谨的代码规范,但不善于设计巧妙的算法;而领航员则有灵活的头脑,两者结合,可以使代码高效、优雅而不失严谨,不会成为“奇技淫巧”。

关于走上工作岗位后是否会选择结对编程

刘鼎乾)我认为我会选择结对编程。不仅是因为队友之间能相互找到彼此的灯下黑,还因为能在工作之余和别人进行交流,切磋。这也是不断提高自己,终身学习的有效途径。

朱池苇在工程需要迅速完成且规模不大时,我不会选择结对编程;但在工作量大的工程中,结对编程无疑是有其意义的。工程较大时,思路容易混乱,或者因为繁琐的各种定义而犯一些低级的错误。结对编程大大减少了这方面的成本。

 

课程建议:

  (刘鼎乾我认为邓老师确实非常非常负责,很认真地想把这门课上好,但是我觉得还是有一些问题。

      1、上课不只是讲软件工程的理论,还希望能多讲一些实际编程有关的东西。
      2、安排大作业和结对编程的时候,尽量和期中考等考试分开,能不影响大家的gpa就不影响。希望后面补做个人作业和结对编程时,不要放在和期末考冲突的时候,可以考虑放在暑假。
      3、我觉得为了难而难是不可取的。有些时候加大难度我感觉不是很有现实意义。而我们工科是非常讲究现实意义的。增加难度可以,但要建立在实际有用的基础上,如果为了难为我们而故意弄一些很繁琐的事情,我觉得并不可取。

 

  (朱池苇目前我选这门课的目的基本上都实现了:了解自己技术栈的缺陷、体验一下稍难一些的工程、磨炼编程技术和肝功能(逃)。因此意见也不多。主要如下:

  希望能具体介绍一下哪种工程师需要精通哪些技能(比如:前端工程师必须精通HTMLXML,JSCSSjsonajax等等),使我们课外自己学习更有方向性,我在这方面比较迷茫,哪些东西是会有用的,它们是用来干嘛的。如果能推荐一些教材或者学习时可以设定的目标等等就更好了。

 

团队项目如何改进    

  与结对编程类似,一个团队中一般都有所谓“架构师”“产品负责人”的存在,这些人对技术或是需求非常了解,他们应该成为团队的领航员,由他们规定工程的架构和规范,所有人需要根据他们设定的规则完成自己的工作。

  而复审工作则不是同时进行的,而是完成一个部分后将代码交由领航员审核,对其中不恰当的部分进行修正。

  同时组内工作职能相近的同学也可以采用标准的结对编程方式。

 

 

posted @ 2018-04-16 00:43  Ignoramus  阅读(524)  评论(1编辑  收藏  举报