201971010208-古丽妮尕尔 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 2019级卓越工程师班 |
这个作业要求链接 | 实验三 软件工程结对项目 |
我的课程学习目标 |
|
这个作业在哪些方面帮助我实现学习目标 |
|
项目Github的仓库链接地址 | 仓库链接 |
结对方学号姓名 | 201971010145_姚恪 |
结对方本次博客作业链接 | 结对方作业链接 |
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;
-
代码风格规范
- 原则:简单、易读、无二义性。
- 缩进:可以使用Tab键以及2、4、8等空格。个人认为依据不同是编程语言,可以使用不同的缩进方式。
- 行宽:对行宽进行同一设置。
- 括号:用括号清楚的表明逻辑优先级。
- 分行:不要把多条语句放在一行上。
- 命名:命名能够表明变量的类型及相应的语义,简洁易懂。
- 下换线:合理使用来分隔变量名字中的作用域标注和变量的语义。
- 大小写:多个单次组成的变量名,用大小写区分,例如著名的驼峰式命名法。
- 注释:能够很好的解释程序是做什么的,以及为什么这样做
-
代码设计规范
- 概念:代码设计规范不光是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方方面面,又有不少内容与具体程序设计语言息息相关(如C,C++,JAVA,C#),但是也有通用的原则。
- 函数:原则:只做一件事,并且要做好。
- goto:函数最好有单一出口,为了达到这一目的,可以使用goto。
- 错误处理(参数处理):在Debug版本中,所有参数都要验证其正确性。
- 错误处理(断言):检验正确性时,可以使用断言。
- 类:
1.使用类来封装面向对象的概念和多态。
2.避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要要用类来实现。
3.对于有显示的构造和析构的类,不要建立全局的实体,因为不知道它们在何时创建和消除。
4.仅在有必要时,才是用“类”。 - class vs. struct:如果只是数据的封装,用struct即可。
- 公共/保护/私有成员:按照这样的次序来说明类中的成员。
- 数据成员:
1.数据类型的成员用m_name说明。
2.不要使用公共的数据成员,要用inline访问函数,这样才可兼顾封装和效率。 - 虚函数:
1.实现多态。
2.仅在很有必要时,使用虚函数。
3.若一类型实现多态,在基类中的析构函数应该是虚函数。 - 构造函数:
1.不做复杂操作。
2.不应返回错误。 - new 和 delete:
1.尽量实现自己的new/delete。
2.检查new的返回值。
3.释放指针时不用检查NULL。 - 运算符:
1.无需自定义操作符。
2.不要做标准语义之外的动作。
3.运算符的实现必须非常有效率。
4.当打不定主意时,用成员函数。 - 异常:
1.不要将异常作为处理程序主要流程。
2.了解异常及处理异常的花销。
3.使用时,注意在什么地方清理数据。
4.异常不能跨过DLL或进程的边界来传递信息。 - 类型继承:
1.仅在必要时使用。
2.用const标注只读的参数。
3.用const标注不改变数据的函数。
-
代码复审
- 定义:看代码是否在代码规范的框架正确地解决了问题。
- 形式:自我复审、同伴复审、团队复审。
-
结对编程概念
- 结对编程能提供更好的设计质量和代码质量,两人合作解决问题的能力更强。
- 结对工作,信心大增,高质量的产出带来高满足感。
- 结对能更有效的交流,相互学习传递经验,分享知识,应对人员流动。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价。
结对对象 | 项目 | 仓库 |
---|---|---|
姚恪—201971010145 | 实验二 | 姚恪仓库 |
- 成果评价
评价项目 | 评价内容 |
---|---|
博文结构 | 页面简介整齐,要素齐全且一目了然。 |
博文内容 | 最大程度达到了作业要求,极少部分地方出现了文字不对齐、序号重复等形式错误,内容饱满且完整 |
博文结构与PSP中“任务内容”列的关系 | 博文结构与“内容任务”列几乎一一对应,思路清晰 |
PSP数据的差异化分析与原因探究 | 具体完成时间与计划完成时间相差无几,因为本身具有扎实的代码功底以及规划能力,即使个别项目所用时间超出计划部分也没有因此拖整体进度。 |
-
克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。
- 克隆对方项目
- 测试代码
- 克隆对方项目
-
代码审查
概要部分 | 执行情况 |
---|---|
代码符合需求和规格说明么? | 符合 |
代码设计是否考虑周全? | 是 |
代码可读性如何? | 符合代码规范,注释简单易懂 |
代码容易维护么? | 容易 |
代码的每一行都执行并检查过了吗? | 检查过了 |
设计规范部分 | |
设计是否遵从已知的设计模式或项目中常用的模式? | 遵从 |
有没有硬编码或字符串/数字等存在 | 不存在 |
代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)? | 不影响 |
在本项目中是否存在类似的功能可以调用而不用全部重新实现? | |
有没有无用的代码可以清除? | 无 |
代码规范部分 | |
修改的部分符合代码标准和风格吗? | 符合 |
具体代码部分 | |
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 没有对错误进行预处理 |
参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度是以0开始计数还是以1开始计数? | 无 |
边界条件是如何处理的? switch语句的default分支是如何处理的?循环有没有可能出现死循环? | 没有使用switch语句所以循环不会出现死循环。 |
有没有使用断言( Assert)来保证我们认为不变的条件真的得到满足? | 没有使用断言 |
数据结构中有没有用不到的元素? | 看不出来 |
效能 | |
代码的效能(Performance)如何?最坏的情况是怎样的? | 运行效率高,没有遇到最坏的情况 |
代码中,特别是循环中是否有明显可优化的部分? | 无 |
对于系统和网络的调用是否会超时?如何处理? | 没有进行网络调用 |
可读性 | |
代码可读性如何?有没有足够的注释? | 注释简洁明了,符合规范 |
可测试性 | |
代码是否需要更新或创建新的单元测试? | 否 |
- 结对方项目仓库中的Fork、Clone、Push、Pull request、Merge pull request日志数据
任务3:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台
- 需求分析
- 平台基础功能:实验二 任务3;
- {0-1}KP 实例数据集需存储在数据库;
- 平台可动态嵌入任何一个有效的{0-1}KP 实例求解算法,并保存算法实验日志数据;
- 人机交互界面要求为GUI界面(WEB页面、APP页面都可);
- 查阅资料,设计遗传算法求解{0-1}KP,并利用此算法测试要求(3);
- 附加功能:除(1)-(5)外的任意有效平台功能实现。
- 软件设计说明
- 将实验二的代码进行了扩充,套装了一个django框架
- 但是仅仅能够实现数据的前端展示,是一个假的前端,没有完全实现前端功能
- 使用python中django库中自带的sqlite数据库进行数据的传输
- 功能流程图
graph LR
start[算法平台] --> input[选择一个指定的背包数据]
input --> conditionA[显示背包数据]
conditionA --> conditionB[遗传算法]
conditionA --> conditionC[动态规划]
conditionA --> conditionD[贪心算法]
conditionA --> conditionE[回溯法]
conditionB --> printa[散点图]
conditionC --> printa[散点图]
conditionD --> printa[散点图]
conditionE --> printa[散点图]
printa --> stop[结束]
- 核心代码展示
- 遗传算法
遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)可抽象表示为染色体,使种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中评价整个种群的适应度,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择和突变产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。
- 遗传算法
点击查看代码
##初始化,N为种群规模,n为染色体长度
def init(self,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(self,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(self,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(self,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(self,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(self,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(self,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
- 使用diango框架和构造数据库
点击查看代码
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ex3.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
-
程序运行结果
-
操作后记录
-
结对沟通过程
-
本次作业PSP
PSP | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 20 | 20 |
Development | 开发 | 1200 | 1200+ |
Analysis | 需求分析 (包括学习新技术) | 120 | 150 |
Design Spec | 生成设计文档 | 20 | 20 |
Design Review | 设计复审 (和同事审核设计文档) | 20 | 15 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 15 |
Design | 具体设计 | 60 | 60 |
Coding | 具体编码 | 600 | 650 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 200 | 260 |
Reporting | 报告 | 100 | 100 |
Test Report | 测试报告 | 30 | 40 |
Size Measurement | 计算工作量 | 40 | 50 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 20 | 30 |
- 小结感受
- 通过本次结对项目,感受到两个人互相督促去完成比一个人效率高,内容完成度更高。
- 可以看到自己的不足之处,为了不拖后腿会去学习,而不是逃避。
- 会拥有更多的视角解决问题。