201971020204-曹霖枫 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
班级博客 | 2019级计算机科学与技术 |
作业要求 | 实验三 软件工程结对项目 |
学习目标 | (1)体验软件项目开发中的两人合作,练习结对编程(Pair programming)(2)掌握Github协作开发软件的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | 让我掌握了如何结对编程,同时也更加熟悉了Github的一些操作 |
结对方学号-姓名 | 201971010246-王孜睿 |
结对方本次博客作业链接 | 结对博客链接 |
仓库地址 | Github |
任务一 阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念
1.代码风格规范
(1).代码风格的原则
代码风格的原则是:简明,易读,无二义性。
(2).几种代码风格规范
- 缩进
- 在学习之前习惯性理解为:对于缩进Tab键是最好的方式,也是最简单的,不用一个空格一个空格的敲,这样的习惯主要是因为大一学习C语言和WEB前端设计养成的。对于Tab键在不同的情况下会显示不同的长度的情况其实在去年学习Linux操作系统的时候用文件编写C语言程序时,就是使用Tab键来规范缩进的,那时很明显Tab键的长度和我之前在Windows系统下写代码时的长度不一样,显示长度为8个空格长度。
- 是用Tab键好,还是2、4、8个空格?
- 结论:4个空格,在VS2005和其他的一些编辑工具中都可以定义Tab键扩展成为几个空格键。不用 Tab键的理由是Tab键在不同的情况下会显示不同的长度。4个空格的距离从可读性来说正好。
- 命名
- 对于命名,最初接触的时候就知道要把程序中的变量、函数等要设计的有意义,然而大多数情况下自己的命名经常图简单用A、B、C...来随意命名,从而导致很多问题,如其他人看不懂你的意义,自己时间久了也不清楚等等一系列影响后续使用修改的问题,这些感受如《构建之法》10.1.6命名所说:
- 阿超:我在某个同学的程序中看到有些变量叫“lili”,“yunyun”,不知道这些变量在现实生活中有没有什么意义。
下面哄笑起来。 - 果冻:(红着脸问)那有些变量的确想不出名字,简单的变量像i、j、k都用完了,怎么办?
- 阿超:当我们的程序比“Hello World”复杂10倍以上的时候,像给变量命名这样简单的事看起来也不那么简单了。我们就来谈谈如何起名字这个问题。程序中的实体、变量是程序员昼思夜想的对象,要起一个好的名字才行。大家都知道用单个字母给有复杂语义的实体命名是不好的,目前最通用的,也是经过了实践检验的方法叫“匈牙利命名法”。例如:
- fFileExist,表明是一个bool值,表示文件是否存在;
- szPath,表明是一个以0结束的字符串,表示一个路
- 除此之外,有一些地方不适合用“匈牙利命名法”,如文中所说:在一些强类型的语言(如C#)中,不同类型的值是不能做运算的,对类型有严格的要求,例如C# 中,if()语句只能接受bool值的表达式,这样就大大地防止了以上问题的发生。在这样的语言中,前缀就不是很必要的,匈牙利命名法则不适用了。Microsoft .Net Framework就不主张用这样的法则。
- 注释
- 谁不会写注释?但是,需要注释什么?注释问题,个人理解是对所写程序的解释说明,增加了程序可读性。好的代码是自我解释的,然而仍然有大量的设计信息不能用代码表示。例如,只能在代码中正式指定类接口的一小部分,如其方法的签名。接口的非正式方面,例如每个方法的高级描述或其结果的含义,只能在注释中进行描述。还有许多其他的例子无法在代码中描述,比如特定设计决策的基本原理,或者调用特定方法的条件。注释背后的总体思想是捕获设计者头脑中但是不能在代码中表示的信息。这些信息的范围很广,从底层的细节(比如驱动一段特别复杂的代码的硬件怪癖),到高层的概念(比如类的基本原理)。当其他开发人员稍后进行修改时,注释将允许他们更快更准确地工作。
2.代码设计规范
- 概念
代码设计规范不光是程序书写的格式问题,而且牵涉到程序设计、模块之间的关系、设计模式等方方面面,这里有不少与具体程序设计语言息息相关的内容(如C、C++、Java、C#),但是也有通用的原则,这里主要讨论通用的原则。如果你只想为了“爽”而写程序,那么可以忽略下面的原则;如果你写的程序会被很多人使用,并且你自己会加班Debug 你的程序,那最好还是遵守下面的规定。 - 一些通用的原则
函数:现代程序设计语言中的绝大部分功能,都在程序的函数(Function, Method)中实现,关于函数最重要的原则是:只做一件事,但是要做好。
3.结对编程
-
(1)概念
- 在结对编程模式下,一对程序员肩并肩地、平等地、互补地进行开发工作。两个程序员并排坐在一台电脑前,面对同一个显示器,使用同一个键盘,同一个鼠标一起工作。他们一起分析,一起设计,一起写测试用例,一起编码,一起单元测试,一起集成测试,一起写文档等。
- 结对编程不是程序开发者独到的发明,在现实生活中,也存在着类似的搭档关系(Partnership):
- 越野赛车(驾驶,领航员)
- 驾驶飞机(驾驶,副驾驶)
- 战斗机的编组(长机,僚机)
提示:这些任务都有共同点:在高速度中完成任务,任务有较高的技术要求,任务失败的代价很高。
-
(2)为什么要结对编程
- 每人在各自独立设计、实现软件的过程中不免要犯这样那样的错误。在结对编程中,因为有随时的复审和交流,程序各方面的质量取决于一对程序员中各方面水平较高的那一位。这样,程序中的错误就会少得多,程序的初始质量会高很多,这样会省下很多以后修改、测试的时间。具体地说,结对编程有如下的好处:
- ① 在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力。
② 对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
③ 在心理上, 当有另一个人在你身边和你紧密配合, 做同样一件事情的时候, 你不好意思开小差, 也不好意思糊弄。
④ 在企业管理层次上,结对能更有效地交流,相互学习和传递经验,能更好地处理人员流动。因为一个人的知识已经被其他人共享。
总之,如果运用得当,结对编程能得到更高的投入产出比(Return of Investment)。
-
(3)如何结对编程
- 书中以驾驶员和领航员为例有如下几点:
- ① 驾驶员:写设计文档,进行编码和单元测试等XP开发流程。
② 领航员:审阅驾驶员的文档、驾驶员对编码等开发流程的执行;考虑单元测试的覆盖程度;是否需要和如何重构;帮助驾驶员解决具体的技术问题。
③ 驾驶员和领航员不断轮换角色,不宜连续工作超过一小时。领航员要控制时间。
④ 主动参与。任何一个任务都首先是两个人的责任,也是所有人的责任。没有“我的代码”、“你的代码”或“她的代码”,只有“我们的代码”。
⑤ 只有水平上的差距,没有级别上的差异。尽管可能大家的级别资历不同,但不管在分析、设计或编码上,双方都拥有平等的决策权利。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价,具体要求如下
1.博客评论
接对方博文链接 | 王孜睿 |
---|---|
评价内容 | 博文结构上简洁大方,排版整齐,内容上语言简洁明了,内容丰富 ,同时博文的结构和PSP相对应,可以看出博主严格遵守PSP的流程进行 |
2.克隆对方项目
接对方项目二仓库地址 | 王孜睿Github |
---|
3.阅读并测试运行代码
项目 | 内容 |
---|---|
设计规范 | |
设计是否遵从已知的设计模式或项目中常用的模式? | 是 |
有没有硬编码或字符串/数字等存在? | 无 |
代码有没有依赖于某一平台,是否会影响将来的移植? | 无影响 |
在本项目中是否存在类似的功能可以调用而不用全部重新实现? | 否 |
有没有无用的代码可以清除? | 无 |
代码规范 | |
修改的部分符合代码标准和风格么? | 符合 |
具体代码 | |
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 无 |
参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度是以0开始计数还是以1开始计数? | 无 |
switch语句的default分支是如何处理的?循环有没有可能出现死循环? | 无switch语句,无死循环 |
有没有使用断言( Assert)来保证我们认为不变的条件真的得到满足? | 无 |
数据结构中有没有用不到的元素? | 有 |
效能 | |
代码的效能(Performance)如何? | 效能一般 |
代码中,特别是循环中是否有明显可优化的部分? | 无 |
对于系统和网络的调用是否会超时?如何处理? | 否 |
可读性 | |
代码可读性如何?有没有足够的注释? | 可读性一般,代码部分注释不清晰 |
可测试性 | |
代码是否需要更新或创建新的单元测试? | 否 |
任务三:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台
- 1.需求分析
- (1)平台基础功能:实验二 任务3;
- (2){0-1}KP 实例数据集需存储在数据库;
- (3)平台可动态嵌入任何一个有效的{0-1}KP 实例求解算法,并保存算法实验日志数据;
- (4)人机交互界面要求为GUI界面(WEB页面、APP页面都可);
- (5)查阅资料,设计遗传算法求解{0-1}KP,并利用此算法测试要求(3);
- (6)附加功能:除(1)-(5)外的任意有效平台功能实现。
- 2.软件设计说明
- 本软件为桌面应用软件,在需求分析阶段,已经从软件开发的角度出发,把系统功能分为层次结构,使每一部分完成简单的功能且各个部分之间保持一定的联系。在设计阶段,把这个功能层次组合起来成为软件。
- 使用的技术:
- 图形界面:PyQt5
- 数据库:MySQL
- 3.核心代码展示
- 连接数据库
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
- GUI界面部分代码
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_widget(object):
def setupUi(self, widget):
widget.setObjectName("widget")
widget.resize(768, 580)
self.tabWidget = QtWidgets.QTabWidget(widget)
self.tabWidget.setGeometry(QtCore.QRect(0, 0, 771, 581))
self.tabWidget.setStyleSheet("font: 16pt \"宋体\";")
self.tabWidget.setTabPosition(QtWidgets.QTabWidget.North)
self.tabWidget.setTabShape(QtWidgets.QTabWidget.Triangular)
self.tabWidget.setElideMode(QtCore.Qt.ElideNone)
self.tabWidget.setObjectName("tabWidget")
self.tab_6 = QtWidgets.QWidget()
self.tab_6.setObjectName("tab_6")
self.label_4 = QtWidgets.QLabel(self.tab_6)
self.label_4.setGeometry(QtCore.QRect(90, 120, 581, 141))
self.label_4.setStyleSheet("color: rgb(129, 0, 0);\n"
"font: 48pt \"华文行楷\";\n"
"")
-
4.测试运行
- 数据库
- 程序主页面
- 数据选择
- 数据与结果查看
- 散点图
- 日志
- 数据库
-
5.结对过程
-
6.PSP
PSP | 任务内容 | 计划完成需要的时间(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 |
- Text | - 测试 | 100 | 100 |
Reporting | 报告 | 50 | 50 |
- Test Report | - 测试报告 | 10 | 10 |
- Size Measurement | - 计算工作量 | 10 | 10 |
- Postmortem & Process Improvement Plan | - 事后总结,并提出过程改进计划 | 30 | 30 |
- 7.实验总结
通过本次实验,我熟练掌握了软件开发过程中两人合作,结对编程,我对于github操作方法更加熟悉,而且通过阅读构建之法学习了代码规范和代码复审的知识,对于结对很有感想。通过此次实验,我认为1+1>2是具备条件的:产生何种效果主要取决与和结对方的沟通,以及在工作分配和设计方面的理解到位与否,总的来说,结对做项目利大于弊,既可以锻炼自己,又可以通过他人学到知识,何乐而不为? - 8.仓库
实验三Github