实验三 软件工程结对项目《{0-1}KP 实例数据集算法实验平台》项目报告
项目概况 |
内容 |
---|---|
班级博客链接 | 2019卓越工程师班 |
作业要求链接 | 实验三 软件工程结对项目 |
我的课程学习目标 | (1)体验软件项目开发中的两人合作,练习结对编程(Pair programming)。 (2)掌握Github协作开发软件的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | (1)练习了结对编程。 (2)自学了《现代软件工程—构建之法》第三至第四章内容。 |
结对方学号姓名 | 201971010241-王晨阳 |
结对方本次博客作业链接 | 201971010241-王晨阳 |
项目Github的仓库链接地址 | 0-1背包问题实验平台 |
正文
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;
(1)代码风格规范:
代码风格的原则是:简明,已读,无二义性。每一个优秀的程序员都应该遵循代码规范及编码原则。
a、缩进:4个空格,在Visual Studio和其他的一些编辑工具中都可以定义Tab键扩展成为几个空格键。不用Tab键的理由是,Tab键在不同的情况下会显示不同的长度,严重干扰阅读体验。4个空格的距离从可读性来说,正好。
b、行宽:行宽必须限制,但是以前有些文档规定的80字符行宽太小了(以前的计算机/打字机显示行宽为80字符),现在时代不同了,可以限定为100字符。
c、括号:在复杂的条件表达式中,用括号清楚地表示逻辑优先级。
d、分行:不要把多条语句放在一行
e、变量命名:只能由字母、数字、下划线组成;第一个字符必须是英文字母;不可以是系统的关键词;不可以包含标点符号和类型说明符。
(2)代码设计规范:
代码设计规范不光是程序书写的格式问题,而且牵涉到程序设计、模块之间的关系、设计模式等方方面面,这里又有不少内容与具体程序设计语言息息相关(如C、C++、Java、C#),但是也有通用的原则,这里主要讨论通用的原则。如果你写的程序会被很多人使用,并且你得加班调试自己的程序,那最好还是遵守下面的规定。
a、函数:现代程序设计语言中的绝大部分功能,都在程序的函数( Function 、 Method )中实现。关于函数,最重要的原则是:只做一件事,并且要做好。
b、goto:函数最好有单一的出口,为了达到这一目的,可以使用goto。只要有助于程序逻辑的清晰体现,什么方法都可以使用,包括 goto。
(3)代码复审:
形式
名称 |
形式 |
目的 |
---|---|---|
自我复审 | 自己VS自己 | 用同伴复审的标准来要求自己。不一定最有效,因为开发者对自己总是过于自信。如果能持之以恒,则对个人有很大好处 |
同伴复审 | 复审者VS开发者 | 简便易行 |
团队复审 | 团队VS开发者 | 有比较严格的规定和流程,适用于关键的代码,以及复市后不再更新的代码覆盖率高—有很多双眼睛盯着程序,但效率可能不高(全体人员都要到会) |
(4)结对编程:
在结对编程模式下,一对程序员肩并肩、平等地、互补地进行开发工作。他们并排坐在一台电脑前,面对同一个显示器,使用同一个键盘、同一个鼠标一起工作。他们一起分析,一起设计,一起写测试用例,一起编码,一起做单元测试,一起做集成测试,一起写文档,等等。
结对编程不是程序开发者独到的发明,在现实生活中,也存在着类似的搭档关系:
越野赛车(驾驶,领航员)
驾驶飞机(驾驶,副驾驶)
这些任务都有共同点:在高速度中完成任务,任务有较高的技术要求,任务失败的代价很高。结对编程中有两个角色:
1.驾驶员(Driver ):控制键盘输入。
2.领航员(Navigator ):起到领航、提醒的作用。
这两个角色是可以互换的。和现实生活中的例子类似,一个人负责具体的执行(驾驶,用键盘编写程序等),另一人负责导航、检查、掩护等。
这种方式自然会引发很多疑问——
·编程从来就是一个人的活动。学校里是这么教的,我们一直以来也是这么做的。两个人本来可以去做两个模块,现在一个模块两个人写是不是一种浪费(这可是两份工资哦)?
·我习惯一个人写程序,不喜欢被人盯着工作,这样我不自在,无法工作。·会不会出现、“我只领航,不用敲键盘,多爽……”的情况?
·身旁的这个家伙老是问问题,他/她不会看书么?我都无法专心工作了。
·会不会出现、“我只领航,不用敲键盘,多爽……”的情况?
......
每人在各自独立设计、实现软件的过程中不免要犯这样那样的错误。在结对编程中,因为有随时的复审和交流、程序各方面的质量取决于一对程序员中各方面水平较高的那一位。这样,程序中的错误就会少得多,程序的初始质量会高很多,这样会省下很多以后修改、测试的时间。具体地说,结对编程有如下的好处:
1.在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作解决问题的能力更强。两人合作,还有相互激励的作用,工程师看到别人的思路和技能,得到实时的讲解,受到激励,从而努力提高自己的水平,提出更多创意。
2,对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
3.在企业管理层次上,结对能更有效地交流,相互学习和传递经验,分享知识,能更好地应对人员流动。
总之,如果运用得当,结对编程可以取得更高的投入产出比(Return of Investment )。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价;
(1)对项目博文作业进行阅读并进行评论,评论要点包括:博文结构、博文内容、博文结构与PSP中“任务内容”列的关系、PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究,将以上评论内容发布到博客评论区。
(2)克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。
(3)依据复审结果尝试利用github的Fork、Clone、Push、Pull request、Merge pull request等操作对同伴个人项目仓库的源码进行合作修改。
项目 |
内容 |
---|---|
结对方 | 王晨阳 |
结对方实验二博客链接 | 实验二 软件工程个人项目 |
结对方实验二Github项目仓库链接 | {0-1}背包问题 |
(1)博客评论:
条目清楚,详略得当,较为全面的阐述了完成任务的过程,且对于所提的问题加以底色进行强调,突出重点,且结构清楚好理解,图文并茂。
(2)克隆项目,阅读并测试:
克隆到本地
测试
代码检查表
项目 |
内容 |
---|---|
1.概要部分 | |
代码能符合需求和规格说明么? | 是 |
代码设计是否考虑周全? | 否 |
代码容易维护么? | 容易 |
2.设计规范部分 | |
设计是否遵从已知的设计模式或项目中常用的模式? | 是 |
有没有硬编码或字符串/数字等存在? | 无 |
有没有无用的代码可以清除? | 无 |
代码有没有依赖于某一平台,是否会影响将来的移植? | 否 |
开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现? | 能 |
3.代码规范部分 | |
修改的部分符合代码标准和风格么? | 符合 |
4.具体代码部分 | |
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 无 |
参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度是以0开始计数还是以1开始计数? | 无 |
switch语句的default分支是如何处理的?循环有没有可能出现死循环? | 无switch语句,无死循环 |
数据结构中有没有用不到的元素? | 无 |
5.效能部分 | |
代码的效能(Performance)如何? | 效能一般 |
代码中,特别是循环中是否有明显可优化的部分? | 有 |
对于系统和网络的调用是否会超时?如何处理? | 否 |
6.可读性 | |
代码可读性如何? | 良好 |
7.可测试性 | |
代码是否需要更新或创建新的单元测试? | 不需要 |
任务3:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台;
(1)平台基础功能:实验二 任务3;
(2){0-1}KP 实例数据集需存储在数据库;
(3)平台可动态嵌入任何一个有效的{0-1}KP 实例求解算法,并保存算法实验日志数据;
(4)人机交互界面要求为GUI界面(WEB页面、APP页面都可);
(5)查阅资料,设计遗传算法求解{0-1}KP,并利用此算法测试要求(3);
(6)附加功能:除(1)-(5)外的任意有效平台功能实现。
·项目背景:
背包问题(Knapsack Problem,KP)是NP Complete问题,也是一个经典的组合优化问题,有着广泛而重要的应用背景。{0-1}背包问题({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP问题形式,它的一般描述为:从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,如何选择才能使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大?
·需求分析:
目前,求解折扣{0-1}背 包 问 题(D{0-1}KP)的主要算法是基于动态规划的具有伪多项式时间的确定性算法,当D{0-1}KP实例中各项的价值系数与重量系数在大范围内取值时缺乏实用性。折扣{0-1}背包问题(Discounted {0-1} Knapsack Problem,D{0-1}KP)是比0-1背包还要难以求解的NP-hard问题。提出了一种求解D{0-1}KP的新遗传算法GADKP。
·遗传算法的基本运算过程:
(1)初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。
(2)个体评价:计算群体P(t)中各个个体的适应度
(3)选择运算:将选择算子作用于群体。选择的目的是把优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。
(4)交叉运算:将交叉算子作用于群体。遗传算法中起核心作用的就是交叉算子。
(5)变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。群体P(t)经过选择、交叉、变异运算之后得到下一代群体P(t+1)。
(6)终止条件判断:若t=T,则以进化过程中所得到的具有最大适应度个体作为最优解输出,终止计算。
·遗传算法的实现
# 遗传算法
start2 = time.perf_counter()
heigh = heigh+70
m = 32 # 规模
N = 500 # 迭代次数
Pc = 0.8 # 交配概率
Pm = 0.05 # 变异概率
V =profit[i]
W =weight[i]
n = len(W) # 染色体长度
w = cubage[i]
C = self.init(m, n)
S,F = self.fitness(C,m,n,W,V,w)
B ,y = self.best_x(F,S,m)
Y =[y]
for i in range(N):
p = self.rate(F)
C = self.chose(p, C, m, n)
C = self.match(C, m, n, Pc)
C = self.vari(C, m, n, Pm)
S, F = self.fitness(C, m, n, W, V, w)
B1, y1 = self.best_x(F, S, m)
if y1 > y:
y = y1
Y.append(y)
·数据库的建立
# 创建数据库
def CreateDataBase(self):
global i
global d
global cubage
global profit
global weight
global pw
conn = sqlite3.connect('mrsoft.db')
cursor = conn.cursor()
cursor.execute('DROP TABLE IF EXISTS user')
cursor.execute('create table if not exists user (num int(10) primary key,profit int(20), weight int(20))')
cubage[i] = max(list(map(int,re.findall(r'\d+',line[i*8+3]))))
profit[i] = list(map(int,re.findall(r'\d+',line[i*8+5])))
weight[i] = list(map(int,re.findall(r'\d+',line[i*8+7])))
pw[i] = list(map(lambda x:x[0]/x[1],zip(profit[i],weight[i])))
for j in range(0,d):
cursor.execute('insert into user (num,profit,weight) values ("%d","%d","%d")'%(j,profit[i][j],weight[i][j]))
cursor.execute('select * from user')
result=cursor.fetchall()
cursor.close()
conn.commit()
conn.close()
return result
·人机交互页面的建立
# 创建“确定”和“取消”按钮,并绑定事件
self.bt_confirm = wx.Button(panel, label='确定')
self.bt_confirm.Bind(wx.EVT_BUTTON,self.OnclickSubmit)
self.bt_cancel = wx.Button(panel, label='取消')
self.bt_cancel.Bind(wx.EVT_BUTTON,self.OnclickCancel)
# 创建文本,左对齐
self.title = wx.StaticText(panel, label="1、beibao.txt\n")
self.label_file = wx.StaticText(panel, label="希望读取的文件:")
self.text_file = wx.TextCtrl(panel, style=wx.TE_LEFT)
# 添加容器,容器中控件按横向并排排列
hsizer_file = wx.BoxSizer(wx.HORIZONTAL)
hsizer_file.Add(self.label_file, proportion=0, flag=wx.ALL, border=5)
hsizer_file.Add(self.text_file, proportion=1, flag=wx.ALL, border=5)
hsizer_button = wx.BoxSizer(wx.HORIZONTAL)
hsizer_button.Add(self.bt_confirm, proportion=0, flag=wx.ALIGN_CENTER, border= 5)
hsizer_button.Add(self.bt_cancel, proportion=0, flag=wx.ALIGN_CENTER, border=5)
# 添加容器,容器中控件按纵向并排排列
vsizer_all = wx.BoxSizer(wx.VERTICAL)
vsizer_all.Add(self.title, proportion=0, flag=wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER,border=30)
vsizer_all.Add(hsizer_file, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
vsizer_all.Add(hsizer_button, proportion=0, flag=wx.ALIGN_CENTER | wx.TOP, border=20)
panel.SetSizer(vsizer_all)
·运行结果
·结对PSP
Planning |
计划 |
||
估计这个任务需要多少时间,并规划大致工作步骤 |
|||
Developement |
开发 |
||
需求分析(包括学习新技术) |
|||
生成设计文档 |
|||
设计复审(和同事审核设计文档) |
|||
代码规范(为目前的开发制定合适的规范) |
|||
具体设计 |
|||
具体编码 |
|||
代码复审 |
|||
测试(自我测试,修改代码,提交修改) |
|||
Reporting |
报告 |
||
测试报告 |
|||
设计工作量 |
|||
事后总结,并提出过程改进计划 |
任务4:完成结对项目报告博文作业;
·实验总结:
通过本次实验项目,我体会到了1+1大于2的效果,并且这种合作不限于两个人之间。通过结对以及协同编程等技术手段,将不同的人连结在同一个项目中,每一个成员都可以对项目进行思考编程,发挥长处,不同成员之间又可以进行互补。这在软件项目开发过程中是非常必要的,因为个人的能力和精力注定是有限的,只有更多的成员加入进来,团队能力的上限才会提高。
·撰写实验报告:已完成。