个人第三次作业:结对编程
个人第三次作业——结对编程
结对伙伴地址 | https://www.cnblogs.com/bronze/ |
---|---|
作业地址 | https://github.com/bronzeonestar/PairProgramming.git |
项目地址 | https://github.com/bronzeonestar/PairProgramming.git |
Team Members
140 刘川:负责项目主要的开发。
122 张新明:负责项目各个环节的设计,测试,评估。
在关键功能开发过程,编码阶段,单元测试由两人结对完成。附加小功能由122进行测试,140进行开发。由于题目要求仅用VS开发,就没有使用数据库,有关学生的增删改查功能并没有实现,算是一个遗憾。
———————————————————————————————————————————————
Part1.任务描述
实现一个WinForm随机点名的程序
要求:
- WinForm有基本的UI,实现班级随机点名的功能
- 体现类的设计,分层思想
- 学生的加载进度用进度条跟踪显示
- 添加自己的创新功能
- 进行单元测试
————————————————————————————————————————————
Part2.PSP表与流程图
PSP表
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 10 |
Estimate | 估计这个任务需要多少时间 | 5 | 5 |
Development | 开发 | 480 | 600 |
Analysis | 需求分析 | 30 | 50 |
Design Spec | 生成设计文档 | 120 | 200 |
Design Review | 设计复审 (和同学审核设计文档) | 60 | 60 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 40 | 40 |
Design | 具体设计 | 60 | 80 |
Coding | 具体编码 | 90 | 120 |
Code Review | 代码复审 | 60 | 90 |
Test | 测试(自我测试,修改代码,提交修改) | 90 | 120 |
Reporting | 报告 | 20 | 20 |
Test Report | 测试报告 | 20 | 30 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 20 | 15 |
流程图
在编码之前,我们商讨了一下大概流程,制作了大致的流程图。起初我们对这些功能的实现并没有头绪,因为仅靠VS来进行开发,不依靠数据库,对结果的保存,以及对学生信息的增删改查有一定难度。后来在老师的启发下,直接构造泛型数组对其进行学生信息的录入,以及学生加载进度条的实现都能较好的完成。
———————————————————————————————————————————————
Part3.程序概述及关键代码
Foreword
本次编码使用了4个项目,这样每个大功能使用一个项目来完成,然后添加引用,实现功能的互通。
-
1.登录
做了一个简单的登录界面,但是由于没有连接数据库,无法给予权限,所以这里的用户名和密码只要不为空就可登录成功。密码属性设置的为不可显示。
-
2.主界面
若是进行全体点名,直接在主界面上操作就好,这里的点名系统界面,在借鉴了肖老师的基础上,进行了自己的创新及改进。 -
3 .随机点到功能
此功能不仅可以支持随机点到功能,而且支持输入随机的数量。当输入字符或者超出班级人员数量时,会弹出提示。
代码
private void butConfirm_Click(object sender, EventArgs e)
{
//获取学生数据源
try
{
StudentDAO stuDao = new StudentDAO();
stuList = stuDao.getAllStudents();
DataTable dt = new DataTable();
dt.Columns.Add("stuID", Type.GetType("System.String"));
dt.Columns.Add("stuName", Type.GetType("System.String"));
ArrayList alist = new ArrayList();
int t = int.Parse(textBox1.Text);
if (int.Parse(textBox1.Text) > stuList.Count || int.Parse(textBox1.Text) < 0)
{
MessageBox.Show("输入有误!", "提示");
}//防止输入数字超过班级人数
else
{
for (int i = 0; i < t; i++)//防止随机到同一位同学
{
Random r = new Random(GetRandomSeed());
int m = r.Next(stuList.Count);
if (!alist.Contains(m))
dt.Rows.Add(stuList[m].Id, stuList[m].Name);
else t++;
alist.Add(m);
}
dgvRandom.DataSource = dt;
}
}
catch
{
MessageBox.Show("输入有误!", "提示");
}
}
- 4.展示本次点名结果 && 可选择路径输出结果(创新功能)
代码
private void butSave_Click(object sender, EventArgs e)
{
StreamWriter myStream;
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
//文件保存的路径
saveFileDialog1.FilterIndex = 1;
//默认选为txt文件
saveFileDialog1.RestoreDirectory = true;
//默认保存路径为桌面
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
//写入结果
myStream = new StreamWriter(saveFileDialog1.FileName);
myStream.WriteLine("本次应到学生:" + stuList.Count + "人,缺席:" + absenceName.Count + "人,请假人数:" + absenceName.Count + "人");
myStream.Write("缺席学生姓名:");
foreach (string i in absenceName)
{
myStream.Write(i + ",");
}
myStream.Write("。请假学生姓名:");
foreach (string i in askForLeaveName)
{
myStream.Write(i + ",");
}
myStream.Write("。");
myStream.WriteLine(DateTime.Now);
myStream.Close();//关闭流
}
———————————————————————————————————————————————
Part4.结对共同单元测试
- 1.随机点到功能测试
public class UnitTest1
{
List<Student> stuList;
List<Student> Test1=null;
[TestMethod] /**测试随机点到的同学是否是有重复,且是否为”真随机点到“
由于Winform和任务台不一样在此重新写一个相同的功能方法给任务台
**/
public void TestMethod1()
{
for (int time = 100; time > 0; time--)//随机点到30次
{
int p = 30;//随机点到30人,全班一共39人
Test1 = new List<Student>();
StudentDAO stuDao = new StudentDAO();
stuList = stuDao.getAllStudents();
if (p > stuList.Count || p < 0)
{
Console.WriteLine("输入有误!");
}
else
{
for (int i = 0; i < p; i++)//防止随机到同一位同学
{
Random r = new Random(GetRandomSeed());
int m = r.Next(stuList.Count);
if (Test1 == null || !Test1.Contains(stuList[m]))
Test1.Add(stuList[m]);
else
p++; //若已经随机到这位同学,则再随即一次
}
}
for (int i = 0; i < Test1.Count; i++) //检验结果是否含有重复的同学
{
for (int j = i + 1; j < Test1.Count; j++)
{
if (Test1[i] == Test1[j])
{
Assert.IsFalse(true);
}
}
}
}
}
static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
}
———————————————————————————————————————————————
Part5.代码规范及代码审查
代码规范
我们互相阅览了对方之前的项目代码,发现命名规则及代码格式都还是有着较大的出入,于是我们制定了一些规则来使我们在结对编程中代码的可读性及可扩展性更好。
-
命名规范
类命名:首字母大写,每个单词首字母大写(大驼峰命名法),尽量使用能够反映类功能的名词短语。
方法命名:首字母小写,之后每个单词首字母都大写(小驼峰法命名法)
变量命名:首字母小写,之后每个单词首字母都大写 -
注释
公共接口(注释要告诉阅读代码的人,当前类能实现什么功能)。
涉及到比较深层专业知识的代码(注释要体现出实现原理和思想)。
容易产生歧义的代码(但是严格来说,容易让人产生歧义的代码是不允许存在的)。
除了上述这三种情况,如果只能依靠注释才能读懂你的代码的时候,就要反思代码出现了什么问题。
最后,对于注释的内容,相对于“做了什么”,更应该说明“为什么这么做”。 -
代码优化
避免相同的代码段在多个地方出现相同的代码,必须归纳出来并且用一个类封装起来
语句嵌套层次不得超过3层,超出的必须抽取出中间函数
for,while循环 if,do等
及时删除或注释掉无用的代码
确定不使用的代码应该删除
代码审查
在结对共同编写关键功能代码的时候,122同学在一旁进行代码的审查。由于我和122同学的编码风格和逻辑有着差异,在审查过程中甚至有过因为一个变量的命名而争执讨论。但在一段磨合过后,不仅开发过程快了不少,代码的可读性也比以前有了较大的提升。而这同时也体现了代码规范的重要性。不过,代码审查也大大增加了项目开发的时间以及人力的消耗。
———————————————————————————————————————————————
Part6.总结
从此次结对编程来看,个人认为结对编程适合一些较有挑战性的项目,这样会加快项目的进度,而且效率比较高。如果是比较简单的项目的话,结对编程所投入的精力和时间与结果可能会无法比较。而且与之一同编程的队友也应该各有所长,互相了解,这样会少很多带有情绪上的争论。最后附上结对时候的照片