201771010110-孔维滢 实验三 结对项目—《西北师范大学疫情防控信息系统》项目报告

实验三 软件工程结对项目

项目 内容
课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/nwnu2020SE/
这个作业要求链接 https://www.cnblogs.com/nwnu-daizh/p/12521474.html
我的课程学习目标 学习软件工程中结对编程(Pair programming)
这个作业在哪些方面帮助我实现学习目标 软件开发流程中的结对编程的方法内容
结对方学号-姓名 王志成-201771010130
结对方本次博客作业链接 https://www.cnblogs.com/847118824wang/p/12587400.html
本项目Github的仓库链接地址 https://github.com/Wei-Ron/epidemic-user-message

任务一 阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念。

(1)代码规范

代码规范风格的原则是:简明,易读,无二义性:
标识符直观且可以拼读,可望文知意,不必进行“解码”。
标识符的长度符合“min-length && max-information”原则。
命名规则尽量与所采用的操作系统或开发工具的风格保持一致。
程序中不可出现仅靠大小写区分的相似的标识符。
变量的名字可使用“名词”或者“形容词+名词”。
全局函数的名字可使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。

(2)代码复审:

代码设计有比较周全的考虑。首先,程序对输入有详细的处理,对输入的格式进行了检查,并对输入的数字大小进行了判断。程序还有周全的错误处理,把错误信息输出到ErrorLog.txt中。
代码有较高的可读性。代码根据功能分为了几个不同的类,对功能的划分较为直观,关键部分有详细的注释,但有些部分仍缺少必要的注释,存在一些难以理解的代码。由于代码的分工十分明确,所以易于维护。
代码的每一行都必须保证执行并检查过了。

(3)结对编程

两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。两个程序员经常互换角色。

任务二 两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价

  • 组员博客链接

  • 组员GitHub项目仓库链接

  • 博客评论

  • 对方代码运行

  • 结对仓库日志数据

代码复审

项目的开发者:王志成
项目的复审者:孔维滢

1、概要部分

(1)代码符合需求和规格说明么?
代码基本符合需求,代码基本符合规范说明。
(2)代码设计是否考虑周全?
考虑基本周全,但是认为设计内容还不够全面。
(3)代码可读性如何?
可以顺利读懂。
(4)代码容易维护么?
容易维护。
(5)代码的每一行都执行并检查过了吗?
检查过了,没有错误,每一行都可以执行。

2.设计规范部分

(1)设计是否遵从已知的设计模式或项目中常用的模式?
遵从
(2)有没有硬编码或字符串/数字等存在?
没有
(3)代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)?
没有,不会影响移植。
(4)开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现?
可以用,部分功能可以调用而不用全部重新实现。
(5)有没有无用的代码可以清除?(很多人想保留尽可能多的代码,因为以后可能会用上,这样导致程序文件中有很多注释掉的代码,这些代码都可以删除,因为源代码控制已经保存了原来的老代码)
基本清除完毕。

3.代码规范部分

(1)修改的部分符合代码标准和风格么?
符合。

4.具体代码部分

(1)有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
对错误都进行了处理,没有任何异常。
(2)参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数?
无错误。不涉及字符串。
(3)边界条件是如何处理的?switch语句的default分支是如何处理的?循环有没有可能出现死循环?
没有出现死循环。
(4)有没有使用断言(Assert)来保证我们认为不变的条件真的得到满足?
没有。
(5)对资源的利用是在哪里申请,在哪里释放的?有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有优化的空间?
在对数据库进行操作之前申请数据库连接资源,操作完毕之后释放申请的资源。不会导致资源泄露。可以使用断言来保证我们认为不变的条件。
(6)数据结构中有没有用不到的元素?
没有。

5.效能

