201971010229-刘转弟 实验三 软件工程结对项目-《D{0-1}KP问题 实例数据集算法实验平台》

项目 内容
课程班级博客链接 2019级卓越工程师班
这个作业要求链接 作业要求
我的课程学习目标 1.了解软件工程过程中结对项目的开发流程
2.理解结对编程的重要性
3.提高个人编码能力
这个作业在哪些方面帮助我实现学习目标 1.通过本次作业的具体流程,使得我了解到了软件工程中结对任务的开发流程
2.填写PSP表格
3.学习相关算法及编码
4.了解到结对编程中代码规范,代码复审的重要性
结对编程队友 201971010222-李瑞婷
项目GitHub的仓库链接地址 仓库链接

1.实验目的与要求

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

2.实验内容与步骤

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

  • 代码规范: 变量名等的规范,缩进格式的规范,函数接口的规范。 原则:代码简单易懂,逻辑清晰 面向变化编程,而不是面向需求编程 。代码风格规范的原则是简明、易读、无二异性

  • 代码复审: 代码审查,是有意识地、有系统地与其他程序员一起检查彼此的代码是否有错误的行为。可以节省一些不必要的时间和资源,提高开发效率。

  • 结对编程: 两人合作工作与两个人各自独立工作相比,结对编程能编写出质量更高的代码。在面对一个问题的时候,经过讨论会得出一些更好的双方都支持的解决方案,使问题能够达到最优程度的解决。

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

  • 2.3 代码核查表
概要部分 代码符合需求和规格说明么? 代码符合要求
代码设计是否考虑周全? 考虑周全
代码可读性如何? 代码可读性较强,有着比较好的可读性。
代码容易维护么? 容易维护
代码的每一行都执行并检查过了吗? 都可以执行
设计规范部分 设计是否遵从已知的设计模式或项目中常用的模式? 遵从
有没有硬编码或字符串/数字等存在? 没有
代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)? 没有,不会影响移植,任何平台都可以
在本项目中是否存在类似的功能可以调用而不用全部重新实现? 可以调用
有没有无用的代码可以清除? 可以再简洁一些
代码规范部分 修改的部分符合代码标准和风格么? 按照代码标准修改的
具体代码部分 有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? 对错误都进行了处理
参数传递有无错误,字符串的长度是字节的长度还是字符的长度,是以0开始计数还是以1开始计数? 不涉及字符串
边界条件是如何处理的?switch语句的default分支是如何处理的?循环有没有可能出现死循环? switch语句的default分支返回false,没有出现死循环
对资源的利用是在哪里申请,在哪里释放的?有没有可能导致资源泄露? 在对数据库进行操作之前申请数据库连接资源,操作完毕之后释放申请的资源
效能 代码的效能如何?最坏的情况如何? 达到了具体任务的要求
代码中,特别是循环中是否有明显可优化的部分 可优化
对于系统和网络调用是否会超时?如何处理? 目前没有出现超时现象
可读性 代码可读性如何?有没有足够的注释? 可以顺利读取、代码有足够的注释让我们读懂
可测试性 代码是否需要更新或创建新的单元测试? 有创新点
- 2.4 clone 后运行

fork操作记录:

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

  • 3.1 需求分析
    • 后台要能够从给定的文件中读取出正确的数据并保存到数据库
    • java后端给前端传递正确的数据,前端根据后端传的数据绘制散点图
    • java后端实现对自定义数据类型的列表的排序(实现Comparator接口),并向前端传数据
    • 实现java后台解决D{0-1}背包问题的动态规划和回溯算法
    • 后台将求解后的数据写入文件并保存,前端展示文件下载阅览
    • 后台接收用户发送的算法文件并运行,将运行结果保存到文件然后返回前端
    • 后台编写遗传算法求解D{0-1}KP
  • 3.2 功能设计
    • D{0-1}KP数据可以保存到数据库,也可以从数据库中清除
    • 平台可绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图
    • 平台可对任意一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序
    • 在平台上,用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位)
    • 在平台上,任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件
    • 平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据
    • 平台可使用遗传算法求解D{0-1}KP
  • 3.3 设计实现
    (1)图形用户界面
