201771030106-葛佳诚 实验三 结对项目—《西北师范大学疫情防控信息系统》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | https://edu.cnblogs.com/campus/xbsf/nwnu2020SE |
作业要求链接 | https://www.cnblogs.com/nwnu-daizh/p/12521474.html |
我的课程学习目标 | 1.体验软件项目开发中的两人合作,练习结对编程; 2.学习Github协作开发程序的操作方法。 |
结对方学号-姓名 | 201771030103-陈正丽 |
结对方本次博客作业链接 | https://www.cnblogs.com/chenzhengli-/p/12556980.html |
作业对我实现学习目标的帮助 | 1.掌握了两人结对编程软件项目的大致流程; 2.熟悉了GitHub协作开发程序的基本流程。 |
项目Github的仓库链接地址 | https://github.com/luorrr/SchoolInfoSystem https://github.com/luorrr/UniversityInfoSystem |
任务一. 阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念
“代码规范”可以分成两个部分——代码风格规范和代码设计规范。其中代码风格规范是我们平时较容易忽略的,其原则是:简明、易读、无二义性,它主要包括代码的缩进、注释、括号等方面。
代码复审对我们代码中错误的改正十分有帮助,能够帮助减少最终代码的错误,同时也能在一定程度上优化其结构,使我们的代码更加简明、易读。
结对编程作为一种敏捷软件开发的方法,它是指两个程序员在一个计算机上共同工作,一个人输入代码,而另一个人审查对方输入的每一行代码。结对编程对于减少代码的错误率与实现更多更全面的功能有较大的帮助。
任务二. 两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价
(一). 对项目博文作业进行阅读并进行评论
对同伴的博客进行评价如下图。
图1.1.1 cnblogs
(二). 克隆结对方项目源码,阅读并测试运行代码,复审同伴项目代码并记录
将同伴的项目clone至本地。
图1.2.1 clone
代码复审情况如下。
图1.2.2 代码审核表
(三). 依据复审结果利用github的Fork、Clone等操作对同伴个人项目源码合作修改
修改同伴的代码并将其提交至Github之上。
图1.3.1 pull requests
任务三. 采用两人结对编程方式,结合我校师生疫情每日上报系统使用体验,设计开发一款符合我校疫情防控工作需求的信息系统
(一). 需求分析
1. 设计一个具有GUI界面(Web或APP等)的程序;
2. 程序能够实现学校全校各类师生员工提交上报疫情信息;
3. 程序设计有各个部门的管理人员,且要能满足各个部门的管理人员查询成员的疫情信息填报情况;
4. 程序设计有一个总的管理人员,能满足查询全校师生成员的疫情信息填报情况;
5. 程序能够根据查询得到的结果导出为Excel文件;
(二). Web部分设计实现
系统分为了两个项目,其中一个是Web端的程序,用于成员疫情信息的上报,另一个是Java应用程序用于后台管理人员的管理操作。
为实现Web端的信息录入功能,我设计有以下几个类:
(1). 学生类 Student.java
(2). 教师类 Teacher.java
(3). 学生功能接口类 StudentDao.java
(4). 教师功能接口类 TeacherDao.java
(5). 学生服务接口类 StudentService.java
(6). 教师服务接口类 TeacherService.java
(7). 学生服务实现类 StudentServiceImpl.java
(8). 教师服务实现类 TeacherServiceImpl.java
(9). 学生控制类 StudentController.java
(10). 教师控制类 TeacherController.java
其中学生类与教师类属于实体层,用以存储学生与教师的所有数据;学生功能接口类与教师功能接口类为数据持久层,提供接口以与相应的xml配置文件结合来完成数据库的查询功能;学生、教师服务接口类为业务接口层,提供学生与教师服务的接口;而学生、教师服务实现类为业务层,实现相应接口的服务;学生控制类与教师控制类属于控制层,提供相应的控制器,以完成具体业务流程模块的控制。在上述各层中,实体层提供具体的数据实体,数据持久层处于业务层之下,业务层处于控制层之下,业务层作为中间层既调用持久层的接口也为控制层提供相应的业务接口。
初次之外,为搭建SSM框架,我设计有以下资源:
(1). StudentDao.xml
(2). TeacherDao.xml
(3). applicationContext.xml
(4). db.properties
(5). log4j.properties
(6). mybatis-config.xml
(7). springmvc-config.xml
Web部分的数据库设计见JAVA图形用户界面设计中的数据库设计部分。
(三). JAVA图形用户界面设计实现
系统分为了两个项目,其中一个是Web端的程序,用于成员疫情信息的上报,另一个是Java应用程序用于后台管理人员的管理操作。
### 1. 程序功能实现为实现基础的数据查询功能,我设计有以下几个类:
(1). 学生类 Student.java
(2). 教师类 Teacher.java
(3). 管理员类 Manager.java
(4). 数据库连接类 DbUtil.java
(5). 学生功能类 StudentDao.java
(6). 教师功能类 TeacherDao.java
(7). 管理员功能类 ManagerDao.java
(8). 柱状图生成类 BarChart.java
(9). 饼状图生成类 PieChart.java
(10). Excel工具类 ExcelUtil.java
(11). 数据库语句生成类 SqlCreate.java
(12). 系统测试类 SchoolSystem.java
其中,学生类、教师类与管理员类提供学生与教师、管理员的数据类型,包含有个人基本的数据;数据库连接类中的数据库连接函数负责程序与mysql数据库的连接;学生功能类、教师功能类与管理员功能类提供程序查询数据库的函数方法;柱状图生成类负责柱状图的生成;饼状图生成类负责饼状图的生成;Excel工具类的方法将List集合类型转换为Excel文件并导出至指定文件夹;数据库语句生成类用于在添加大量数据至数据库时SQL语句的生成;系统测试类中包含主函数Main,负责系统的运行测试。
1. 程序界面实现
(1). 成员添加面板类 AddInfoPanel.java
(2). 管理员登录面板类 LoginPanel.java
(3). 主菜单面板类 MenuPanel.java
(4). 信息查询菜单面板类 SelectInfoPanel.java
(5). 信息查询显示面板类 SelectShowPanel.java
(6). 柱状图面板类 ShowChartPanel.java
(7). 饼状图面板类 ShowPieChartPanel.java
(8). 显示菜单类 SystemMenu.java //目前不再使用
其中,成员添加面板类用于显示添加成员时的GUI界面绘制;管理员登录面板类用于管理员登录GUI界面的绘制;主菜单面板类绘制各个菜单项用于选择功能;信息查询菜单面板类用于显示查询功能的菜单项;信息查询显示面板类显示根据指定条件查询得到的结果;柱状图面板类与饼状图面板类绘制统计柱状图;显示菜单类用于在命令行下的主菜单与其他二级菜单的打印,目前已不再使用。
2. 数据部分设计
在数据部分我使用了MySQL数据库来完成实现,数据库名为schooldb,其中有三个表,分别为学生信息表studentinfo、教师信息表teacherinfo与管理员表Manager,三类表的设定如下图:
图2.3.1 studentinfo
图2.3.2 teacherinfo
图2.3.3 manager
其中学生信息主要包括学号id、姓名name、性别sex、学院college、专业major、电话号码phoneNumber、记录日期recordDate、所在省province、所在市city、是否感染diagnosed与体温temperature;教师的信息除了没有专业major一项以外,仅在工号id上有所不同,学生的学号设定为12位,教师的工号设定为4位。而管理员类记录管理员的登录信息,主要包括工号id、姓名name、所在部门/学院dept与登录密码password。
studentinfo与teacherinfo两张表均插入了随机生成的用户数据,学生表中有大约2400名学生在100余天内的信息,而教师表中越有50名教师在100余天内的信息,两个表中的数据加起来越有25万条左右。manager中的数据主要是十几个管理员的登录数据。
(四). Web端测试运行
1. 网页界面
图2.4.1 主页
2. 成员信息录入界面
图2.4.2 学生信息上报界面
图2.4.3 教师信息上报界面
3. 教师信息录入测试
图2.4.4 教师信息上报
网页中点击学生信息上报或教师信息上报将弹出不同的模态框,在其上填写信息后点击提交将提交成员的信息,上图为信息上报成功,若当天已经上报过信息则会提示今天已经上报。
(五). JAVA程序测试运行
1. 管理员登录界面
图2.5.1 管理员登录界面
2. 程序主菜单界面
在管理员登录成功后,进入程序主菜单页面。
图2.5.2 主菜单界面
3. 成员信息录入
程序可以选择学生信息录入或教师信息录入,如下是学生信息填写界面。
图2.5.3 学生信息填写界面1
图2.5.4 学生信息填写界面2
测试插入学生信息,数据插入情况如下图,可见数据插入成功。
图2.5.5 学生信息提交成功
3. 成员信息查询
测试查询成员的信息如下,首先选择通过学号/工号查询成员的信息。
图2.5.6 学号查询学生信息
根据学号查询到的信息显示如下图。
图2.5.7 学生信息查询结果
将查询到的数据导出为Excel如下,首先输入文件导出的绝对路径,之后导出成功。
图2.5.8 Excel导出路径
图2.5.9 Excel导出成功
查看导出的Excel文件如下图。
图2.5.10 Excel文件展示
根据学号/工号与日期联合查询信息如下,首先是输入页面,之后是结果显示,查询成功。
图2.5.11 学号/工号与日期输入页面
图2.5.12 查询结果显示页面
4. 信息统计图生成
根据输入的日期区间查询疫情相关信息如下,首先是未提交输入数据的页面,之后是结果显示,可见查询成功。
图2.5.13 初始统计图界面
输入日期区间并提交后得到感染人数查询结果。
图2.5.14 感染人数统计界面
输入时期区间查询感染人员地区分布统计结果。
图2.5.15 感染地区分布统计界面
统计当天该管理员所属部门/学院的成员信息上报统计情况。
图2.5.16 当天成员疫情信息上报情况统计界面
输入日期统计该天该管理员所属部门/学院的成员信息上报统计情况。
图2.5.17 指定日期成员疫情信息上报情况统计界面
(六). 代码展示
此段代码实现信息查询菜单面板的按钮的监听作用。
// chooseButton
chooseBtn.addActionListener(event -> {
List<Student> stuList = null;
List<Teacher> teaList = null;
if (chooseType == 0) {
// Select by id
if (isStudent) {
// isStudent
stuList = new ArrayList<Student>();
try {
stuList = stuDao.quaryById(fieldId.getText());
if (stuList.isEmpty() || stuList == null) {
int selectResult = JOptionPane.showConfirmDialog(null, "没有该学生信息!", "信息提示",
JOptionPane.DEFAULT_OPTION);
if (selectResult == JOptionPane.OK_OPTION) {
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} else {
// Create new JFrame
CreateShowFrame(manager, 0, stuList, teaList);
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} catch (SQLException e1) {
JOptionPane.showConfirmDialog(null, "数据库连接查询错误!", "信息提示", JOptionPane.DEFAULT_OPTION);
e1.printStackTrace();
}
} else {
// isTeacher
teaList = new ArrayList<Teacher>();
try {
teaList = teaDao.quaryById(fieldId.getText());
if (teaList.isEmpty() || teaList == null) {
int selectResult = JOptionPane.showConfirmDialog(null, "没有该教师信息!", "信息提示",
JOptionPane.DEFAULT_OPTION);
if (selectResult == JOptionPane.OK_OPTION) {
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} else {
// Create new JFrame
CreateShowFrame(manager, 0, stuList, teaList);
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} catch (SQLException e1) {
JOptionPane.showConfirmDialog(null, "数据库连接查询错误!", "信息提示", JOptionPane.DEFAULT_OPTION);
e1.printStackTrace();
}
}
} else {
// Select by id and date
// date transform
java.sql.Date recordDate = null;
try {
recordDate = new java.sql.Date(sdf.parse(fieldDate.getText()).getTime());
} catch (ParseException e) {
JOptionPane.showConfirmDialog(null, "日期信息格式错误!", "信息提示", JOptionPane.DEFAULT_OPTION);
e.printStackTrace();
}
if (isStudent) {
// isStudent
stuList = new ArrayList<Student>();
try {
Student stu = stuDao.findStudentInfo(fieldId.getText(), recordDate);
stuList.add(stu);
if (stu == null) {
stuList = new ArrayList<Student>();
}
if (stuList.isEmpty() || stuList == null) {
int selectResult = JOptionPane.showConfirmDialog(null, "没有该学生信息!", "信息提示",
JOptionPane.DEFAULT_OPTION);
if (selectResult == JOptionPane.OK_OPTION) {
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} else {
// Create new JFrame
CreateShowFrame(manager, 1, stuList, teaList);
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} catch (SQLException e1) {
JOptionPane.showConfirmDialog(null, "数据库连接查询错误!", "信息提示", JOptionPane.DEFAULT_OPTION);
e1.printStackTrace();
}
} else {
// isTeacher
teaList = new ArrayList<Teacher>();
try {
Teacher tea = teaDao.findTeacherInfo(fieldId.getText(), recordDate);
teaList.add(tea);
if (tea == null) {
teaList = new ArrayList<Teacher>();
}
if (teaList.isEmpty() || teaList == null) {
int selectResult = JOptionPane.showConfirmDialog(null, "没有该教师信息!", "信息提示",
JOptionPane.DEFAULT_OPTION);
if (selectResult == JOptionPane.OK_OPTION) {
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} else {
// Create new JFrame
CreateShowFrame(manager, 1, stuList, teaList);
// Jump
isStudent = true;
MenuPanel menuPanel = new MenuPanel(win, mainPanel, manager);
menuPanel.setSize(ScreenWidth, ScreenHeight);
}
} catch (SQLException e1) {
JOptionPane.showConfirmDialog(null, "数据库连接查询错误!", "信息提示", JOptionPane.DEFAULT_OPTION);
e1.printStackTrace();
}
}
}
});
(七). 实验总结
在此次实验中,我了解了两人结对编程的流程,这对我之后的团队软件开发学习提供了帮助。同时,我在这次实验中也进一步熟悉了模块化的开发原则,同时也再次熟悉了Web开发中SSM框架的搭建与使用。除了以上几点外,我也熟悉了在Github上进行项目的合作的操作。关于结对编程,我觉得它对我们提高团队协作能力十分有帮助,通常,在一些两人都熟悉的领域这种方式的效果的确是1+1>2,而在一些双方部分熟悉或不熟悉的领域来说,有时可能会有不够理想的进展,但大多数情况下双方均能获益,我也从这种合作编程中学习到了许多方法知识。当然,在这次结对编程中,虽然我们合作得比较顺利,也取得了较好的成果,但是依旧有提高的空间,希望之后的类似实验中我与我的合作伙伴能够合作地更好。
(八). 结对编程过程展示
在此次实验中,我们主要通过qq进行交流,这里选取一张截图作为展示:
图3.8.1 QQ截图
除此之外,也在Github上完成代码的提交
图3.8.2 GitHub截图
(九). PSP展示
PSP | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 20 | 20 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 20 | 20 |
Development | 开发 | 715 | 1030 |
Analysis | 需求分析 (包括学习新技术) | 45 | 60 |
Design Spec | 生成设计文档 | 5 | 5 |
Design Review | 设计复审 (和同事审核设计文档) | 15 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
Design | 具体设计 | 30 | 40 |
Coding | 具体编码 | 400 | 800 |
Code Review | 代码复审 | 120 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 90 | 40 |
Reporting | 报告 | 90 | 140 |
Test Report | 测试报告 | 70 | 120 |
Size Measurement | 计算工作量 | 8 | 5 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 12 | 15 |
在这次实验中,前期设计规划上用时基本符合预期。在代码部分用时与预期最不一致的有三个部分,第一是具体编码部分的时间超出预期,主要是因为对一些方法框架仍然不够熟悉;第二与第三是在代码复审与测试环节的用时低于预期,这可能与我在代码编写过程中会反复修改查看有关。总之,在这次的实验中我有许多的不足之处,希望之后能做得更好。
(十). GitHub界面展示
图3.10.1 Web端GitHub页面
图3.10.2 Java应用端GitHub页面