201871010123-吴丽丽 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

201871010123-吴丽丽 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

项目 内容
课程班级博客链接 班级链接
这个作业要求链接 作业要求链接
我的课程学习目标 1.掌握代码风格规范、设计规范,写出规范的代码及语句
2.了解什么是汉堡包法
3.对结对编程有进一步的了解
这个作业在哪些方面帮助我实现学习目标 1.通过阅读“构建之法”,从而理解代码风格规范、设计规范等相关概念及对应的原则
2.通过浏览关于汉堡法的阐述参见,在进行项目交流时,利用该法来促进两人之间的沟通
3.通过互换角色来进一步的了解结对编程
结对方学号-姓名 201871010112-梁丽珍
结对方本次博客作业链接 梁丽珍
本项目Github的仓库链接地址 https://github.com/l728672/bag

一、实验目的与要求

(1)体验软件项目开发中的两人合作,练习结对编程(Pair programming)。
(2)掌握Github协作开发程序的操作方法。

二、实验内容和步骤

任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;

已经阅读完第3-4章内容,相关概念如下:
1、代码风格规范

  • 代码风格的原则是:简明,易读,无二义性。

  • 缩进:4个空格,不用Tab键是因为在不同的情况下显示的长度可能不一样。

  • 行宽:限定为100字符。

  • 括号:在复杂的条件表达式中,可以清晰地表示逻辑优先级。

  • 断行与空白的{}行:断行在程序调试时可以清晰的表达变量的变化情况,{}来判断程序的结构。

  • 分行:不要把多个变量定义在一行上。

  • 命名:
      - 在变量名中不要提到类型或其他语法方面的描述。
      - 避免过多的描述。
      - 如果信息可以从上下文中得到,那么此类信息就不必写在变量名中。
      - 避免可要可不要的修饰词。

  • 下划线:用来分割变量名字中的作用域标注和变量的语义。

  • 大小写:
       - 所有类型/类/函数名都用Pascal形式(所有单词第一个字母都大写)。
       - 所有变量都用Camel形式(第一个单词全部小写,随后单词用Pascal形式)。
       - 类/类型/变量:名词或组合名词。
       - 函数则用动词或动宾组合词来表示。

  • 注释:注释是为了解释程序做什么(What),为什么这样做(Why)以及要特别注意的地方。

