201771010123-汪慧和 实验三 结对项目—《西北师范大学疫情防控信息系统》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | https://edu.cnblogs.com/campus/xbsf/nwnu2020SE |
作业要求链接 | https://www.cnblogs.com/nwnu-daizh/p/12521474.html |
我的课程学习目标 | (1)体验软件项目开发中的两人合作,练习结对编程。(2)掌握Github协作开发程序的操作方法。 |
这个作业作业在哪些方面帮助我实现学习目标 | 两人合作练习结对编程、掌握Github协作开发程序的操作方法以及运用学习工具 |
结对方学号-姓名 | 201771010136-杨野 |
结对方本次博客作业链接 | https://www.cnblogs.com/2017xinghui/p/12554158.html |
本项目Github的仓库链接地址 | https://github.com/yy202901582/DieaseSubmitSystem |
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;
已阅读完,相关概念如下:
1、代码风格规范
(1)代码风格的原则是:简明,易读,无二义性。
(2)缩进:4个空格,不用Tab键是因为在不同的情况下显示的长度可能不一样。
(3)行宽:限定为100字符。
(4)括号:在复杂的条件表达式中,可以清晰地表示逻辑优先级。
(5)断行与空白的{}行:断行在程序调试时可以清晰的表达变量的变化情况,{}来判断程序的结构。
(6)分行:不要把多个变量定义在一行上。
(7)命名:
①在变量名中不要提到类型或其他语法方面的描述。
②避免过多的描述。
③如果信息可以从上下文中得到,那么此类信息就不必写在变量名中。
④避免可要可不要的修饰词。
(8)下划线:用来分割变量名字中的作用域标注和变量的语义。
(9)大小写:
①所有类型/类/函数名都用Pascal形式(所有单词第一个字母都大写)。
②所有变量都用Camel形式(第一个单词全部小写,随后单词用Pascal形式)。
③类/类型/变量:名词或组合名词。
④函数则用动词或动宾组合词来表示。
(10)注释:注释是为了解释程序做什么(What),为什么这样做(Why)以及要特别注意的地方。
2、代码设计规范
(1)概念:代码设计规范不光是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方方面面,又有不少内容与具体程序设计语言息息相关(如C,C++,JAVA,C#),但是也有通用的原则。
(2)函数:原则:只做一件事,并且要做好。
(3)goto:函数最好有单一出口,为了达到这一目的,可以使用goto。
(4)错误处理:
①参数处理:在Debug版本中,所有的参数都要验证其正确性,在正式版本中,对从外部(用户或别的模块)传递过来的参数,要验证其正确性。
②断言:验证正确性就要用断言。
(5)如何处理C++中的类
①类:
a.使用类来封装面向对象的概念和多态。
b.避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要要用类来实现。
c.对于有显示的构造和析构的类,不要建立全局的实体,因为不知道它们在何时创建和消除。
d.仅在有必要时,才是用“类”。
②class vs.struct:如果只是数据的封装,用struct即可。
③公共/保护/私有成员:按照这样的次序来说明类中的成员。
④数据成员:
a.数据类型的成员用m_name说明。
b.不要使用公共的数据成员,要用inline访问函数,这样可兼顾封装和效率。
⑤虚函数
a.使用虚函数来实现多态。
b.仅在很有必要时,才使用虚函数。
c.如果一个类型要实现多态,在基类中的析构函数应该是虚函数。
⑥构造函数
a.不要在构造函数中做复杂的操作,简单初始化所有成员即可。
b.构造函数不应该返回错误。
⑦析构函数
a.把所有的清理工作都放在析构函数中。如果有些析构函数在之前就释放了,要重置这些成员为0或NULL。
b.析构函数也不应该出错。
⑧new和delete
a.如果可能,实现自己的new/delete,这样可以方便地加上自己的跟踪和管理机制。自己的new/delete可以包装系统提供的new/delete。
b.检查new的返回值。new不一定都成功。
c.释放指针时不用检查NULL。
⑨运算符
a.在理想情况下,我们定义的类不需要自定义操作符。确有必要时,才会自定义操作符。
b.运算符不要做标准语义之外的任何动作。
c.运算符的实现必须非常有效率,如果有复杂的操作,应定义一个单独的函数。
d.当拿不定注意时,用成员函数,不要用运算符。
⑩异常
a.不要用异常作为逻辑控制来处理程序的主要流程。
b.当使用异常时,要注意在什么地方清理数据。
c.异常不能跨过DLL或进程的边界来传递消息,所以异常不是万能的。
⑪类型继承
a.仅在有必要时,才使用类型继承。
b.用const标注只读的参数。
c.用const标注不改变数据的函数。
3、代码复审:看代码是否在代码规范的框架内正确的解决了问题。代码复审的形式包括:自我复审、同伴复审、团队复审。
4、结对编程:结对编程中有两个角色:领航员和驾驶员。在个人编写的过程中,很多人喜欢根据个人喜好来规定代码规范,而且存在的bug自己难以发现,因此,在结对编程时,我们可以互换角色,在开始写代码之前,规定两个人都认可的一套代码规范,并且不间断地进行复审,以减少软件中存在的问题,修复bug,提高软件质量。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价,具体要求如下:
对项目博文作业进行阅读并进行评论,评论要点包括:博文结构、博文内容、博文结构与PSP中“任务内容”列的关系、PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究,将以上评论内容发布到博客评论区。
结对伙伴:
结对方博客链接
https://www.cnblogs.com/2017xinghui/p/12452438.html
结对方Github项目仓库链接
https://github.com/yy202901582/DieaseSubmitSystem
克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。
1、概要部分
(1)代码符合需求和规格说明么?
答:部分符合需求与规格。
(2)代码设计是否有周全考虑?
答:基本周全,改动的地方很少。
(3)代码可读性如何?
答:可读性好。
(4)代码容易维护么?
答:较易。
(5)代码的每一行都执行并检查过了吗?
答:是的,检查过。
2、设计规范部分
(1)设计是否遵从已知的设计模式或项目中常用的模式?
答:部分遵从。
(2)有没有硬编码或字符串/数字等存在?
答:有一部分。
(3)代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)
答:没有依赖,不会影响移植。
(4)开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现?
答:可以实现,存在,调用了一部分。
(5)有没有无用的代码可以清除?(很多人想保留尽可能多的代码,因为以后可能会用上,这样导致程序文件中有很多注释掉的代码,这些代码都可以删除,因为源代码控制已经保存了原来的老代码。)
答:有,基本清除完毕。
3、代码规范部分
(1)修改的部分符合代码标准和风格么(详细条文略)?
答:大部分代码符合,不符合的已修改。
4、具体代码部分
(1)有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
答:对错误进行了处理,检查了返回值,并处理了异常。
(2)参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数?
答:无错误,字符串的长度是字节的长度,是以0开始计数。
(3)边界条件是如何处理的?Switch语句的Default是如何处理的?循环有没有可能出现死循环?
答:结对伙伴未用到Switch语句,没有出现死循环,循环语句正确。
(4)有没有使用断言(Assert)来保证我们认为不变的条件真的满足?
答:没有使用。
(5)对资源的利用,是在哪里申请,在哪里释放的?有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有可能优化?
答:是随机生成的,不会导致资源泄漏,有可能优化。
(6)数据结构中是否有无用的元素?
答:没有。
5、效能
(1)代码的效能(Performance)如何?最坏的情况是怎样的?
答:代码正确,程序运行正常。
(2)代码中,特别是循环中是否有明显可优化的部分(C++中反复创建类,C#中 string 的操作是否能用StringBuilder 来优化)?
答:没有可优化地方,比较优化。
(3)对于系统和网络调用是否会超时?如何处理?
答:不会超时。
6、可读性
代码可读性如何?有没有足够的注释?
答:代码不是很复杂,有足够的注释。
7、可测试性
代码是否需要更新或创建新的单元测试?还可以有针对特定领域开发(如数据库、网页、多线程等)的核查表。
答:不需要。
结对方的项目仓库原本Fork、Clone、Push、Pull request、Merge pull request日志数据如下。
使用git命令clone结对方仓库到本地便于查看修改
对代码的一些更改操作
作出回应,并关闭
任务3:采用两人结对编程方式,结合我校师生疫情每日上报系统使用体验,设计开发一款符合我校疫情防控工作需求的信息系统,使之具有以下功能:
(1)可采集全校各类师生员工疫情信息;
(2)各二级部门疫情防控工作负责人可查看本部门人员疫情汇总,并提供高级查询功能进行多属性组合查询和可视化统计功能;
(3)学校防控办指定负责人登录《西北师范大学疫情防控信息统计》子系统,可浏览所有人员填报汇总数据清单,利用【高级查询】可进行数据组合筛选,系统以图形化方式展示各学院已填报和未填报学生统计情况和关键疫情数据统计情况,可【导出】查询列表的EXCEL文件;
(4)人机交互界面要求GUI界面(WEB页面、APP页面都可);
(5)附加分功能:定时填报提醒
1、需求分析陈述。
就(1)而言,要求能采集全校学生/教职工的疫情信息。我们将用户填写的数据保存在txt文件中,作为数据便于后续使用。
就(2)而言,要求各二级部门疫情防控工作负责人可查看本部门人员疫情汇总,并能够进行多属性组合查询和可视化统计功能。我们做了学院查询,姓名查询以及地区查询和是否感染查询等多种组合查询,并用饼状图直观地表示查询到结果的信息。
就(3)而言,要求学校负责人登录子系统,可浏览所有人员填报汇总数据清单,可进行数据组合筛选查询,以图形化方式展示各学院已填报和未填报学生统计情况和关键疫情数据统计情况,可【导出】查询列表的EXCEL文件。我们将用户填写的信息保存在txt文件中,方便查阅。
就(4)而言,我们采用了GUI界面,并在之前讨论了界面的大致样子,并绘图,如下图所示:
就(5)而言,我们采用了弹出框的形式来提示用户,询问用户是否填写,若用户填写,则不再提醒。否则每隔10分钟提醒一次
2、.软件设计说明。
(1)软件界面设计
包括搜索菜单,图标功能,提醒功能和填报功能,在界面设计上,采用简单明了,易于操作的原则,凸显出了要求功能。
(2)工程项目图:
其中writetxt生成txt文件。
(3)主要的功能:
1)师生可登录系统进行疫情信息的填报;
2)二级防疫部门人员可进行疫情信息的填报;
3)二级防疫部门负责人可可根据姓名进行模糊查询,根据姓名、学院、感染情况进行准确查询,可查看感染情况的统计数据(用柱状图来表示)。
3、软件实现及核心功能代码展示:软件包括哪些类,这些类分别负责什么功能,他们之间的关系怎样?类内有哪些重要的方法,关键的方法是否需要画出流程图?
工程结构说明:
。chart:存放生成的图表
。img:存放系统图标
。src:存放具体代码
。Text.txt:存放数据
src说明:
。Frame.java
绘制界面内容,与事件的监听处理
。MenuTnput.java
其中有initializeGragh方法,主要用于初始化内容,包括数据计数和生成graph
。ProduceChart.java
生成数据统计图,借用了插件JFreeChart Java图表库。里面有ProduceChart,ProduceChartC2,生成柱状图和扇形图的方法,生成的在chart文件中。
。Search.java
增加方法BuildGragh(),生成图表的包装函数,一次执行完生成图表。
。SthFunction.java
其中有采集数据的方法:Insert_Message,会在action事件中被调用
。listMain.java
主函数,运行入口,其中实例化了MenuTnput,ReadFile进行初始化工作,再通过frame生成swing界面
。writetxt.java
生成Text.txt中数据信息
4、程序运行:程序运行时每个功能界面截图。扩展功能实现可得附加分5分。
二级防疫部门负责人可输入各自学院筛选查看:
查询某个人的状况:
所在地查询:
是否感染查询:
图标可视化,可以根据出现的字段生成相应的图表:
学院,饼状图和柱状图显示:
师生比:
所在地:
感染情况:
填报信息:
定时提醒
数据文件展示
5、核心功能代码展示
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import org.jfree.chart.*;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.general.DefaultPieDataset;
/**
* Created by IntelliJ IDEA.
* User: YANG
*/
public class ProduceChart {
/**
* 生成扇形统计图
*
*/
public void ProduceChartC(String[][] GraphList,int[][] ListCount){
String[] list = new String[]{"college","place","ID","timeM","timeD","situation"};
Font font = new Font("宋体", Font.BOLD, 20);
try {
for (int j = 0; j < 6; j++) {
DefaultPieDataset dataset = new DefaultPieDataset();
for (int i = 0; i < GraphList[0].length; i++) {
if (GraphList[j][i]!=null){
double count = ListCount[j][i];
String Gcount = GraphList[j][i]+ListCount[j][i];
dataset.setValue(Gcount,count);
}
}
//创建图
JFreeChart chart = ChartFactory.createPieChart(
list[j], // chart title
dataset, // data
true, // include legend
true,
false);
int width = 1000;
int height = 800;
//设置字体
chart.getTitle().setFont(font);
chart.getLegend().setItemFont(font);
PiePlot piePlot = (PiePlot) chart.getPlot();
piePlot.setLabelFont(font);
chart.getLegend().setItemFont(font);
// 改样式
chart.setTextAntiAlias(true);
chart.setBackgroundPaint(ChartColor.WHITE);
piePlot.setBackgroundPaint(ChartColor.WHITE);
// 关闭片区外廓
piePlot.setSectionOutlinesVisible(false);
// 生成jpeg
String pathname = "chart//"+list[j]+".jpeg";
File pieChart = new File(pathname);
ChartUtilities.saveChartAsJPEG( pieChart , chart , width , height );
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 生成柱统计图
*
*/
public void ProduceChartC2(String[][] GraphList,int[][] ListCount){
String[] list = new String[]{"college","place","ID","timeM","timeD","situation"};
Font font = new Font("宋体", Font.BOLD, 20);
try {
for (int j = 0; j < 6; j++) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < GraphList[0].length; i++) {
if (GraphList[j][i]!=null){
double count = ListCount[j][i];
String str = GraphList[j][i]+ListCount[j][i];
dataset.addValue(count,str,list[j]);
}
}
//创建图
JFreeChart chart = ChartFactory.createBarChart(
list[j], //标题
"x", //x轴名称
"y", //y轴名称
dataset,//数据集
PlotOrientation.VERTICAL,//使用垂直柱状图
true,//是否使用legend
false,//是否使用tooltip
false); //是否使用url
int width = 1000;
int height = 800;
//设置字体
chart.getTitle().setFont(font);
chart.getLegend().setItemFont(font);
chart.getLegend().setItemFont(font);
// 改样式
chart.setTextAntiAlias(false);
chart.setBackgroundPaint(ChartColor.WHITE);
// 生成jpeg
String pathname = "chart//"+list[j]+"1.jpeg";
File pieChart = new File(pathname);
ChartUtilities.saveChartAsJPEG( pieChart , chart , width , height );
// 生成png
String pathname2 = "chart//"+list[j]+"1.png";
File pieChart2 = new File(pathname2);
ChartUtilities.saveChartAsPNG( pieChart2, chart , width , height );
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
6、描述结对的过程,提供两人在讨论、细化和编程时的微信或QQ截图(截图要完整,能够显示结对双方姓名)
7、提供此次结对作业的PSP
PSP | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Estimate | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 30 |
Development | 开发 | 2585 | 1705 |
Analysis | 需求分析 (包括学习新技术) | 20 | 20 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审(和同事审核设计文档) | 10 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 5 | 5 |
Design | 具体设计 | 900 | 500 |
Coding | 具体编码 | 1440 | 960 |
Code Review | 代码复审 | 180 | 180 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 30 | 30 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 30 | 30 |
8、小结感受:两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。
通过本次合作我觉得两个人合作做项目比一个人独自做效果要好很多。在项目完成方面,结对编程会带来1+1>2的效果,在编写程序遇到问题时,可以及时的向同伴求助,特别感谢我这次的结对编程伙伴杨野同学。我在写程序时遇到好几个问题都是他帮我解决的。通过这次合作我真真体会到了结对编程的乐趣和互相督促的进步。结对编程还可以找出自己代码的不足之处,以及版本的兼容问题。比如在我的的电脑上字体显示正常,结果到编程伙伴的电脑上出现乱码,通过这种相互测试,可以更好的优化自己的程序。再次特别感谢杨野同学。