项目 | 内容 |
---|---|
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/xbsf/nwnu2020SE |
这个作业的要求在哪里 | https://www.cnblogs.com/nwnu-daizh/p/12521474.html |
作业学习目标 | (1)通过结对编程,学习软件开发过程中两人的合作;(2)掌握Github发布软件项目的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | 这个作业让我了解了团队合作时,分工和交流的重要 |
结对方学号-姓名 | 201771010104——狄慧 |
结对方本次博客作业链接 | https://www.cnblogs.com/dhlll/p/12584172.html |
项目Github的仓库链接地址 | https://github.com/dalacao/text6 |
一、实验内容
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;
- 代码风格规范:代码风格规范主要是文字上的规定,是对缩进、行宽、括号、断行与空白的{}行、分行、命名等的处理方式。代码风格的原则是:简明、易懂、无二义性。
- 代码设计规范:代码设计规范不光是程序书写格式问题,而且牵涉到程序设计、模块之间的关系、设计模式等方方面面。比如关于函数,最重要的原则是:只做一件事,并且要做好。
- 代码复审:
- 代码复审的定义:看代码是否在代码规范的框架内正确的解决了问题。
- 代码复审的形式有:自我复审、同伴复审、团队复审。
- 代码复审的目的:(1)找出代码的错误;(2)发现逻辑错误;(3)发现算法错误;(4)发现潜在的错误和回归性错误;(5)发现可能需要改进的地方。 - 结对编程概念:两个人可以通过合作平等地、互补地进行开发工作。可以一起分析、一起设计、一起编码等。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价;
结对方的博客链接:
https://www.cnblogs.com/dhlll/p/12504178.html
结对方的GitHub链接:
https://github.com/dihuidihui/text2.git
复审同伴项目代码:
-
克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。
-概要部分
(1)代码符合需求和规格说明么?
答:基本符合需求与规格。
(2)代码设计是否有周全考虑?
答:考虑的不是特别周全。
(3)代码可读性如何?
答:易读。
(4)代码容易维护么?
答:比较容易。
(5)代码的每一行都执行并检查过了吗?
答:是。
-设计规范部分
(1)设计是否遵从已知的设计模式或项目中常用的模式?
答:部分遵从。
(2)有没有硬编码或字符串/数字等存在?
答:有。
(3)代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)
答:没有依赖,应该不会影响。
(4)开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现?
答:可以实现,不存在。
(5)有没有无用的代码可以清除?
答:基本没有。
-代码规范部分
(1)修改的部分符合代码标准和风格么?
答:基本符合。
-具体代码部分
(1)有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
答:检查并处理了。
(2)参数传递有无错误,字符串的长度是字节的长度还是字符的长度,是以0开始计数还是以1开始计数?
答:没有错误,字符串的长度是字节的长度,是以0开始计数。
(3)有没有可能出现死循环?
答:没有出现死循环。
(4)有没有使用断言(Assert)来保证我们认为不变的条件真的满足?
答:没有使用。
(5)对资源的利用,是在哪里申请,在哪里释放的?有没有可能导致资源泄露?
答:不会导致资源泄漏。
(6)数据结构中是否有无用的元素?
答:没有无用的元素。
-效能
(1)代码的效能(Performance)如何?最坏的情况是怎样的?
答:代码简洁易懂,程序运行正常。
(2)代码中,特别是循环中是否有明显可优化的部分?
答:代码在之前基础上已经做过优化处理,目前没有明显可优化部分。
(3)对于系统和网络调用是否会超时?如何处理?
答:没有超时。
-可读性
代码可读性如何?有没有足够的注释?
答:代码有注释,可读性强。
-可测试性
代码是否需要更新或创建新的单元测试?
答:目前不需要。 -
结对方项目仓库中的Fork、Clone、Push、Pull request、Merge pull request日志数据
任务3、采用两人结对编程方式,结合我校师生疫情每日上报系统使用体验,设计开发一款符合我校疫情防控工作需求的信息系统
- 需求分析:
2019年12月末,中国武汉发生新型冠状病毒(2019-nCoV) 感染的肺炎疫情,为遏制疫情蔓延,有效切断病毒传播途径,在中央政府指导下,各级政府部分采取了一系列防控措施: 2020年1 月23 日10时起对武汉“封城”,全国 31个省市也相继实施了严格的防控措施;全国各省市向武汉和湖北派遣医疗队参与救治工作;在全国范围内调配口罩、防护服、药品等急需的医疗资源支援武汉;指导和督促全国范围内拥有医疗物资生产资质的企业尽快恢复生产能力;定向拨付专项财政资金用于疾病防控;从其他省份调集物资保障武汉市民日常生活。
值得一提的是,中国互联网企业在此次疫情防控中发挥了社会治理方面的重要作用。以腾讯为例,围绕应对疫情管控需求开发了十一款产品。其中疫情在线问诊功能,对于减少发热病人之间的相互交叉感染具有重要的作用,患者在家通过互联网向在线医生问诊,减少了病毒传播或感染的风险;谣言粉碎对于公众采取理性态度看待疫情的发展具有重要意义。滴滴出行还在武汉专门组建车队,服务于医护人员的通勤,这在实施交通管制的武汉具有重要作用。此外,还有新型肺炎确诊患者同行程查询工具,用户只需要输入自己所乘坐交通工具的时间和班次,就可以确认是否与被确诊感染者同行,提前做好自我隔离和就诊工作。在疫情防控中,中国互联网企业不仅发展壮大,在承担社会责任方面也越来越成熟。
为有效配合防控机构有关疫情信息的采集、统计与排查,我校开发了教职工/学生疫情上报系统,该系统由教职工疫情每日上报、学生疫情每日上报、二级部门疫情每日汇总表、疫情防控填报统计四个子系统组成。实现对我校各类人员基本情况、所在区域及活动轨迹及健康状况的信息收集。在此基础上提供了高级查询,相对的可视化功能,定时功能以及导出到excel表中的功能。
-1.在疫情期间方便学校了解具体情况 ;
-2.可以借此系统掌握具体的数据,以便了解情况。
软件设计说明。 - 功能设计:
- 核心代码展示:
、、、
package Student_Manage;
//信息管理人员登陆后的界面
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;/*ArrayList;
import java.util.Hashtable;
*/
public class ManagerLogin extends JFrame implements ActionListener{
Function fun=new Function();
//定义组件
JLabel lb1=new JLabel("当前是信息管理人员登录界面" );//JLabel 对象可以显示文本、图像
JLabel lb2=new JLabel("提示:录入前请先输入学号,修改、删除根据学号修改信息");
JTextField 学号,姓名,年龄,电话号码,家庭住址,体温;//输入学生基本信息得文本
JRadioButton 男,女;//声明单选项对象,性别选择
ButtonGroup group=null;//声明按钮组
JButton 录入,查询,删除,修改,显示,返回;//声明相应的操作的按钮
JPanel p1,p2,p3,p4,p5,p6,p7,pv,ph,pb;//调节布局的通道
public ManagerLogin(){ //负责管理员登录的主窗口
super("西北师范大学学生疫情信息上报管理系统");
学号=new JTextField(10);//创建文本信息的的对象
姓名=new JTextField(10);
电话号码=new JTextField(15);
年龄=new JTextField(5);
家庭住址=new JTextField(15);
体温=new JTextField(5);
group=new ButtonGroup();
男=new JRadioButton("男");//初始化单选框,
女=new JRadioButton("女");
group.add(男);//把按钮添加到按钮组
group.add(女);
录入=new JButton("增加学生信息");//创建按钮对象
查询=new JButton("查询符合条件的学生信息");
删除=new JButton("删除学生信息");
修改=new JButton("修改学生信息");
显示=new JButton("显示全部学生信息");
返回=new JButton("返回登录界面");
pb=new JPanel();
pb.add(lb1,JLabel.CENTER);
p1=new JPanel();//创建一个面板
p1.add(lb2,JLabel.CENTER);
p1.add(new JLabel("学号:",JLabel.CENTER));//JLabel.CENTER是指JLabel的中心点。CENTER是中心点的坐标
p1.add(学号);
p2=new JPanel();
p2.add(new JLabel("姓名:",JLabel.CENTER));
p2.add(姓名);
p3=new JPanel();
p3.add(new JLabel("性别:",JLabel.CENTER));
p3.add(男);
p3.add(女);
p4=new JPanel();
p4.add(new JLabel("年龄:",JLabel.CENTER));
p4.add(年龄);
p5=new JPanel();
p5.add(new JLabel("电话号码:",JLabel.CENTER));
p5.add(电话号码);
p6=new JPanel();
p6.add(new JLabel("家庭住址:",JLabel.CENTER));
p6.add(家庭住址);
p7=new JPanel();
p7.add(new JLabel("体温:",JLabel.CENTER));
p7.add(体温);
pv=new JPanel();//面板
pv.setLayout(new GridLayout(7,1)); //把pv组件设置成第七行1列的网格布局
pv.add(p1);//把面板放到容器中,add()代表容器
pv.add(p2);
pv.add(p3);
pv.add(p4);
pv.add(p5);
pv.add(p6);
pv.add(p7);
ph=new JPanel();
ph.add(录入);
ph.add(查询);
ph.add(修改);
ph.add(删除);
ph.add(显示);
ph.add(返回);
Container con=getContentPane();//建立容器对象con,取得容器面板
con.setLayout(new BorderLayout());//设置布局为边框布局,边框布局分东南西北中5个方位来添加控件。
//若没有指定方位,将添加到中间,上下左右都可以扩展
con.add(pb, BorderLayout.NORTH);//Frame对象lb调用方法add(),lb放在最北上方
con.add(pv, BorderLayout.CENTER);//pv在中间
con.add(ph, BorderLayout.SOUTH);//ph在南边
setDefaultCloseOperation(EXIT_ON_CLOSE);//置一个默认的关闭操作,也就是你的JFrame窗口的关闭按钮,点击它时,退出程序
setBounds(100,100,900,450);//setBounds(x,y,width,height); x:组件在容器X轴上的起点 y:组件在容器Y轴上的起点 width:组件的长度 height:组件的高度
setVisible(true);//目的是使控件可以显示出来,如果该控件已经被显示出来
student_information stu=new student_information();
ArrayList arry=new ArrayList();
//添加监听
//点击录入按钮 学号","姓名","性别","年龄","电话号码","家庭住址","体温"
录入.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String sID = 学号.getText(); //获取文本框中内容
if(fun.find(sID)!=-1)
{
JOptionPane.showMessageDialog(null, "该学号对应的学生已经存在!!!\n\n请重新输入或者修改已经录入的学生");
//清空文本框
学号.setText("");
姓名.setText("");
年龄.setText("");
电话号码.setText("");
家庭住址.setText("");
体温.setText("");
return;
}
String sname = 姓名.getText();
//先判断学号和姓名是否为空,如果为空,直接退出
if(sID.equals("")||sname.equals(""))
{
JOptionPane.showMessageDialog(null, "录入的学生学号或姓名为空!!!\n\n请重新输入");
return;
}
String sage = 年龄.getText();
if(sage.equals(""))//年龄为空,没有输入
sage="--";
String scall = 电话号码.getText();
if(scall.equals(""))
scall="--";
String shome = 家庭住址.getText();
if(shome.equals(""))
shome="--";
String siden = 体温.getText();
if(siden.equals(""))
siden="--";
String ssex=null;
if(男.isSelected()){//选择男女
ssex=男.getText();
}
else{
ssex=女.getText();
}
stu.setStuID(sID);
stu.setAge(sage);
stu.setName(sname);
stu.setSex(ssex);
stu.setCallnummber(scall);
stu.setHome_place(shome);
stu.settiwen(siden);
//arry.clear();// 清除原数组列表中的数据
// Input input=new Input(stu);
System.out.println("信息管理员");
System.out.println(stu.fileString());
fun.add(stu);
fun.writefile();
JOptionPane.showMessageDialog(null, "录入成功!!!");
//dispose();
setVisible(false);
new ManagerLogin();
//清空文本框
/*
学号.setText("");
姓名.setText("");
年龄.setText("");
电话号码.setText("");
家庭住址.setText("");
体温.setText("");
group.clearSelection(); //清空按钮已选状态
*/
}
});
//显示全部学生信息
显示.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//show_stuall all=new show_stuall();
new show_stuall();
}
});
//查询某个学生信息
查询.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String sID = 学号.getText(); //获取文本框中内容
if(sID.equals(""))
sID="--";
String sname = 姓名.getText();
if(sname.equals(""))
sname="--";
String sage = 年龄.getText();
if(sage.equals("")) //年龄为空,没有输入
sage="--";
String scall = 电话号码.getText();
if(scall.equals(""))
scall="--";
String shome = 家庭住址.getText();
if(shome.equals(""))
shome="--";
String siden = 体温.getText();
if(siden.equals(""))
siden="--";
String ssex=null;
if(男.isSelected()){//选择男女
ssex=男.getText();
}
else {
if(女.isSelected())
ssex=女.getText();
else {
ssex="--";
}
}
//将要查询的符合条件的写入文件
FileWriter fw=null;
BufferedWriter out=null;//学号","姓名","性别","年龄","电话号码","家庭住址","体温" };
try {
fw = new FileWriter("查询时暂时存放的文件.txt");
out = new BufferedWriter(fw);
//姓名学号等中间隔一个空格
out.write(sID+" ");
out.write(sname+" ");
out.write(ssex+" ");
out.write(sage+" ");
out.write(scall+" ");
out.write(shome+" ");
out.write(siden+" "); //每次覆盖写入,无需全部保存
out.close();
fw.close();
} catch (IOException e1) {
e1.printStackTrace();
}
//开始查询
new showones();
//清空文本框
学号.setText("");
姓名.setText("");
年龄.setText("");
电话号码.setText("");
家庭住址.setText("");
体温.setText("");
group.clearSelection();
}
});
//删除学生信息,按学号删除
删除.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String sID = 学号.getText(); //获取文本框中内容
int flag=fun.find(sID);
if(flag==-1)
{
JOptionPane.showMessageDialog(null, "未查找到该学号的学生!!!\n\n请重新输入");
}
else {
fun.delete(sID);
fun.writefile();
JOptionPane.showMessageDialog(null, "删除成功!!!\n");
}
//清空文本框
学号.setText("");
姓名.setText("");
年龄.setText("");
电话号码.setText("");
家庭住址.setText("");
体温.setText("");
group.clearSelection();
}
});
//修改学生信息
修改.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String sID = 学号.getText(); //获取文本框中内容
int flag=fun.find(sID); //查找是否存在
if (flag==-1)
{
JOptionPane.showMessageDialog(null, "未查找到该学号的学生!!!\n\n请重新输入");
return;
}
else
JOptionPane.showMessageDialog(null, "该系统中存在该学生数据\n\n,确认返回后请输入需要修改后的数据");
String sage = 年龄.getText();
if(sage.equals(""))//年龄为空,没有输入
sage="--";
String scall = 电话号码.getText();
if(scall.equals(""))
scall="--";
String shome = 家庭住址.getText();
if(shome.equals(""))
shome="--";
String siden = 体温.getText();
if(siden.equals(""))
siden="--";
String ssex=null;
if(男.isSelected()){//选择男女
ssex=男.getText();
}
else{
ssex=女.getText();
}
String sname = 姓名.getText();
//先判断学号和姓名是否为空,如果为空,直接退出
if(sname.equals(""))
{
JOptionPane.showMessageDialog(null, "录入的学生姓名为空!!!\n\n请重新输入");
return;
}
// student_information stu=new student_information();
stu.setStuID(sID);
stu.setAge(sage);
stu.setName(sname);
stu.setSex(ssex);
stu.setCallnummber(scall);
stu.setHome_place(shome);
stu.settiwen(siden);
fun.update(stu); //修改
fun.writefile();
JOptionPane.showMessageDialog(null, "修改成功!!!");
//清空文本框
学号.setText("");
姓名.setText("");
年龄.setText("");
电话号码.setText("");
家庭住址.setText("");
体温.setText("");
group.clearSelection();
}
});
返回.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false); //目的是使控件不可以显示出来
new Login();
}
});
}
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
、、、
描述结对的过程,提供两人在讨论、细化和编程时的微信或QQ截图(截图要完整,能够显示结对双方姓名)
七、PSP:
PSP2.1 | 内容 | 计划完成需要的时间(min) | 实际完成所需要的时间(min) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 30 |
Development | 开发 | 3000 | 3200 |
Analysis | 需求分析(包括学习新技术) | 200 | 220 |
Design Spec | 生成设计文档 | 50 | 100 |
Design Review | 设计复审(和同事审核设计文档) | 200 | 220 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 60 | 100 |
Design | 具体设计 | 800 | 800 |
Coding | 具体编码 | 1350 | 1400 |
Code Review | 代码复审 | 250 | 270 |
Test | 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | 200 | 250 |
Test Report | 测试报告 | 50 | 70 |
Size Measurement | 计算工作量 | 80 | 100 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 70 | 80 |
总结:
这次的实验我们尝试了结对编程,通过结对编程我们可以一起去交流学习,但是由于现在处于疫情期间,所以我们结对编程的交流过程是在线上的。这次的系统我们没能实现对数据的可视化。但是结对编程的效果还是挺大的,通过结对编程我们共同合作,能够想到一些对方没有考虑地方,可以分享知识、共同解决遇到的问题。两个人合作完成一个项目,要比起自己单独去完成效果好很多,不仅会减轻双方的工作量,还可以在合作中最大化发挥自己的优点,同时也可以从对方身上学到很多自己不擅长的技术,互相弥补,共同进步。而且通过这次的结对编程,我们学会了合作学习、交流,知道怎么团队工作。