201971010157-张颖 实验三 结对项目-《{0-1}KP实例数据集算法实验平台》
项目 | 内容 |
课程班级博客链接 | 2019级卓越班 |
这个作业要求链接 | 实验三 软件工程结对项目 |
我的课程学习目标 |
|
这个作业在哪些方面帮助我实现学习目标 |
|
结对方学号-姓名 | 201971010106-陈玉英 |
结对方本次博客作业链接 | 201971010106-陈玉英 实验三 结对项目-《{0-1}KP实例数据集算法实验平台》项目报告 |
本项目Github的仓库链接地址 | https://github.com/xiaokaxi08042/text2 |
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念
代码规范-
- 代码规范可以分为两个部分:
- 代码风格规范-主要是文字上的规定、看似表面文章,实际上非常重要
- 代码设计规范-牵扯到程序设计、模块之间的关系、设计模式等方方面面的通用规则
代码风格规范-
- 代码风格的原则是:简明,易读,无二义性
- 缩进:4个空格比tab键更好,tab键在不同的情况下会显示不同的长度,严重干扰阅读体验,4个空格的距离从可读性来说,正好。
- 行宽:行宽必须限制,以前有些文档规定的80字符行宽太小,现在可以先定为100字符
- 括号:在复杂的条件表达式中,用括号清楚地表示逻辑优先级
- 断行与空白的{}行:每个“{”和“}”都独占一行
- 分行:不要把多条语句放在一行上,更严格的说,不要把多个变量定义在一行上
- 命名:(1)在变量名中不要提到类型或其他语法方面的描述(2)避免过多的描述(3)如果信息可以从上下文中得到,那么此类信息就不必写在变量名中(4)避免可要不可要的修饰词
- 下划线:用来分隔变量名字中的作用域标注和变量的语义
- 大小写:所有单词的第一个字母都大写(Pascal);第一个单词全部小写,随后单词随Pascal形式
- 注释:(1)解释程序做什么,为什么这样做,以及要特别注意的地方(2)复杂的注释应该放在函数头(3)注释要随着程序的修改而不断更新(4)注释应该只用ASCII字符,不要用中文或其他特殊字符
代码设计规范-
- 代码设计规范不光是程序书写的格式问题,而且牵扯到程序设计、模块之间的关系、设计模式等方方面面,这里又有不少内容与具体程序设计语言息息相关,但是也有通用的规则,主要有——
- 函数:现代程序设计语言中的绝大部分功能,都在程序 的函数中实现
- goto:函数最好有单一的出口,为了达到这一目的,可以使用goto
- 错误处理:(1)参数处理(2)断言
- 处理c++中的类
代码复审-
- 定义:看代码是否在代码规范的框架内正确的解决了问题
- 形式:
名称 |
形式 |
目的 |
自我复审 |
自己vs.自己 |
用同伴复审的标准来要求自己。不一定最有效,因为开发者对自己总是过于自信。如果能持之以恒,则对个人有很大好处 |
同伴复审 |
复审者vs.开发者 |
简单易行 |
团队复审 |
团队vs.开发者 |
有比较严格的规定和流程,适用于关键的代码,以及复审后不再更新的代码覆盖率高——有很多双眼睛盯着程序,但效率可能不高 |
- 目的:
- 找出代码的错误
- 发现逻辑错误
- 发现算法错误
- 发现潜在的错误和回归性错误
- 发现可能需要改进的地方
- 互相教育开发人员,传授经验
- 步骤:
- 代码必须成功地编译
- 程序员必须测试过代码
- 程序员必须提供新的代码,以及文件差异分析工具
- 在面对面的复审中,一般是开发者控制流程,讲述修改的前因后果。但是复审者有权在任何时候打断叙述,提出自己的意见。
- 复审者必须逐一提供反馈意见。
- 开发者必须负责让所有的问题都得到满意的解释或解答,或者在TFS中创建爱你新的工作项以确保这些问题会得到处理。
- 对于复审的结果,双方必须达成一致的意见
- 代码复审的核查表:
概要部分 |
|
设计规范部分 |
|
代码规范部分 |
修改的部分符合代码标准和风格么? |
具体代码部分 |
|
效能 |
|
可读性 |
代码可读性如何?有没有足够的注释? |
可测试性 |
代码是否需要更新或创建新的单元测试?针对特定领域的开发(如数据库、网页、多线程等),可以整理专门的核查表。 |
结对编程-
- 结编程是一个相互学习、相互磨合的渐进过程。
- 优点:
- 在开发层次,结对编程能提供更好的设计质量和代码质量,良人合作解决问题的能力更强。两人合作,还有相互激励的作用,工程师看到别人的思路和技能,得到实时的讲解,受到激励,从而努力的提高自己的水平,提出更多的创意。
- 对开发人员来说,就地工作能带来更多的信心,高质量的产出能带来更高的满足感。
- 在企业管理层次上,就地能更有效地交流,相互学习和传递经验、分享知识,能更好地应对人员流动。
- 两人合作的不同阶段和技巧:
- 萌芽阶段
- 磨合阶段
- 规范阶段
- 创造阶段
- 解体阶段
- 影响他人的几种方式:
- 断言
- 桥梁
- 说服
- 吸引
- 评论别人的三种层次:
- 最外层:行为和后果
- 中间层:习惯与动机
- 最内层:本质和固有属性
- 如何正确地给予反馈:“三明治”办法
- 先来一片面包,做好铺垫:强调双方的共同点,从团队共同的愿景讲起,让对方觉得处于一个安全的环境。
- 再把肉放上:这时就可以把建设性的意见加工好,加上生菜、佐料等。怎么准备这块肉也有讲究,在提供反馈时,不宜完全沉溺于过去的陈年谷子烂芝麻,给别人做评价,下结论。这样会造成一种“你就是做得不好,我恨你”的情绪。不妨换个角度,展望将来的结果,强调“过去你做得不够,但是我们以后可以做得更好”。在技术团队里,我们的反馈还是要着重于“行为和后果”这一层面,不要贸然深入到“习惯和动机”、“本质”除非情况非常严峻,需要触动别人内心深处,让别人悬崖勒马。
- 再来一片面包:呼应开头,鼓励对方把工作做好。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价
- 结对方博客链接:201971010106-陈玉英 实验二 个人项目 —《{0-1}背包问题》项目报告
- 结对方Github项目仓库链接:https://github.com/15294140835
- 符合(1)要求的博客评论:
- 符合(2)要求的代码审查表:
概要部分 | |
代码符合需求和规格说明么? | 符合 |
代码设计是否考虑周全? | 考虑的不是很周全 |
代码可读性如何? | 可读性好,有注释 |
代码容易维护么? | 层次清晰,模块化不错,遵从基于接口而非实现编程的原则,容易维护 |
代码的每一行都执行并检查过了吗? | 是 |
设计规范部分 | |
设计是否遵从已知的设计模式或项目中常用的模式? | 是 |
有没有硬编码或字符串/数字等存在? | 没有直接将数据嵌入到程序中,没有硬编码存在 |
代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到 Win64 ) ? | 没有依赖于某一平台 |
开发者新写的代码能否用已有的 Library/SDK/Framework 中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现? | 没有用其功能实现 |
有没有无用的代码可以清除? | 有 |
代码规范部分 | |
修改的部分符合代码标准和风格么? | 符合 |
具体代码部分 | |
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 有对错误进行处理,对于调用的外部函数,检查了返回值没有发现错误 |
参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数? | 参数传递没有错误,字符串的长度是字符的个数,ASCII码下也是字节数,是以0开始计数 |
边界条件是如何处理的? switch语句的default分支是如何处理的?循环有没有可能出现死循环? | 没有用到switch语句,没有出现死循环 |
有没有使用断言(Assert)来保证我们认为不变的条件真的得到满足? | 没有使用断言 |
对资源的利用,是在哪里申请,在哪里释放的?有无可能存在资源泄漏(内存、文件、各种GUI资源、数据库访问的连接等等)?有没有优化的空间? | 因程序功能较为简单,没有使用到GUI资源、数据库等 |
数据结构中有没有用不到的元素? | 没有用不到的元素 |
效能 | |
代码的效能(Performance)如何?最坏的情况是怎样的? | 效能一般,在数据量很大时会运行较长时间 |
代码中,特别是循环中是否有明显可优化的部分? | 没有明显可优化的部分 |
可读性 | |
代码可读性如何?有没有足够的注释? | 可读性很好,注释足够 |
可测试性 | |
代码是否需要更新或创建新的单元测试?针对特定领域的开发(如数据库、网页、多线程等),可以整理专门的核查表。 | 实验二的代码没有使用到数据库、网页等的开发 |
- 结对方项目仓库中的Fork、Clone、Push、Pull request、Merge pull request日志数据
Fork 是 Github 上的常用操作之一,不同于 Star,Fork 会将进行 Fork 操作那一刻的仓库代码完全复制到自己的仓库下。Fork 之后,可能会为原仓库添加一个 Feature,之后发起 Pull Request
克隆:
运行:
fork:
任务3:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台
- 需求分析陈述——采用“3W”分析法
-
- what:需求是什么
-
- 采用动态规划法、贪心算法和回溯算法求解不超过背包容量的最大价值和解向量
- 绘制价值重量为横轴,价值为纵轴的数据散点图
- 输出的最优解和求解时间可保存为txt文件
- 实例数据集存储在数据库
- 平台可动态嵌入任何一个有效的{0-1}KP 实例求解算法,并保存算法实验日志数据;
- 人机交互界面为GUI界面
- 设计遗传算法求解{0-1}KP,并利用此算法测试要求
-
- why:为什么会产生这样的需求
-
- 用多种算法解决0-1背包问题
- 更好的存储和管理数据
- 增加用户的体验感
-
- how:如何将需求转化为产品进行后续的价值分析
- 软件设计说明
- 软件实现及核心功能代码展示:软件包括哪些类,这些类分别负责什么功能,他们之间的关系怎样?类内有哪些重要的方法,关键的方法是否需要画出流程图?
遗传算法:遗传算法类似于自然进化,通过作用于染色体上基因寻找好染色体来求解问题。及自然界相似,遗传算法对求解问题本身一无所知,它所需要仅是对算法所产生每个染色体进行评价,并基于适应值来选择染色体,使适应性好染色体有更多繁殖机会。在遗传算法中,通过随机方式产生若干个所求解问题数字编码,即染色体,形成初始群体;通过适应度函数给每个个体一个数值评价,淘汰低适应度个体,选择高适应度个体参加遗传操作,经过遗传操作后个体集合形成下一代新种群。对这个新种群进行下一轮进化。
算法流程图:
-
- 遗传算法-GAType类
class GAType(): # 种群
def __init__(self, obj_count):
self.gene = [0 for x in range(0, obj_count, 1)] # 序列编码 0 / 1
self.fitness = 0 # 适应度
self.cho_feq = 0 # choose 选择概率
self.cum_feq = 0 # cumulative 累积概率
class genetic():
def __init__(self, value, weight, max_weight):
self.value = value
self.weight = weight
self.max_weight = max_weight
self.obj_count = len(weight)
self._gatype = [GAType(self.obj_count) for x in range(0, population_size, 1)]
self.total_fitness = 0
Back_pack类:(部分功能代码)
def draw(self): # 画散点图
nums_pro = self.str_profit[0:len(self.str_profit)]
nums_wei = self.str_weight[0:len(self.str_weight)]
nums_pro = [int(i) for i in nums_pro]
nums_wei = [int(i) for i in nums_wei]
df = pd.DataFrame({'profit': nums_pro, 'weight': nums_wei})
df.plot(kind="scatter", x="weight", y="profit")
plt.show()
def DP(self): # 动态规划算法
dp = [[[0 for k in range(self.cubage + 5)] for i in range(4)] for j in range(self.size + 5)] # 三维dp数组
for k in range(1, self.size + 1):
for i in range(1, 4):
for v in range(self.cubage + 1):
for j in range(1, 4):
dp[k][i][v] = max(dp[k][i][v], dp[k - 1][j][v])
if v >= self.items[k - 1].pack[i - 1].weight:
dp[k][i][v] = max(dp[k][i][v],dp[k - 1][j][v - self.items[k - 1].pack[i - 1].weight]+self.items[k - 1].pack[i - 1].profit)
self.max_val = max(self.max_val, dp[k][i][v])
数据库-sql
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': 'root',
'db': 'dk',
'charset': 'utf8',
'cursorclass': pymysql.cursors.DictCursor,
}
- 程序运行:程序运行时每个功能界面截图。
主页面(GUI界面):
绘制散点图:
-
- 数据库存储的数据:
遗传算法:
导出结果文件:
- 描述结对的过程,提供两人在讨论、细化和编程时的结对照片(非摆拍)。
理解了领航员和驾驶员两种角色关系:两人都必须参与编码工作,在结对编程中两个人轮流做对方的角色。
采用了汉堡包法实施项目结对中两个人的沟通:
讨论的步骤总结:
- 提交源码到Github项目仓库中,编撰两人合作开发遵守共同认可的编码规范,提交项目代码规范文档到Github项目仓库根目录下
- 提供此次结对作业的PSP。
PSP2.1 | 任务内容 | 计划完成需要的时间(h) | 实际完成需要的时间(h) |
Planning | 计划 | 1 | 1 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 1 | 1 |
Development | 开发 | 16.5 | 21.5 |
Analysis | 需求分析(包括学习新技术) | 5 | 7 |
Design Spec | 生成设计文档 | 0.5 | 0.5 |
Design Review | 设计复审 | 0.5 | 0.5 |
Coding Standard | 代码规范 | 0.5 | 0.5 |
Design | 具体设计 | 1 | 1 |
Coding | 具体编码 | 5 | 5 |
Code Review | 代码复审 | 1 | 2 |
Test | 测试 | 3 | 5 |
Reporting | 报告 | 6.3 | 9.8 |
Test Report | 测试报告 | 5 | 8 |
Size Measurement | 计算工作量 | 0.3 | 0.3 |
Postmortem &Process Improvement Plan | 事后总结,并提出过程改进计划 | 1 | 1.5 |
- 小结感受:两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。
通过这次结对实验合作,让我觉得1+1真的大于2,我们两个人在彼此沟通的过程中,都能发现对方没有注意到的问题,这是一个人需要经过很长时间才能意识到的。三人行,必有我师。也就是说每个人都有自己的优劣点以及自己独创的想法。结对完成项目有助于产生不同种想法,从而有助于在决策的时候可以集思广益而产生一种比较好的方案。人无完人,一个人的力量有限,若是个人单打独斗难以把全部事情都做尽做全。但是两人分工合作的话,就会有监督有分工,还能提高自身的效率。
任务4:完成结对项目报告博文作业