2、代码设计规范
  (1)概念:代码设计规范不光是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方方面面,又有不少内容与具体程序设计语言息息相关(如C,C++,JAVA,C#),但是也有通用的原则。
  (2)函数:原则:只做一件事,并且要做好。
  (3)goto:函数最好有单一出口,为了达到这一目的,可以使用goto。
  (4)错误处理:
    ①参数处理:在Debug版本中,所有的参数都要验证其正确性,在正式版本中,对从外部(用户或别的模块)传递过来的参数,要验证其正确性。
    ②断言:验证正确性就要用断言。
  (5)如何处理C++中的类
    ①类:
      a.使用类来封装面向对象的概念和多态。
      b.避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要要用类来实现。
      c.对于有显示的构造和析构的类,不要建立全局的实体,因为不知道它们在何时创建和消除。
      d.仅在有必要时,才是用“类”。
    ②class vs.struct:如果只是数据的封装,用struct即可。
    ③公共/保护/私有成员:按照这样的次序来说明类中的成员。
    ④数据成员:
      a.数据类型的成员用m_name说明。
      b.不要使用公共的数据成员,要用inline访问函数,这样可兼顾封装和效率。
    ⑤虚函数
      a.使用虚函数来实现多态。
      b.仅在很有必要时,才使用虚函数。
      c.如果一个类型要实现多态,在基类中的析构函数应该是虚函数。
    ⑥构造函数
      a.不要在构造函数中做复杂的操作,简单初始化所有成员即可。
      b.构造函数不应该返回错误。
    ⑦析构函数
      a.把所有的清理工作都放在析构函数中。如果有些析构函数在之前就释放了,要重置这些成员为0或NULL。
      b.析构函数也不应该出错。
    ⑧new和delete
      a.如果可能,实现自己的new/delete,这样可以方便地加上自己的跟踪和管理机制。自己的new/delete可以包装系统提供的new/delete。
      b.检查new的返回值。new不一定都成功。
      c.释放指针时不用检查NULL。
    ⑨运算符
      a.在理想情况下,我们定义的类不需要自定义操作符。确有必要时,才会自定义操作符。
      b.运算符不要做标准语义之外的任何动作。
      c.运算符的实现必须非常有效率,如果有复杂的操作,应定义一个单独的函数。
      d.当拿不定注意时,用成员函数,不要用运算符。
    ⑩异常
      a.不要用异常作为逻辑控制来处理程序的主要流程。
      b.当使用异常时,要注意在什么地方清理数据。
      c.异常不能跨过DLL或进程的边界来传递消息,所以异常不是万能的。
    ⑪类型继承
      a.仅在有必要时,才使用类型继承。
      b.用const标注只读的参数。
      c.用const标注不改变数据的函数。
3、代码复审:看代码是否在代码规范的框架内正确的解决了问题。代码复审的形式包括:自我复审、同伴复审、团队复审。
4、结对编程:结对编程中有两个角色:领航员和驾驶员。在个人编写的过程中,很多人喜欢根据个人喜好来规定代码规范,而且存在的bug自己难以发现,因此,在结对编程时,我们可以互换角色,在开始写代码之前,规定两个人都认可的一套代码规范,并且不间断地进行复审,以减少软件中存在的问题,修复bug,提高软件质量。

任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价,具体要求如下:

(1)对项目博文作业进行阅读并进行评论,评论要点包括:博文结构、博文内容、博文结构与PSP中“任务内容”列的关系、PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究,将以上评论内容发布到博客评论区。
评论内容如下图所示:

评论链接:https://www.cnblogs.com/LZ-728672/p/14575859.html
(2)克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。
情况说明:因对方能力有限,未能上传代码到github的仓库,所以无法对对方项目源代码进行克隆,阅读并测试运行代码,无法进行该任务要求。
(3)依据复审结果尝试利用github的Fork、Clone、Push、Pull request、Merge pull request等操作对同伴个人项目仓库的源码进行合作修改。
情况说明:因对方未上传代码到仓库,所以无法进行相应操作。

任务3:采用两人结对编程方式,设计开发一款D{0-1}KP 实例数据集算法实验平台,使之具有以下功能:

(1)平台基础功能:实验二 任务3;
(2)D{0-1}KP 实例数据集需存储在数据库;
(3)平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据;
(4)人机交互界面要求为GUI界面(WEB页面、APP页面都可);
(5)查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求(3);
(6)附加功能:除(1)-(5)外的任意有效平台功能实现。

1.需求分析陈述。(5分)

通过查阅相关资料我了解到了遗传算法:

(1)利用遗传算法求解D{0-1}KP问题,可假设一个项集的物品扩展为A、B、C三个物品,将三个物品间两两组合的折扣关系分别假设为物品D、E、F,选择三个物品时的折扣关系假设为物品G。在该项集中选择情况包含:全部不选、选择物品A、选择物品B、选择物品C、选择物品D(物品A和B的组合)、选择物品E(物品A和C的组合)、)、选择物品F(物品B和C的组合)以及选择物品G(物品A、B和C的组合)共八种情况。在同一时刻,每个项集的选择只能是八种情况之一。
(2)遗传算法:基于随机的进化算法;希望通过多次将高质量的个体繁衍后,生出所需要的个体。随机:新的解会在原有的解上发生随机变化。
(3) 基本思想:遗传算法的搜索从一个被称作种群的候选解集开始,新的种群由旧的种群中产生以期得到更好的种群。从旧种群中按照解的适应度来选择解以产生新的解;适应度越大,解被选择生成后代的机率也越大。这个从已有种群中选择双亲并产生后代的迭代过程持续到遗传算法的停止条件满足为止。
(4) 遗传算法的基本元素:由染色体组成的种群,根据适应度进行选择以及交叉产生后代。
(5) 要采用遗传算法,则首先确定以下几个要素:染色体的编码方法、适值函数、染色体交叉和变异采用的方案、选择策略
(6)关键步骤如下:

a.基因编码:在这个过程中,尝试对一些个体的基因做一个描述,构造这些基因的结构,有点像确定函数自变量的过程。

b.设计初始群体:在这里需要造一个种群出来,这些种群有很多生物个体但基因不同。