点击查看代码
<title>01背包问题_最优解</title>
	</select> -->散点图
	</a></li>
	<li><a href="#">价值,重量比排序</a></li>
	<li><a href="#">最优解</a></li>
	<li><a href="01_start.jsp">散点图</a></li>
	<li><a href="02_start.jsp">价值,重量比排序 </a></li>
	<li class="active"><a href="03_start.jsp">最优解 <span
	class="sr-only">(current)</span></a></li>	
	<h2 class="page-header">请输入查询数据</h2>					
		<ul class="btn-group" role="group">
			<li class="btn btn-default"><a href="03_IDKP0_00_DT.jsp"
			style="text-decoration: none;">动态规划法</a></li>
		</ul>
		<ul class="btn-group" role="group">
			<li class="btn btn-default"><a href="03_IDKP0_00_HS.jsp"
			style="text-decoration: none;">回溯法</a></li>
		</ul>
		<ul class="btn-group" role="group">
		       <li class="btn btn-default"><a href="03_IDKP0_00_YC.jsp"
		       style="text-decoration: none;">遗传算法</a></li>
		</ul>	
(2)数据库访问
点击查看代码
//Product的数据访问类
public class Data1DAO {
	//添加一行商品数据,实际上是添加一个Product的对象
	public static int insert(Data1 p) throws SQLException{
		//1.连接数据库  2.构造SQL语句  3.(通过)预编译SQL语句  4.设置参数  5.执行SQL
		Connection conn = dbtool.getConnection();
		String insert = "insert into table_product(id v weight na ratio)"
				        +"values(?,?,?,?,?)";
		PreparedStatement pst = conn.prepareStatement(insert);
		pst.setString(1,p.getV());
		pst.setInt(2, p.getId());
		pst.setString(3, p.getWeight());
		pst.setString(4, p.getNa());
		pst.setString(5, p.getRatio());
		int result = pst.executeUpdate();
		return result;
	}	
	//删除一行数据
	public static void delete(int id){
		Connection conn = dbtool.getConnection();
		String delete = "delete from data1"
		+"where id=+'"+id+"'" ;
	}	
	//查找一个
	public static Data1 findProuduct(int id){
		//ResultSet rs;
		//从结果集rs中获得各列的值,用这些值构造一个Product对象
		return null;
	}	
	//查找多个
	public static List<Data1> findAll(){
		//ResultSet rs;
		//从结果集rs中获得各列的值,用这些值构造一个Product对象
		return null;
	}
}
(3)遗传算法
点击查看代码
//遗传算法
public class GeneticAlgorith {
    private static final Chromosome Exception = null;
    long timeStart = System.currentTimeMillis();
    public List<Chromosome> population=new ArrayList<Chromosome>();//存放所有的种群基因
    private int popSize; //种群规模N
    private int chromoLength;//每条染色体数目m;
    private double mutationRate=0.01;//基因突变概率pm
    private  double crossoverRate=0.6;//交叉概率pc
    private int bagMax=1000;
    private int generation;//种群代数t
    private int iterNum=10000;//最大迭代次数
   // private int stepmax=3;//最长步长
    private int [] charge={408,921,1329,11,998,1009,104,839,943,299,374,673,703,954,1657,425,950,1375,430,541,971,332,483,815,654,706,1360,956,992,1948};
    private int [] weight={508,1021,1321,111,1098,1196,204,939,1107,399,474,719,803,1054,1781,525,1050,1362,530,641,903,432,583,894,754,806,1241,1056,1092,1545};
    private double[]  density=new double[50];
    private Chromosome nowGenome;
    private Chromosome bestFit; //最好适应度对应的染色体
    private Chromosome iterBestFit;//全局最优染色体
    private double bestFitness;//种群最大适应度
    private double worstFitness;//种群最坏适应度
    private double averageFitness;
    /*
    初始化种群
     */
    public void init(){
        for(int i=0;i<charge.length;i++){
            density[i]=charge[i]/weight[i];
        }
        for(int i=0;i<popSize;i++){
            Chromosome g=new Chromosome(50);
            changeGene(g);
            population.add(g);
    /*
    计算种群适应度
     */
    public void caculteFitness(){
        bestFitness=population.get(0).getFitness();
        worstFitness=population.get(0).getFitness();
        totalFitness=0;
        for (Chromosome g:population) {
            //changeGene(g);
            setNowGenome(g);
            if(g.getFitness()>bestFitness){
                setBestFitness(g.getFitness());
                if(y<bestFitness){
                    y=g.getFitness();
                }
                setIterBestFit(g);
            }
            if(g.getFitness()<worstFitness){
                worstFitness=g.getFitness();
            }
            totalFitness+=g.getFitness();
        }
        averageFitness = totalFitness / popSize;
        //因为精度问题导致的平均值大于最好值,将平均值设置成最好值
        averageFitness = averageFitness > bestFitness ? bestFitness : averageFitness;
    }
    /*
    遗传算法GA流程
     */
    public void geneticAlgorithProcess(){
        generation=1;
        init();
        while(generation<iterNum){
            evolve();
            print();
            generation++;
        }
    }

3.测试运行

(1)登录界面

(2)后台页面

(3)绘制散点图

(4)排序

(5)算法选择及最优解

(6)具体算法求解(以遗传算法为例)

(7)数据库连接及数据导入

(8)数据库连接及数据导入

(9)结对编程交流

  • 结对编程
    • 项目分工
      • 1.项目刚开始我们在讨论是使用哪种人机交互界面,考虑到了使用安卓app等方案,但是基于实验二的实验基础最终出于页面效果和开发时间进度方面我们选择图形用户界面(Graphical User Interface,简称 GUI),GUI是计算机图形学技术的一种,它一般由窗口、下拉菜单或者对话框等图形化的控件组成。用户通过点击菜单栏、按钮或者弹出对话框的形式来实现与机器的交互,我们本次项目主要使用Web页面,提供选择算法解决D{0-1}KP问题,以及显示结果。
      • 2.在项目的具体开展过程中,我们各司其职,工作主要有网站页面开发,将前后端分离,算法设计,网站开发,将项目克隆下来,将算法嵌入到后台代码中,再push上去等等。最终在我们两个人的合作之下,完成了本次项目开发。
    • 分析程序的需求,并提交文档到github

4.PSP展示

PSP 任务内容 计划共完成需要的时间(min) 实际完成需要的时间(min)
Planning 估计这个任务需要多少时间,并规划大致工作步骤 15 10
Estimate 估计这个任务需要多少时间,并规划大致工作步骤 15 10
Development 开发 840 940
Analysis 需求分析 (包括学习新技术) 30 25
Design Spec 生成设计文档 20 30
Design Review 设计复审 (和同事审核设计文档) 10 10
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 45
Design 具体设计 60 65
Coding 具体编码 600 650
Code Review 代码复审 30 60
Reporting 报告 90 71
Test Report 测试报告 50 25
Size Measuremen 计算工作量 10 16
Test 测试(自我测试,修改代码,提交修改) 30 60
Postmortem & Process Improvement Plan 事后总结 ,并提出过程改进计划 30 30

5.项目总结

  • 1.结对编程有利有弊,但是总的来说是利大于弊的,1+1的效果>2。
  • 2.结对编程也是一次互相学习的过程,在结对的过程中,我们可以互相帮助,分享学习资源,出现问题也可以一起讨论解决,大大加快了项目的开展进度。而且我们分工明确,我们各司其职,互相交流,一起合作,最终很好的完成了本次项目。
  • 3.在项目开展过程中,遇到很多的问题,例如网络质量不佳,GitHub官网进不去,克隆项目也会出现网络超时的情况,在提交项目的时候也会出现github连接超时的情况,这个比较影响开发效率,还有遗传算法求解D{0-1}KP,经过查阅资料,最终只做出了遗传算法求解0-1问题,所以最终根据自己的情况,将实验要求中和了一下,只实现了0-1背包问题的求解,所以项目在这方面还有所欠缺。
  • 4.在结对过程我也看到了自己能力上的缺陷,以前学习的时候重视理论课而疏于实践课,导致和别人在动手实践上面的差距,但是在合作的过程中,更多的是鼓舞。此外,对于一些关于网站设计的思想,我也请教了队友,总体来说,是一次比较不错的合作体验。
posted @ 2022-04-04 22:44  刘转弟  阅读(89)  评论(2编辑  收藏  举报