201871030117-李亚楠 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 课程班级 |
这个作业要求链接 | 作业要求 |
我的课程学习目标 | 1.体验软件项目开发中的两个人合作、练习结对编程; 2.掌握Github协作开发程序的操作方法; 3.熟悉编程语言的综合使用,提高提取文件信息、处理数据、对数据库的操作能力; |
这个作业在哪些方面帮助我实现学习目标 | 1.这次作业涉及图形用户界面的设计以及数据的处理,所以熟悉C语言、Java语言、Python语言的语法,并比较其特点,选择性使用; 2.与伙伴协同合作,体会结对编程的益处; 3.在上次实验的基础上,进一步熟悉Github的使用方法; |
结对方学号-姓名 | 201871030119-马桂婷 |
结对方本次博客作业链接 | 结对方博客链接 |
本项目GitHub的仓库链接地址 | 仓库地址 |
任务1:阅读《现代软件工程——构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念;
-
代码风格规范:代码风格规范是指文字上的规定,主要目的是使程序员和阅读者能够看得清楚,理得明白,具有更高的可读性,因此简明、易读、无二义性是其主要原则。主要包括以下几个方面:
- 缩进:4个空格可读性最好,因为Tab键在不同的情况下会显示不同的长度。
- 行宽:行宽必须受到限制,以前为80字符,现在为100字符。
- 括号:复杂表达式中,括号可清楚表示优先级。
- 断行与空白的{}行:为了方便程序调试,在程序中要有断行;{}是为了在多层控制嵌套时,能够看清结构和对应关系,最好的情况就是"{"和"}"都独占一行。
- 分行:不要把多条语句放在一行上;不要把多个变量定义在一行上。
- 命名:事实证明,用单个字母给复杂语义的实体命名并不可取。
- 下划线:分隔变量名字中得作用域标注和变量的语义。
- 大小写:为了满足可读性的要求,由多个单词组成的变量名应该用大小写来区分。Pascal——所有单词的第一个字母都大写。Camel——第一个单词全部小写,随后但系随Pascal形式,这种方式叫lowerCamel。一般地,所有的类型/类/函数名都用Pascal形式,所有变量都用Camel形式。
- 注释:注释应该起到一个帮助理解代码的作用。复杂的注释应该放在函数头,一般都用来解释参数;注释会随着程序的修改不断更新;注释应该只用ASCII字符,不用中文或其他特殊字符,否则会影响程序的可移植性。现代的编程环境支持各种美观字体,所以可设置不同风格的字体表示不同部分。项目中不必进行像教科书一般的注释。
-
代码设计规范:代码设计规范不仅是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方面。其中包含以下几个方面的规范:
-
函数:一个函数只做一件事。
-
goto:使程序有个唯一的出口。
-
错误处理:错误处理一般会花费大量的时间
- 参数处理在Debug版本中,所有参数都要验证正确性;在正式版本中,对外部传递过来的参数,要验证正确性;
- 断言可以验证程序正确性,当你觉得事件一定发生时,就可用断言;
-
类(C++):主要有以下几个方面的说明:
-
类
1)使用类来封装面向对象的概念和多态;
2)避免传递类型实体的值,应该用指针传递,对于简单数据类型,可以不用类实现;
3)对于有显式的构造和析构函数的类,不要建立全局实体;
4)必要时使用类。
-
class vs.struct只是数据的封装,可用struct
-
按公共(public)、保护(protected)、私有(private)的顺序来说明成员
-
数据成员
1)数据类型的成员用m_name说明;
2)不要访问公共数据成员,要用inline访问函数。
-
虚函数
1)使用虚函数实现多态;
2)有必要时使用;
3)如果一个类型要实现多态,在基类中的析构函数应该是虚函数。
-
构造函数(Constructors)
1)构造函数只需初始化说有数据成员即可;
2)构造函数不应该返回错误;
-
析构函数(Destructor)
1)释放空间;
2)析构函数不应出错
-
new和delete
1)为了方便加上自己的跟踪和管理机制,可实现自己的new/delete;
2)检查new的返回值,验证其是否成功;
3)释放指针时不用检查NULL。
-
运算符
1)一般无需自定义操作符;
2)运算符不要做标准语义之外的动作;
3)运算符实现应该保证效率,若操作复杂,可定义一个函数实现;
4)不知所措时用成员函数而不是运算符
-
异常(Exceptions)
1)不要用异常作为逻辑控制来处理程序的主要流程,太浪费时间;
2)了解异常和处理异常花费很大开销;
3)使用异常时,注意清理数据;
4)异常不可跨过DLL或进程的边界来传递信息。
-
类型继承
1)必要时使用;
2)用const标注只读参数;
3)用const标注不改变数据的参数。
-
-
-
代码复审:代码复审是指项目开发人员编写程序后,由代码复审人员进行核查,能及时检测程序存在的问题,复审者逐一提供反馈意见,在开发人员修改之后还要存在这样一些疑问:修改之后功能是否有影响,出现这个问题的原因是什么,后续工作中如何避免。复审的方式有很多,包括面对面复审、独立复审或其他方式。
名称 形式 目的 自我复审 自己 vs. 自己 用同伴复审的标准来要求自己。若能持之以恒,则会带来益处 同伴复审 复审者 vs. 开发者 简单易行 团队复审 团队 vs. 开发者 有严格的规定和流程,适用于关键代码以及复审后不再更新代码;覆盖率高——多人审核,但效率可能不高 -
结对编程:结对编程是指一对程序员肩并肩、平等地、互补地进行开发工作。一起分析、一起设计、一起测试、一起编码、一起做集成测试、一起编写文档。这个过程中队友的身份可以互换。这种模式有以下优点:
- 提供更好的设计质量和代码质量,合作解决问题能力更强;
- 结对双方更有信心,同时程序也会有高质量;
- 有利于相互交流和学习,传递经验、分享知识,能更好应对人员流动;
- 获得更高投入产出比
任务2:两两自由结对,对结双方《实验二 软件工程个人项目》的项目成果进行评价,具体要求如下:
-
对项目博文进行阅读和点评:点评博文
-
克隆结对方项目源码,阅读并测试运行,复审同伴项目代码并记录:
部分 | 要求 | 记录 |
---|---|---|
概要部分 | 1.代码是否符合需求和规格说明? 2.代码设计是否考虑周全? 3.代码的可读性 4.代码的维护性 5.每行代码是否都被执行和检查? |
1.代码符合需求和规格说明; 2.代码设计考虑到位,但不能说考虑周全; 3.代码具有较强的可读性,程序表达清晰,结构完整,有必要的注释; 4.代码的维护性较强,模块之间的联系很密切; 5.程序每行都被执行和检查; |
设计规范部分 | 1.设计是否遵从一定的项目模式? 2.有没有硬编码或字符串/数字? 3.代码是否可移植? 4.代码是否用已有的Library/SDK/Framework中得功能实现?是否有类似功能可以调用? 5.有没有无用代码? |
1.设计中得项目模式体现得很微观; 2.有字符串和数字; 3.代码可移植; 4.没有类似功能可以被调用; 5.程序中有一些对解决问题无用的代码; |
代码规范部分 | 1.修改的部分符合代码规范和风格吗? |
1.修改的部分解决了问题,但是不是那么符合代码规范和风格; |
具体代码部分 | 1.是否对错误进行了处理?调用外部函数,是否检查返回值和处理异常? 2.参数有无错误?字符串的长度是字节长度还是字符长度,从0/1开始计数? 3.边界条件如何处理?switch和default如何处理?是否有死循环? 4.有无断言保证我们认为不变的条件得到满足? 5.资源利用在哪里申请?哪里释放?有无优化空间? 6.数据结构中有无没有的元素? |
1.对错误进行了处理,但是没有处理异常和检查返回值; 2.参数没有错误;字符串长度是按字符长度计数,从1开始; 3.边界处理得当;没有switch和default,无死循环; 4.没有断言; 5.没有资源的释放,无优化空间; 6.数据结构中没有无用的元素; |
效能 | 1.代码的效能如何?最坏情况怎样? 2.代码中,特别是循环中是否有可优化的部分? 3.对系统和网络的调用是否会超时?如何处理? |
1.代码的效能可能在数据量比较小的时候效能较好,数据量较大时,效能会比较低; 2.代码中无可优化的循环; 3.对系统和网络调用不会超时; |
可读性 | 1.可读性如何?有无注释? | 1.代码的可读性较好,思路很清晰,有明确的注释,帮助读者阅读; |
可测试性 | 1.代码是否需要更新或创建新的单元测试? | 1.代码需更新或创建新的单元测试 |
任务3:采用两人结对编程方式设计开发一款D{0-1}KP实例数据集算法实验平台,使之具有以下功能:
-
需求分析称述:
- D{0-1}KP实例数据集需要存储在数据库;
- 平台可动态嵌入任何一个有效的D{0-1}KP实例求解算法,并保存算法实验日志数据;
- 人机交互界面要求为GUI界面(WEB界面、APP界面);
- 查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求;
- 附加功能,除了(1)-(5)外的任意有效平台功能实现;
-
软件设计说明:
- 程序首先应该实现文本数据导入到数据库中,但是存在一个问题,每一组数据量度不同,有30个数据的数据集,也有300个数据的数据集,在建立数据库时就会存在问题,因为之前做的数据库操作都是所有数据集中得数据量大小是相同的,所以,想明白这个问题花费了一些时间;
- 程序应该应该实现遗传算法;遗传算法是平时接触的比较少的一类算法,所以完成本节实验,必须先学习遗传算法,以及尝试用遗传算法求解D{0-1}背包问题,并进行单元测试,测试没问题之后整合到整个程序中;
- 完成实验需要设计一个图形用户界面,还需要处理大量数据集,所以这就需要选择一个合适的编程语言,导入合适的库函数;
- 实验需要动态插入数据集。在图形用户界面中设计文本框对其输入到对应的数据库中。
-
软件实现及核心功能代码展示:软件包含哪些类,这些类分别负责什么功能,他们之间的关系怎样?类内有哪些重要的方法,关键的方法是否需要画出流程图?
-
链接数据库的类DBO
public class DBO { //SQLServer private String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";//加载驱动程序 private String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=1";//设置数据库连接串 master为数据库名 private String user = "sa";//数据库登录用户名 private String password = "123456";//数据库登录密码 public Connection getConnection() { try { Class.forName(driverName); return DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); return null; } }
-
图形用户界面Demo17
public Demo17() { jmb = new JMenuBar(); menu1 = new JMenu("文件(F)"); menu1.setMnemonic('F');// 设置助记符 menu2 = new JMenu("编辑(E)"); menu2.setMnemonic('E'); menu3 = new JMenu("格式(O)"); menu3.setMnemonic('O'); menu4 = new JMenu("查看(V)"); menu4.setMnemonic('V'); menu5 = new JMenu("帮助(H)"); menu5.setMnemonic('H'); xinjian = new JMenu("算法选择"); file = new JMenuItem("遗传算法"); project = new JMenuItem("贪心法"); project1 = new JMenuItem("动态规划算法"); item2 = new JMenuItem("打开", new ImageIcon("images\1.png")); item3 = new JMenuItem("保存(S)"); item3.setMnemonic('S'); item3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK)); item4 = new JMenu("散点图"); a1 = new JMenuItem("idkp1-10"); a2 = new JMenuItem("sdkp1-10"); a3 = new JMenuItem("udkp1-10"); a4 = new JMenuItem("wdkp1-10"); item5 = new JMenuItem("插入数据"); item6 = new JMenuItem("查询数据"); itm7 = new JMenuItem("退出"); }
-
图形用户界面Demo16
public Demo16() { jp1 = new JPanel(); jp2 = new JPanel(); jp3 = new JPanel(); jp4 = new JPanel(); jp5 = new JPanel(); jlb1 = new JLabel("名称(如IDKP0)"); jlb2 = new JLabel("维数(diemnsion)"); jlb3 = new JLabel("容量(cubage)"); jlb4 = new JLabel("数据个数"); //jlb2 = new JLabel("维数(diemnsion)"); jb1 = new JButton("确定"); jb2 = new JButton("取消"); jpf1 = new JPasswordField(10); this.setLayout(new GridLayout(3, 1)); this.setSize(250, 150); this.setTitle("折扣{0-1}背包问题"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); }
-
遗传算法
public class Reader { public static List<Object> read(File file) { BufferedReader br = null; List<Object> data = new ArrayList<Object>(); try { br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); br.readLine(); String inputLine = br.readLine(); StringBuilder sb = new StringBuilder(""); while(inputLine != null) { sb.append(inputLine + "\n"); inputLine = br.readLine(); } String[] arr = sb.toString().split("[ \n]"); float[] weight = new float[arr.length/2]; float[] profit = new float[arr.length/2]; for(int i = 0; i < arr.length/2; i++) { weight[i] = Float.parseFloat(arr[2*i]); profit[i] = Float.parseFloat(arr[2*i + 1]); } data.add(weight); data.add(profit); return data; } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } return null; }
-
-
程序运行:程序运行时每个功能界面截图
-
图形用户界面
-
图形用户界面
-
散点图
-
数据库
-
-
描述结对的过程,提供两人在讨论、细化和编程时的结对照片
-
提供此次结对作业的PSP:
PSP 任务内容 计划共完成需要的时间(min) 实际完成需要的时间(min) Planning 计划 30 25 · Estimate · 估计这个任务需要多少时间,并规划大致工作步骤 30 25 Development 开发 1120 983 ·· Analysis 需求分析 (包括学习新技术) 310 260 · Design Spec · 生成设计文档 90 60 · Design Review · 设计复审 (和同事审核设计文档) 30 25 · Coding Standard 代码规范 (为目前的开发制定合适的规范) 10 8 · Design 具体设计 60 40 · Coding 具体编码 500 520 · Code Review · 代码复审 60 40 · Test · 测试(自我测试,修改代码,提交修改) 60 30 Reporting 报告 100 62 ·· Test Report · 测试报告 60 30 · Size Measurement 计算工作量 10 7 · Postmortem & Process Improvement Plan · 事后总结 ,并提出过程改进计划 30 25 -
小结感受:两人合作怎的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会?
(1) 以前的软件项目都是独自完成的,可能由于之前写的程序量不大,所以感觉难度也不是很大,也没有进行单元测试和代码复查,但是没有进行单元测试和代码复核,程序中存在一些难以发现的问题就得不到解决,长此以往,在软件项目编程这块形成了不好的编码习惯,不注意代码设计规范、异常没有处理、代码可能会陷入死循环等等。
(2)但是随着知识体系的逐步完善,我们开始编写大型的软件项目,所以编程模式和编码规范显得格外重要,但是会发现对于大型项目来说,一个人的力量往往是不够的。两个人之间合作才能更高效的完成项目,可以及时发现错误、可以交流学习、学习结伴方编码的优点,发现自己的错误和不足,及时反思并进行改正。
(3) 这次我的结伴方是长期和我合作学习的伙伴,所以我们就少了磨合期,节省了时间。在这个过程中,我们一起讨论、设计、修改、测试,过程很愉快,效率也比独自编程的时候高很多,因为在这个过程中是两个人在思考,总会比一个人的思维更广,而且两个人之间的角色可以互换,都很积极参与其中。两人合作能够带来1+1>2的效果,这个效果可能长篇大论不如自己亲身体会,所以在平时学习和研究的过程中,可以尝试一下结对合作。
任务4:完成结对项目报告博文
- 这次结对编程已经到此告一段落了,我深刻体会到了1+1>2的效果和效率,当然我也意识到自己编程中存在的许多不足,对语言的语法不熟悉,大量时间耗费在底层设计,这是编程中最忌讳的问题,就像《现代软件工程-构建之法》中所说,不知道数组该怎么定义,不知道什么时候该导入什么库函数,这不是一个计算机专业的学生应该有的状态。大学三年学习了很多知识,学习了很多编程语言,但是当实际应用的时候发现知识体系没有构建起来,都是一些零散的知识,数据库会建立、数据库可以链接成功、散点图可以绘制、文本中可以读取到数据,但当它们都结合在一起时,就会很迷茫,不知道从何下手。这次实验又一次感觉编程能力太差,缺乏相应的思维意识,所以之后想要提高编程能力就要有针对性的练习,提高自己的编程能力,完善自己的知识体系。