c.适应度计算:这里对那些不符合要求的后代进行剔除,不让他们产生后代。否则他们产生的后代只会让计算量更大而对逼近目标没有增益。

d.产生下一代:有3种方法,即:直接选择,基因重组,基因突变
而后回到步骤c进行循环,适应度计算,产生下一代,这样一代一代找下去,直到找到最优解为止。

2.软件设计说明。(5分)
  • 在本次设计中我们采用一个函数来进行读取文件,用draw_scatter()函数来绘制重量——价值的散点图,datasorted()函数来进行价值与重量的比值进行非递增排序,再通过pack()函数来利用动态规划算法来进行分组背包问题的求解,求出在不超过容量的限制下能装入的最大价值和该算法的运行时间,再将其保持到txt文件中。之后我们设计了遗传算法类,里面设置了初始化种群、评估个体的适配值、交叉、突变、选择个体、产生新后代,产生下一代这些方法。
3.软件实现及核心功能代码展示:软件包括哪些类,这些类分别负责什么功能,他们之间的关系怎样?类内有哪些重要的方法,关键的方法是否需要画出流程图?(5分)
  • 软件包括了一个主函数和一个遗传类以及实现一些基本功能的函数。
  • 遗传算法流程图:
  • 遗传算法类中包含的各种方法:
4.程序运行:程序运行时每个功能界面截图。扩展功能实现可得附加分5分。(2分)

(1)读取文件,读取出物品数量、背包容量、存放重量和价值相对应的列表,读取数据成功,结果如图所示:

(2)绘制重量——价值的散点图,运行结果如图所示:

(3)对价值与重量的比值进行非递增排序,排序后我将以列表的形式来存储其比值,将对应的列表输出,运行结果如图所示:

(4)用动态规划算法来解决分组背包问题,计算出在不超限制容量的情况下,背包能装的最大价值,以及运用该算法运行的时间,实验运行结果如图所示:

(5)将运行结果写进.txt文件,其运行结果如图所示:

5.描述结对的过程,提供两人在讨论、细化和编程时的结对照片(非摆拍)。(3分)

在本次结对编程过程中,我们各自学习了遗传算法,之后两人互相交流了一下自己对遗传算法的一些看法,进一步了解了遗传算法的基本思想,因我们两的能力有限,编码能力不足,在上一次的作业中我们都没能够把其对应的功能实现,因而在本次结对编程中,我们互相协作,将各自的代码给了对方看,从中寻找解决问题的方法,在编程时我们老是编译不过去,总是出现各自各样的问题,各自针对其问题提出意见,并且结合网上的一些资料,进行不断的测试、运行。以下是我们在交流过程中的一些截图:

两人互相交流的照片:

6.提供此次结对作业的PSP。(4分)

Personal Software Process Table (PSP)

PSP2.1 任务内容 计划共完成需要的时间(min) 实际共完成需要的时间(min)
Planning 计划 10 10
· Estimate 计划 10 10
Development 开发 240 295
· Analysis · 需求分析 (包括学习新技术) 20 15
Design Spec · 生成设计文档 10 10
· Design Review · 设计复审 (和同事审核设计文档) 30 40
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 30
· Design · 具体设计 60 70
· Coding · 具体编码 70 100
· Code Review · 代码复审 20 20
· Test · 测试(自我测试,修改代码,提交修改) 10 10
Reporting 报告 20 20
· Test Report · 测试报告 10 10
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 20
合计 320 355
7.小结感受:两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。(4分)

我觉得两个人合作可以带来1+1>2的效果,通过此次结对编程,虽然我们项目没能够顺利的完成,但是在这次合作过程中我们学到了挺多的,在不断交流项目,两者的思想互相碰撞,产生一些更有效的想法,结合两者的优点,进行扬长避短,提高完成项目效率。在这个过程中,虽然有意见不合,但通过向对方阐述,让对方理解自己的意思,互相影响和反馈,来达到更好地合作。在本次项目我们花费了挺多时间去完成,虽然没有将项目完成出来,但是在此过程中我也收获了许多,也从中意识到了自己存在着许多不足的地方,以后会多加注意的。

posted on 2021-04-13 20:37  201871010123-吴丽丽  阅读(140)  评论(0编辑  收藏  举报