201971010246-王孜睿 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
班级博客链接 | 课程班级 |
这个作业的要求链接 | 作业要求 |
我的课程学习目标 | (1)体验软件项目开发中的两人合作,练习结对编程(Pair programming)。 (2)掌握Github协作开发程序的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | (1)通过该实验练习结对编程 (2)练习github操作方法并掌握 (3)掌握代码编写能力及规范 |
结对方学号-姓名 | 201971020204-曹霖枫 |
结对方本次博客作业链接 | 结对方链接 |
项目Github的仓库链接地址 | 仓库地址 |
任务一
理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念
1.代码规范
2.代码复审
定义:看代码是否在“代码规范”的框架内正确地解决了问题
代码复审形式:
名称 | 形式 | 目的 |
---|---|---|
自我复审 | 自己vs.自己 | 用同伴复审的标准来要求自己 |
同伴复审 | 复审者vs.开发者 | 简便易行(最基本复审手段) |
团队复审 | 团队vs.开发者 | 有比较严格的规定和流程,适用于关键的代码 |
代码复审目的:
-
找出代码的错误
-
发现逻辑错误
-
发现算法错误
-
发现潜在的错误和回归性错误
-
发现可能需要改进的地方
-
教育开发人员
代码复审步骤:
复审前:
-
代码必须成功编译
-
程序员必须测试过代码
-
程序员必须提供新的代码以及文件差异分析工作。用Windiff或VSTS自带工具都可以
-
面对面复审中,一般是开发者控制流程
-
复审者必须逐一提供反馈意见
-
开发者必须负责让所有的问题都得到满意解释
-
复审意见必须达成一致
复审后:
-
更正明显错误
-
对于无法更正错误在项目管理软件中创建Bug并记录
-
把错误记在“我常犯的错误”表中
3.结对编程
为什么要结对编程?
每人在各自独立设计、实现软件的过程中不免要犯这样那样的错误。在结对编程中,因为有随时的复审和交流,程序各方面的质量取决于一对程序员中各方面水平较高的那一位。这样,程序中的错误就会少得多,程序的初始质量会高很多,这样会省下很多以后修改、测试的时间。具体地说,结对编程有如下的好处:
(1)在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力。
(2)对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
(3)在心理上, 当有另一个人在你身边和你紧密配合, 做同样一件事情的时候, 你不好意思开小差, 也不好意思糊弄。
(4)在企业管理层次上,结对能更有效地交流,相互学习和传递经验,能更好地处理人员流动。因为一个人的知识已经被其他人共享。
如何结对编程?
(1)驾驶员:写设计文档,进行编码和单元测试等XP开发流程。
(2)领航员:审阅驾驶员的文档、驾驶员对编码等开发流程的执行;考虑单元测试的覆盖程度;是否需要和如何重构;帮助驾驶员解决具体的技术问题。
(3)驾驶员和领航员不断轮换角色,不宜连续工作超过一小时。领航员要控制时间。
(4)主动参与。任何一个任务都首先是两个人的责任,也是所有人的责任。没有“我的代码”、“你的代码”或“她的代码”,只有“我们的代码”。
(5)只有水平上的差距,没有级别上的差异。尽管可能大家的级别资历不同,但不管在分析、设计或编码上,双方都拥有平等的决策权利。
结对编程是个渐进的过程
有效率的结对编程不是一天就能做到的。结对编程是一个相互学习、相互磨合的渐进过程。开发人员需要时间来适应这种新的开发模式。刚开始的结对编程很可能不比单独开发效率更高。但是在度过了学习阶段后,结对编程小组的开发质量、开发时间通常比两人单独开发有明显的改善。
要避免的误区
不分情况强迫每个任务都用结对编程的方式, 或者固执地遵守一些教条 (例如 "结对的成员必须水平相当..." 等等)
没有提供足够的支持就匆忙上马结对编程 - 工作环境, 硬件, 对结果的期望都要准备好。
在具体作法上加入过多限制或要求 - 应该让两位程序员自己决定具体的方式。
不适合结对编程的情况
并不是所有的项目都适合结对编程,下面是一些不适合使用的例子。
1)处于探索阶段的项目,需要深入地研究,在这种情况下,一个人长时间的独立钻研是有必要的。
2)在做后期维护的时候,如果维护的技术含量不高,只需要做有效的复审即可,不必拘泥于形式,硬拉一个人来结对唱二人转。
3)如果验证测试需要运行很长时间,那么两个人在那里等待结果是有点浪费时间。
4)如果团队的人员要在多个项目中工作,不能充分保证足够的结对编程时间,那么成员要经常处于等待的状态,反而影响效率。
5)关键是如何最大限度地发挥“领航员”的作用,如果用处不大,也就无需结对。
两人合作的不同阶段
1.萌芽
2.磨合阶段
3.规范阶段
4.创造阶段
5.解体阶段
两人的合作——如何影响对方
方式 | 简介 | 逻辑/感情 | 推/拉 | 注解 |
---|---|---|---|---|
断言 (Assertion) | 就是这样吧,听我的,没错! | 感情 | 推—— 主动推动同伴做某事 | 感情很强烈,适用于有充分信任的同伴。语音、语调、肢体语言都能帮助传递强烈的信息 |
桥梁 (Bridge) | 能不能再给我讲讲你的理由…… | 逻辑 | 拉—— 吸引对方,建立共识 | 给双方充分条件互相了解 |
说服 (Persuasion) | 如果我们这样做,根据我的分析,我们会有这样的好处,a、 b、 c…… | 逻辑 | 推—— 让对方思考 有条理,建立在逻辑分析的基础上。 | 即使不能全部说服,对方也可能接受部分意见 |
吸引 (Attraction) | 你想过舒适的生活么?你想在家里发财么?加入我们的传销队伍吧,几个月后就可以有上万元的收入…… | 感情 | 拉—— 描述理想状态,吸引对方加入 | 可以有效地传递信息,但是要注意信息的准确性。夸大的渲染会降低个人的可信度 |
任务二
对结对方《实验二 软件工程个人项目》的项目成果进行评价
作业点评链接:
结对方仓库链接
代码复审的核查表
1.概要部分 | |
---|---|
(1)代码能符合需求和规格说明么? | 是 |
(2)代码设计是否有周全的考虑? | 是 |
(3)代码可读性如何? | 良好 |
(4)代码容易维护么? | 容易 |
(5)代码的每一行都执行并检查过了吗? | 是 |
2.设计规范部分 | |
(1)设计是否遵从已知的设计模式或项目中常用的模式? | 是 |
(2)有没有硬编码或字符串/数字等存在? | 否 |
(3)代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)? | 否 |
(4)开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现? | 能 |
(5)在本项目中是否存在类似的功能可以调用而不用全部重新实现? | 是 |
(6)有没有无用的代码可以清除? | 有 |
3.代码规范部分 | |
(1)修改的部分符合代码标准和风格么(详细条文略)? | 符合 |
4.具体代码部分 | |
(1)有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 无 |
(2)参数传递有无错误,字 | 无 |
(3)边界条件是如何处理的?Switch语句的Default是如何处理的?循环有没有可能出现死循环? | 无死循环 |
(4)有没有使用断言(Assert)来保证我们认为不变的条件真的满足? | 无 |
(5)有没有可能优化? | 有 |
(6)数据结构中是否有无用的元素? | 有 |
5.效能 | |
(1)代码的效能(Performance)如何?最坏的情况是怎样的? | |
(2)代码中,特别是循环中是否有明显可优化的部分? | 无 |
(3)对于系统和网络调用是否会超时?如何处理? | |
6.可读性 | |
代码可读性如何? | 良好 |
7.可测试性 | |
代码是否需要更新或创建新的单元测试? | 不需要 |
任务三
需求分析
- 本次任务内容为解决{0-1}背包问题。按照题目要求,由于第三项价值为前两项总和且重量小于其他两项之和,且要保证装入背包的价值最大,就需要计算出每三个项集中性价比最高的,在不超过背包容量的情况下装入。
功能设计
- 平台基础功能:实验二 任务3;
- {0-1}KP 实例数据集需存储在数据库;
- 平台可动态嵌入任何一个有效的{0-1}KP 实例求解算法,并保存算法实验日志数据;
- 人机交互界面要求为GUI界面(WEB页面、APP页面都可);
- 查阅资料,设计遗传算法求解{0-1}KP,并利用此算法测试要求(3);
- 附加功能:除(1)-(5)外的任意有效平台功能实现。
设计实现
- 本次实验所使用的数据库,用MySQL与python进行连接
- 程序主页面
- 数据选择
- 数据与结果的查看
- 散点图
- 运行记录
部分代码
- 数据库的连接
import pymysql.cursors
import pymysql
import pymysql.cursors
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': 'root',
'db': 'test',
'charset': 'utf8',
'cursorclass': pymysql.cursors.DictCursor,
}
connection = pymysql.connect(**config)
connection.autocommit(True)
cursor = connection.cursor()
def get_table_list():
results=[]
cursor.execute('show tables from test;')
query_result = cursor.fetchall()
for i in query_result:
results.append(i['Tables_in_test'])
return results
def get_data(sets_id):
sql='select * from kpdata where id='+sets_id+';'
cursor.execute(sql)
query_result = cursor.fetchall()
return query_result
- 遗传算法
# 遗传算法
def init(N,n):
C = []
for i in range(N):
c = []
for j in range(n):
a = np.random.randint(0,2)
c.append(a)
C.append(c)
return C
##评估函数
# x(i)取值为1表示被选中,取值为0表示未被选中
# w(i)表示各个分量的重量,v(i)表示各个分量的价值,w表示最大承受重量
def fitness(C,N,n,W,V,w):
S = []##用于存储被选中的下标
F = []## 用于存放当前该个体的最大价值
for i in range(N):
s = []
h = 0 # 重量
f = 0 # 价值
for j in range(n):
if C[i][j]==1:
if h+W[j]<=w:
h=h+W[j]
f = f+V[j]
s.append(j)
S.append(s)
F.append(f)
return S,F
##适应值函数,B位返回的种族的基因下标,y为返回的最大值
def best_x(F,S,N):
y = 0
x = 0
B = [0]*N
for i in range(N):
if y<F[i]:
x = i
y = F[x]
B = S[x]
return B,y
## 计算比率
def rate(x):
p = [0] * len(x)
s = 0
for i in x:
s += i
for i in range(len(x)):
p[i] = x[i] / s
return p
## 选择
def chose(p, X, m, n):
X1 = X
r = np.random.rand(m)
for i in range(m):
k = 0
for j in range(n):
k = k + p[j]
if r[i] <= k:
X1[i] = X[j]
break
return X1
##交配
def match(X, m, n, p):
r = np.random.rand(m)
k = [0] * m
for i in range(m):
if r[i] < p:
k[i] = 1
u = v = 0
k[0] = k[0] = 0
for i in range(m):
if k[i]:
if k[u] == 0:
u = i
elif k[v] == 0:
v = i
if k[u] and k[v]:
# print(u,v)
q = np.random.randint(n - 1)
# print(q)
for i in range(q + 1, n):
X[u][i], X[v][i] = X[v][i], X[u][i]
k[u] = 0
k[v] = 0
return X
##变异
def vari(X, m, n, p):
for i in range(m):
for j in range(n):
q = np.random.rand()
if q < p:
X[i][j] = np.random.randint(0,2)
return X
PSP
PSP2.1 | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 30 | 35 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 35 |
Development | 开发 | 600 | 780 |
Analysis | 需求分析 (包括学习新技术) | 30 | 55 |
Design Spec | 生成设计文档 | 10 | 10 |
Design Review | 设计复审 (和同事审核设计文档) | 5 | 5 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 5 | 10 |
Design | 具体设计 | 50 | 50 |
Coding | 具体编码 | 300 | 450 |
Code Review | 代码复审 | 100 | 100 |
Test | 测试(自我测试,修改代码,提交修改) | 100 | 100 |
Reporting | 报告 | 50 | 50 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 30 | 30 |
实验总结
通过本次实验,我对于github操作方法更加熟悉,并且对PSP的作用有了更深刻的认识,而且通过阅读构建之法学习了代码规范和代码复审的知识,对于结对很有感想。通过此次实验,我理解到了结对所带来的并非固定的一种效果,而是三种:1+1<2;1+1=2;1+1>2;我认为产生何种效果主要取决与和结对方的沟通,以及在工作分配和设计方面的理解到位与否,总的来说,结对做项目利大于弊,既可以锻炼自己,又可以通过他人学到知识,何乐而不为?
- 部分线上沟通过程如下