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的效果和效率,当然我也意识到自己编程中存在的许多不足,对语言的语法不熟悉,大量时间耗费在底层设计,这是编程中最忌讳的问题,就像《现代软件工程-构建之法》中所说,不知道数组该怎么定义,不知道什么时候该导入什么库函数,这不是一个计算机专业的学生应该有的状态。大学三年学习了很多知识,学习了很多编程语言,但是当实际应用的时候发现知识体系没有构建起来,都是一些零散的知识,数据库会建立、数据库可以链接成功、散点图可以绘制、文本中可以读取到数据,但当它们都结合在一起时,就会很迷茫,不知道从何下手。这次实验又一次感觉编程能力太差,缺乏相应的思维意识,所以之后想要提高编程能力就要有针对性的练习,提高自己的编程能力,完善自己的知识体系。
posted @ 2021-04-14 09:42  201871030117-李亚楠  阅读(98)  评论(0编辑  收藏  举报