(1)代码的效能(Performance)如何?最坏的情况如何?
达到了任务二的基本要求。
(2)代码中,特别是循环中是否有明显可优化的部分(C++中反复创建类,C#中 string 的操作是否能用StringBuilder 来优化)?
没有。
(3)对于系统和网络调用是否会超时?如何处理?
没有出现超时的现象。

6.可读性

(1)代码可读性如何?有没有足够的注释?
可以顺利读取,注释较为全面。

7.可测试性

(1)代码是否需要更新或创建新的单元测试?针对特定领域的开发(如数据库、网页、多线程等),可以整理专门的核查表。
不需要更新或者创建新的单元测试。可以继续开发,添加更多的功能。

任务三 采用两人结对编程方式,结合我校师生疫情每日上报系统使用体验,设计开发一款符合我校疫情防控工作需求的信息系统。

需求分析

(1)实现西北师范大学所有学生以及教职工每天的疫情信息填写;
(2)实现师生对个人所填信息的查询;
(3)设置信息管理员对于全体师生疫情信息的多样化以及可视化查询;
(4)实现人机交互界面。

设计说明

(1)登录时分为师生登录和管理员登录两部分,into表——师生登录信息表 message——疫情填报信息表

(2)into表中name分为两个选择,用户和管理员,number是登陆账号,psw是登陆密码

(3)message表中name是师生姓名,college是学院,hot_messege是否感染,where_wuhan是否接触过武汉籍人员,where_hubei是否接触过湖北籍人员,come_wuhan是否来自武汉,come_hubei是否来自湖北

(4)代码结构

(5)代码说明
Logup//用户和管理员登录界面
UseLog//用户登陆后跳转到信息填报界面
UseManagement//管理员登录后跳转界面
BarChart//生成柱状图
UseAdd//实现添加学生信息的一个类
query//实现查询全部信息的一个类
UseQuery//实现通过学号查询信息的一个类
time//实现通过日期查询信息的一个类
UseHot//实现查询所有患病人员信息的一个类
UseUpdate//实现更新信息的一个类
UseDelete//实现删除信息的一个类

  • 实现功能如下:
    • 该系统分为用户和管理员两部分

    • 数据库如下:

    • 登录界面:

    • 信息填写界面

    • 管理员界面

    • 全部查询功能

    • 分类查询功能

      • 按学号查询

      • 按时间查询

      • 查询患病人员及生成柱状图

     - 信息更新

     - 信息删除

  • 关键代码如下
public Logup()
	{
		try{
			Class.forName("com.mysql.cj.jdbc.Driver");
		}
		catch(ClassNotFoundException e){}
		try{
			con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=utf8","root","123456");
			sql = con.createStatement();
		}
		catch(SQLException ee){}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand()=="退出")
		{
			System.exit(0);
		}else if(e.getActionCommand()=="登录")
		{
			if(!jtf.getText().isEmpty() && !jpf.getText().isEmpty())
			{
				//:当点击登录按钮时,首先与数据库建立连接
				//:如果选中管理员登录
				if(jrb1.isSelected())
				{
					try {
						queryman();
					} catch (SQLException e1) {
						//:TODO Auto-generated catch block
						e1.printStackTrace();
					}
					//:首先判断是否存在该用户,即是否得到了密码
					if(pwd ==null)
					{
                         this.clear();
					}else
					{
						//:调用登录方法
						this.manlogin();
					}
				}else if(jrb2.isSelected()) //:用户登录系统
				{
 				try {
					queryuse();
				} catch (SQLException e1) {
					//:TODO Auto-generated catch block
					e1.printStackTrace();
				}
					//:首先判断是否存在该用户,即是否得到了密码
					if(pwd ==null)
					{
                         this.clear();
					}else
					{
						//:调用登录方法
						this.uselogin();
					}
				}
			}else if(jtf.getText().isEmpty())
			{
				JOptionPane.showMessageDialog(null,"请输入用户名","提示消息",JOptionPane.WARNING_MESSAGE);
			    this.clear();
			}else if(jpf.getText().isEmpty())	
			{
				JOptionPane.showMessageDialog(null,"请输入密码","提示消息",JOptionPane.WARNING_MESSAGE);
			    this.clear();
			}
		}else if(e.getActionCommand()=="重置")
		{
			this.clear();
		}			
	}	
		//:清空文本框和密码框
	public	void clear()
		{
			jtf.setText("");
			jpf.setText("");
		}
	//:用户登录判断方法
	public void uselogin()
	    {
			if(pwd.equals(jpf.getText()))
			{
				JOptionPane.showMessageDialog(null,"登录成功!","提示消息",JOptionPane.WARNING_MESSAGE);
				this.clear();
				//:关闭当前界面
				dispose();
				//:创建一个新界面
				Uselog usel = new Uselog();
				usel.setVisible(true);	
				usel.addWindowListener(new WindowAdapter(){
				public void windowClosing(WindowEvent e){
						System.exit(0);
							}
							});
				}else if(jtf.getText().isEmpty()&&jpf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入用户名和密码!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else if(jtf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入用户名!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else if(jpf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入密码!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else
				{
					JOptionPane.showMessageDialog(null,"用户名或者密码错误!
请重新输入","提示消息",JOptionPane.ERROR_MESSAGE);
				    //:清空输入框
					this.clear();
				}
			}
	public void queryuse() throws SQLException{
		con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=utf8","root","123456");
		ResultSet rs = sql.executeQuery("SELECT* FROM list_1 WHERE name='用户'");	
		if (rs.next()) {
			userword = rs.getString(3);
			pwd = rs.getString(4);
			System.out.println("成功获取到密码和用户名from数据库");
			System.out.println(userword + "	" + pwd + "	");
			//:调用登录方法
		}else
		{
			JOptionPane.showMessageDialog(null, "没有此用户,请重新输入!", "提示消息", JOptionPane.WARNING_MESSAGE);
		}
	}
			//:管理员登录判断方法
			public void manlogin()
			{
				if(pwd.equals(jpf.getText()))
				{
					 JOptionPane.showMessageDialog(null,"登录成功!","提示消息",JOptionPane.WARNING_MESSAGE);
					 this.clear();	
					//:关闭当前界面
					 dispose();
					 //:创建一个新界面,适用于管理员来管理用户
					 UseManagement useM = new UseManagement();
					useM.setVisible(true);
						
					useM.addWindowListener(new WindowAdapter(){
						public void windowClosing(WindowEvent e){
							System.exit(0);
						}
							});	 					
				}else if(jtf.getText().isEmpty()&&jpf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入用户名和密码!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else if(jtf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入用户名!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else if(jpf.getText().isEmpty())
				{
					JOptionPane.showMessageDialog(null,"请输入密码!","提示消息",JOptionPane.WARNING_MESSAGE);
				}else
				{
					JOptionPane.showMessageDialog(null,"用户名或者密码错误!
请重新输入","提示消息",JOptionPane.ERROR_MESSAGE);
				    //:清空输入框
					this.clear();
				}
			}
			public void queryman() throws SQLException{
				con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=utf8","root","123456");
				ResultSet rs = sql.executeQuery("SELECT* FROM list_1 WHERE  name='管理员'");	
				if (rs.next()) {
					//:将管理员的用户名和密码取出
					userword = rs.getString(3);
					pwd = rs.getString(4);
					System.out.println("成功获取到密码和用户名from数据库");
					System.out.println(userword + "	" + pwd + "	");
					//:调用登录方法
				}else
				{
					JOptionPane.showMessageDialog(null, "没有此用户,请重新输入!", "提示消息", JOptionPane.WARNING_MESSAGE);
				    
				}
			}
}
public class query extends JPanel implements ActionListener{ 
	Connection con; //与特定数据库的连接(会话)。
	  Statement sql; //用于执行静态 SQL 语句并返回它所生成结果的对象。
	  JButton b1,b2;//定义两个按钮
	  Object[] columns={"编号","姓名","学院","是否确诊患病","是否在武汉","是否在湖北","近期是否到达武汉","近期是否到达湖北",
"是否与武汉人员接触","是否与湖北人员接触","时间"};//字段
	   Object[][] data=new Object[200][11];
	   JTable table;
	   JScrollPane sc;
	query (){
		try{		//:错误处理机制
		    Class.forName("com.mysql.cj.jdbc.Driver");	//:通过 Class.forName为数据库管理系统加载一个JDBC驱动程序。
		    }
		   catch(ClassNotFoundException e){}		//:如果加载驱动失败 控制台抛出异常
		    try{									//:如果加载驱动成功, 调用驱动连接特定数据库
		     con=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=utf8","root","12");
		     sql=con.createStatement();      //:调取con成员方法获取Statement对象
		    }
		    catch(SQLException ee){}//:异常处理块
		   setLayout(new BorderLayout());//:布局为边框布局
		   JPanel p1=new JPanel();//:定义一个面板的对象为p1

		   table = new JTable(data, columns);
			table.setPreferredScrollableViewportSize(new Dimension(400, 300));
             sc = new JScrollPane(table) {
            	 public Dimension getPreferredSize() {
    			     return new Dimension(1300, 400);//:括号内参数,可以根据需要更改
    			   }
            };
	        p1.add(sc);
	        add(p1,"Center");
	        setSize(350,300);
	           setBackground(Color.pink);
		   b1=new JButton("查询全部");  
		   b2=new JButton("清空");
		   //:给两个按钮添加监视器
		   b1.addActionListener(this);
		   b2.addActionListener(this);
		   //:将两个按钮添加到面板p1
		   p1.add(b1);
		   p1.add(b2);   
}
@Override
public void actionPerformed(ActionEvent e) {
	if(e.getSource()==b1){
		try{insert();}
		catch(SQLException ee){}
	}
	 else if(e.getSource()==b2){
		 ((DefaultTableModel) table.getModel()).getDataVector().clear();   //:清除表格数据
		 ((DefaultTableModel) table.getModel()).fireTableDataChanged();//:通知模型更新
		 table.updateUI();	
	 }
}
public void insert() throws SQLException{
  int i,j;
  con=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/useruseUnicode=true&
characterEncoding=utf8","root","12");
  ResultSet rs = sql.executeQuery("SELECT*  FROM message" );
  i=0;
  j=0;
          while(rs.next()){
          	data[i][j++]=rs.getString("id");
              data[i][j++]=rs.getString("name");
              data[i][j++]=rs.getString("college");
              data[i][j++]=rs.getString("hot_message");
              data[i][j++]=rs.getString("where_wuhan");
              data[i][j++]=rs.getString("where_hubei");
              data[i][j++]=rs.getString("come_wuhan");
              data[i][j++]=rs.getString("come_hubei");
              data[i][j++]=rs.getString("touch_wuhan");
              data[i][j++]=rs.getString("touch_wuhan");
              data[i][j]=rs.getString("time");
              i++;
              j=0;  
	}
	   con.close();	
 }
}
  • 小组讨论

    • 我们主要分工负责系统中用户和管理员两部分内容

PSP 内容 计划完成需要的时间(min) 实际完成需要的时间(min)
Planning 计划 20 30
*Estimate 预计开发时长,规划大致工作步骤 15 20
Development 开发 400 500
*Analysis 需求分析 (包括学习新技术) 60 90
*Design Spec 生成设计文档 30 30
*Design Review 设计复审 (和同学审核设计文档) 10 15
*Coding Standard 代码规范 (为目前的开发制定合适的规范) 5 5
*Design 具体设计 100 120
*Coding 具体编码 400 500
*Code Review 代码复审 60 30
*Test 测试(自我测试,修改代码,提交修改 60 120
*Reporting 报告 50 60
*Test Report 测试报告 60 70
*Size Measurement 计算工作量 5 5
*Postmortem & Process Improvement Plan 事后总结 ,并提出过程改进计划 30 30

总结

这次实验,我们基本上完成了一个疫情管理系统。该系统主要分为用户和管理员两个模块,用户可以对每天的个人疫情信息进行填写,并且查询自己所填报的信息,而管理员可以对所有的信息进行查询、修改、删除、更新。但是对于提醒填报的通知功能我们没有实现.但是,对于这次的工作,我还是觉得两个人协作会有更有效、更好的效果,而且和我合作的同学能力比我强,我也学习到了很多。

原文地址:https://www.cnblogs.com/Weiron/p/12588171.html