项目 | 内容 |
---|---|
课程班级博客链接 | https://edu.cnblogs.com/campus/xbsf/nwnu2020SE |
这个作业要求链接 | https://www.cnblogs.com/nwnu-daizh/p/12521474.html |
我的课程学习目标 | 熟悉结对项目开发流程 |
这个作业在哪些方面帮助我实现学习目标 | 让我学会了结对项目的开发流程 |
项目Github的仓库链接地址 | https://github.com/Bufanbin/test2 |
任务二:
-
结对方博客链接:201771030104-道彤阳 实验二 个人项目——《西北师范大学学生疫情上报系统》
-
结对方Github项目仓库链接:Git地址
-
符合(1)要求的博客评论
-
符合(2)要求的代码审核
-
概要部分
a. 代码能符合需求和规格说明么? 答:符合需求与规格。
b. 代码设计是否有周全的考虑? 答:整体考虑较周全,细节上有一些小问题。
c. 代码可读性如何? 答:简单易懂。
d. 代码容易维护么? 答:容易维护。
e. 代码的每一行都执行并检查过了吗? 答:检查过了。
-
设计规范部分
a. 设计是否遵从已知的设计模式或项目中常用的模式? 答:是。
b. 有没有硬编码或字符串/数字等存在? 答:无。
c. 代码有没有依赖于某一平台,是否会影响将来的移植? 答:无依赖,不影响。
d. 开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现? 答:可以实现,不存在。
e. 有没有无用的代码可以清除? 答:无。
-
代码规范部分
a. 修改的部分符合代码标准和风格么(详细条文略)? 答:符合标准。
-
具体代码部分
a. 有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? 答:基本没有。
b. 参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数? 答:无错误,字符串的长度是字节的长度,以0开始计数。
c. 边界条件是如何处理的?Switch语句的Default是如何处理的?循环有没有可能出现死循环? 答:不会出现死循环。
d. 有没有使用断言(Assert)来保证我们认为不变的条件真的满足? 答:没。
e. 对资源的利用,是在哪里申请,在哪里释放的?有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有可能优化? 答:线下使用,不会导致资源泄露,没有优化。
f. 数据结构中是否有无用的元素? 答:没有。
-
效能
a. 代码的效能(Performance)如何?最坏的情况是怎样的? 答:代码正确,程序运行正常,数据结构待优化。b. 代码中,特别是循环中是否有明显可优化的部分(C++中反复创建类,C#中 string 的操作是否能用StringBuilder 来优化)? 答:有,不影响正常运行。
c. 对于系统和网络调用是否会超时?如何处理? 答:不会超时。
-
可读性
a. 代码可读性如何?有没有足够的注释? 答:代码可读性较好,注释足够。
-
可测试性
a. 代码是否需要更新或创建新的单元测试? 还可以有针对特定领域开发(如数据库、网页、多线程等)的核查表。 答:不需要。
-
-
结对方项目仓库中的Fork、Clone、Push、Pull request、Merge pull request日志数据。
-
Fork
-
Clone
-
Pull request
-
Merge pull request
-
任务三
需求分析
(1)可采集全校各类师生员工疫情信息;
(2)各二级部门疫情防控工作负责人可查看本部门人员疫情汇总,并提供高级查询功能进行多属性组合查询和可视化统计功能;
(3)学校防控办指定负责人登录《西北师范大学疫情防控信息统计》子系统,可浏览所有人员填报汇总数据清单,利用【高级查询】可进行数据组合筛选,
系统以图形化方式展示各学院已填报和未填报学生统计情况和关键疫情数据统计情况,可【导出】查询列表的EXCEL文件;
(4)人机交互界面要求GUI界面(WEB页面、APP页面都可);
(5)附加分功能:定时填报提醒
软件设计
- 结构设计
- 程序设计
严格执行结构设计中提到的方法和技术和环境,对于这次的任务,设计的包,类,jsp如图所示:
- 数据结构
实验二和实验三相差不是特别大,实验二我采用了命令行的形式,但这次是GUI形式,对数据库我也进行了相应的改动,这个增加了疫情的负责人和二级管理部门,学院可以查看和修改学生的信息,学生可以查看自己的疫情信息,学校的负责人可以查看全校的信息。
软件实现及核心功能代码展示
- 核心代码
/**
* 给构造的查询链接赋值参数
* @param page
* @param prepareStatement
* @return
*/
private PreparedStatement setParams(Page<T> page,PreparedStatement prepareStatement){
List<SearchProperty> searchProperties = page.getSearchProperties();
int index = 1;
for(SearchProperty searchProperty : searchProperties){
try {
if(searchProperty.getOperator() != Operator.IN){
prepareStatement.setObject(index++, searchProperty.getValue());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return prepareStatement;
}
/**
* 构造一般查询语句
* @param type
* @return
*/
private String buildSql(int type) {
// TODO Auto-generated method stub
String sql = "";
switch (type) {
case CURD_ADD:{
String sql1 = "insert into " + StringUtil.convertToUnderLine(t.getSimpleName()) + "(";
Field[] declaredFields = t.getDeclaredFields();
for(Field field : declaredFields){
sql1 += StringUtil.convertToUnderLine(field.getName()) + ",";
}
sql1 = sql1.substring(0,sql1.length()-1) + ")";
String sql2 = " values(null,";
String[] params = new String[declaredFields.length-1];
Arrays.fill(params, "?");
sql2 += StringUtils.join(params, ",") + ")";
sql = sql1 + sql2;
break;
}
case CURD_SELECT:{
sql = "select * from " + StringUtil.convertToUnderLine(t.getSimpleName());
break;
}
case CURD_COUNT:{
sql = "select count(*) as total from " + StringUtil.convertToUnderLine(t.getSimpleName());
break;
}
case CURD_UPDATE:{
sql = "update " + StringUtil.convertToUnderLine(t.getSimpleName()) + " set ";
Field[] declaredFields = t.getDeclaredFields();
for(Field field : declaredFields){
if(!"id".equals(field.getName())){
sql += StringUtil.convertToUnderLine(field.getName()) + " =?,";
}
}
sql = sql.substring(0,sql.length()-1) + " where id = ?";
break;
}
case CURD_DELETE:{
sql = "delete from "+StringUtil.convertToUnderLine(t.getSimpleName())+" where id in(";
break;
}
default:
break;
}
System.out.println(sql);
return sql;
}
/**
* 给构造的查询链接赋值参数
* @param page
* @param prepareStatement
* @return
*/
private PreparedStatement setParams(Page<T> page,PreparedStatement prepareStatement){
List<SearchProperty> searchProperties = page.getSearchProperties();
int index = 1;
for(SearchProperty searchProperty : searchProperties){
try {
if(searchProperty.getOperator() != Operator.IN){
prepareStatement.setObject(index++, searchProperty.getValue());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return prepareStatement;
}
程序运行
- 登录界面
- 以管理员身份进入,对学生列表进行操作
- 以学生身份进入,查询,删除,修改自己的信息
- 将数据库导出到的Excel中
描述结对的过程
结对过程中,我们配合的很好,有问题积极交流,及时交换意见,项目完成的很坎坷,不过最终完成了。中途因为使用框架和语言讨论过很多次,不过最终
还是达成一致,努力完成。
此次结对作业的PSP
PSP2.1 | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 30 | 20 |
Estimate | 估计这个任务需要多少时间 | 1448 | 1450 |
Development | 开发 | 100 | 105 |
Analysis | 需求分析(包括学习新技术) | 20 | 20 |
Design Spec | 生成设计文档 | 50 | 40 |
Design Review | 设计复审(和同事审核设计文档) | 40 | 50 |
Coding Standard | 代码规范(为目前的开发指定合适的规范) | 20 | 20 |
Design | 具体设计 | 200 | 195 |
Coding | 具体编程 | 800 | 850 |
Code Review | 代码复审 | 50 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 70 | 65 |
Reporting | 报告 | 50 | 40 |
Test Report | 测试报告 | 10 | 9 |
Size Measurmen | 计算工作量 | 8 | 6 |
Postmortem & Process Imporvement Plan | 事后总结,并提出过程改进计划 | 30 | 20 |
小结
通过这次编程我认识到结对编程的巨大优势,合作可以弥补个人缺点,发挥彼此长处。结对的效率一加一大于二,实际操作中一定要积极交流,
有问题及时解决。我认识到,我们两人前端都不是特别好,一定要积极学习,弥补不足,提升能力。