201871010131-张兴盼 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | https://edu.cnblogs.com/campus/xbsf/2018CST |
这个作业要求链接 | https://www.cnblogs.com/nwnu-daizh/p/14604444.html |
我的课程学习目标 | 熟悉软件项目结对合作开发流程,并开发出本次软件项目。 |
这个作业在哪些方面帮助我实现学习目标 | (1)思维方面,有利于构建软件项目合作意识。 (2)学习经验方面,学会如何去完成结对软件项目。 |
结对方学号-姓名 | 2018710128-杨丽霞 |
结对方本次博客作业链接 | 结对方博客作业链接 |
本项目Github的仓库链接地址 | 仓库链接地址 |
实验内容
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念。
- 已阅读。
- 代码风格规范
1、代码风格的原则是:简明,易读,无二义性。
2、缩进:4个空格,不用Tab键是因为在不同的情况下显示的长度可能不一样。
3、行宽:限定为100字符。
4、括号:在复杂的条件表达式中,可以清晰地表示逻辑优先级。
5、断行与空白的{}行:断行在程序调试时可以清晰的表达变量的变化情况,{}来判断程序的结构。
6、分行:不要把多个变量定义在一行上。
7、命名:
1)在变量名中不要提到类型或其他语法方面的描述。
2)避免过多的描述。
3)如果信息可以从上下文中得到,那么此类信息就不必写在变量名中。
4)避免可要可不要的修饰词。
5)下划线:用来分割变量名字中的作用域标注和变量的语义。
8、大小写:
1)所有类型/类/函数名都用Pascal形式(所有单词第一个字母都大写)。
2)所有变量都用Camel形式(第一个单词全部小写,随后单词用Pascal形式)。
3)类/类型/变量:名词或组合名词。
4)函数则用动词或动宾组合词来表示。
10、注释:注释是为了解释程序做什么(What),为什么这样做(Why)以及要特别注意的地方。 - 代码设计规范
1、概念:代码设计规范不光是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方方面面,又有不少内容与具体程序设计语言息息相关(如C,C++,JAVA,C#),但是也有通用的原则。
2、函数:原则:只做一件事,并且要做好。
3、goto:函数最好有单一出口,为了达到这一目的,可以使用goto。
4、错误处理:
1)参数处理:在Debug版本中,所有的参数都要验证其正确性,在正式版本中,对从外部(用户或别的模块)传递过来的参数,要验证其正确性。
2)断言:验证正确性就要用断言。
5、如何处理C++中的类
1)类:
a.使用类来封装面向对象的概念和多态。
b.避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要要用类来实现。
c.对于有显示的构造和析构的类,不要建立全局的实体,因为不知道它们在何时创建和消除。
d.仅在有必要时,才是用“类”。
2)class vs.struct:如果只是数据的封装,用struct即可。
3)公共/保护/私有成员:按照这样的次序来说明类中的成员。
4)数据成员:
a.数据类型的成员用m_name说明。
b.不要使用公共的数据成员,要用inline访问函数,这样可兼顾封装和效率。
5)虚函数
a.使用虚函数来实现多态。
b.仅在很有必要时,才使用虚函数。
c.如果一个类型要实现多态,在基类中的析构函数应该是虚函数。
6)构造函数
a.不要在构造函数中做复杂的操作,简单初始化所有成员即可。
b.构造函数不应该返回错误。
7)析构函数
a.把所有的清理工作都放在析构函数中。如果有些析构函数在之前就释放了,要重置这些成员为0或NULL。
b.析构函数也不应该出错。
8)new和delete
a.如果可能,实现自己的new/delete,这样可以方便地加上自己的跟踪和管理机制。自己的new/delete可以包装系统提供的new/delete。
b.检查new的返回值。new不一定都成功。
c.释放指针时不用检查NULL。
9)运算符
a.在理想情况下,我们定义的类不需要自定义操作符。确有必要时,才会自定义操作符。
b.运算符不要做标准语义之外的任何动作。
c.运算符的实现必须非常有效率,如果有复杂的操作,应定义一个单独的函数。
d.当拿不定注意时,用成员函数,不要用运算符。
10)异常
a.不要用异常作为逻辑控制来处理程序的主要流程。
b.当使用异常时,要注意在什么地方清理数据。
c.异常不能跨过DLL或进程的边界来传递消息,所以异常不是万能的。
11)类型继承
a.仅在有必要时,才使用类型继承。
b.用const标注只读的参数。
c.用const标注不改变数据的函数。 - 代码复审:看代码是否在代码规范的框架内正确的解决了问题。代码复审的形式包括:自我复审、同伴复审、团队复审。
- 结对编程:结对编程中有两个角色:领航员和驾驶员。在个人编写的过程中,很多人喜欢根据个人喜好来规定代码规范,而且存在的bug自己难以发现,因此,在结对编程时,我们可以互换角色,在开始写代码之前,规定两个人都认可的一套代码规范,并且不间断地进行复审,以减少软件中存在的问题,修复bug,提高软件质量。
- 代码风格规范
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价。
-
对项目博文作业进行阅读并进行评论,评论要点包括:博文结构、博文内容、博文结构与PSP中“任务内容”列的关系、PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究,将以上评论内容发布到博客评论区。
- 已完成。点击这里查看结对方实验二作业博客。
- 已完成。点击这里查看结对方实验二作业博客。
-
克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.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)外的任意有效平台功能实现。
- 需求分析陈述。
- 读取文件的数据并处理数据:在读取文件的时候有去除掉多余的数据,并将读出的结果分别存在多个数组Array List的对象中;然后将这些Array List对象进行切割并输出在另一个文件中;
- 生成散点图:将文件中的点对读出来后,用java的swing来画出散点图;
- 动态规划:动态规划法是一种通用的算法设计技术用来求解多阶段决策最优化问题。其设计思想如下:
1.划分子问题:将原有的问题划分为若干个个子问题;
2.确定动态规划函数,将子问题之间的重叠关系找到子问题满足递推关系式即动态规划函数,这是关键;
3.填写表格:设计表格,以自底向上的方式计算各个子问题的解并填表,实现动态规划过程。 - 回溯法: 回溯法在包含问题的所有可能解的解空间树中,从根节点出发,按照深度优先的策略进行搜素,对于解空间树的某个结点,如果该结点满足问题的约束条件,则进入该子树进行搜素,否则将以该结点为根节点的子树进行搜素;
- 对程序进行调试。
- 软件设计说明。
- 可正确读入实验数据文件的有效D{0-1}KP数据;
- 能够绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
- 能够对一组D{0-1}KP 数据按项集第三项的价值:重量比进行非递增排序;
- 用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
- 任意一组D{0-1}KP数据的最优解、求解时间和解向量可保存为txt文件或导出 EXCEL文件。
- 程序运行:程序运行时每个功能界面截图。扩展功能实现可得附加分5分。
- 绘制散点图
- 算法求解
- 动态算法求解
- 数据库存储
- 排序实现
- 主要代码
- 绘制散点图
class IndexAction extends CommonAction {
public function index() {
$this->display();
}
public function sort()
{
$this->display();
}
public function sortResult()
{
$data['fileName'] = $_REQUEST['fileName'];
$data['seriesNumber'] = (int)$_REQUEST['seriesNumber'];
$url = 'http://127.0.0.1:5000/sort';
$return = $this->posturl($url, $data);
$len=count($return,COUNT_NORMAL);
for($i=0;$i<$len;$i++)
{
$str[$i]=str_ireplace(array('{','\'','}','p1','p2','p3',':','pw1','pw2','pw3','w1','w2','w3'), array('', '','','','','','','','',''), $return[$i]);
$result[$i]=explode(",",$str[$i]);
}
if (Null != $return)
{
$this->assign('result_data',$result);
$this->display('sort');
}
else
{
$this->error('排序失败',__APP__ . '?g=Index&m=Index&a=sort');
}
}
function posturl($url,$data){
ini_set('max_execution_time',0);
$data = json_encode($data);
$headerArray = array("Content-type:application/json;charset='utf-8'","Accept:application/json");
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return json_decode($output,true);
}
public function scatter() {
header("Cache-Control: no-cache, must-revalidate");
$data['fileName'] = $_REQUEST['fileName'];
$data['seriesNumber'] = (int)$_REQUEST['seriesNumber'];
$url = 'http://127.0.0.1:5000/';
$pic_url='http://127.0.0.1:5000/static/1.png';
$return=$this->posturl($url,$data);
$this->assign('pic_url',$pic_url);
$this->display();
}
public function salve() {
$this->display();
}
public function salveResult()
{
$data['fileName'] = $_REQUEST['fileName'];
$data['seriesNumber'] = (int)$_REQUEST['seriesNumber'];
$data['maxWeight'] = (int)$_REQUEST['maxWeight'];
if (Null == $data['maxWeight'])
{
$this->error('背包的最大重量未填',__APP__ . '?g=Index&m=Index&a=salve');
}
$url_flashBack = 'http://127.0.0.1:5000/flashBack';
$url_dp = 'http://127.0.0.1:5000/dp';
if ($_REQUEST['salve_function'] == flashback) {
$flashBack_result = $this->posturl($url_flashBack, $data);
$this->assign('salveResult',$flashBack_result);
$this->display('salve');
} else {
$dp_result = $this->posturl($url_dp, $data);
$this->assign('salveResult',$dp_result);
$this->display('salve');
}
}
public function dp(){
}
public function check(){
$this->display();
}
public function checkResult(){
$data['fileName'] = $_REQUEST['fileName'];
$data['seriesNumber'] = (int)$_REQUEST['seriesNumber'];
$data['maxWeight'] = (int)$_REQUEST['maxWeight'];
$data['fileType'] =$_REQUEST['fileType'];
$data['value']=$_REQUEST['value'];
if (Null == $data['maxWeight'])
{
$this->error('背包的最大重量未填',__APP__ . '?g=Index&m=Index&a=check');
}
if (Null == $data['value'])
{
$this->error('运行错误',__APP__ . '?g=Index&m=Index&a=check');
}
$url = 'http://brp964.natappfree.cc/upload';
$salve_return=$this->posturl($url,$data);
dump($salve_return);
$this->assign('salve_return',$salve_return);
$this->display('check');
}
}
- 描述结对的过程,提供两人在讨论、细化和编程时的结对照片(非摆拍)。
-
结对照片
-
讨论记录
-
提供此次结对作业的PSP。
-
PSP 各个阶段 | 我们预估的时间(小时) | 实际的记录(小时) |
---|---|---|
计划: 明确需求和其他因素,估计以下的各个任务需要多少时间 | 1 | 1 |
开发 | 5 | 7 |
需求分析 | 3 | 4 |
生成设计文档 | 1 | 1 |
设计复审 | 3 | 3 |
代码规范 | 4 | 3 |
具体设计 | 5 | 4 |
具体编码 | 6 | 10 |
代码复审 | 1 | 2 |
测试 | 1 | 1 |
报告 | 1 | 1 |
测试报告(发现了多少bug,修复了多少) | 3 | 4 |
事后总结, 并提出改进计划 (包括写文档、博客的时间) | 1 | 1 |
总共花费的时间 (小时) | 35 | 42 |
- 小结感受:小结感受:两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。
首先,我认为两人合作肯定能够带来1+1>2的效果。于我个人而言,上次的个人项目完成的很不好,面对学习任务无从下手,在网上查了相关资料之后还是无能为力。但在结对编程的过程中,我们先根据自己的思路进行了沟通,先快速地制定了完整的PSP流程。整个任务过程遇到问题我们会及时进行沟通,或者共同查阅资料,节省了很多时间,大大提高了我们的效率。虽然最终我们的任务完成的不是很好,但也有了一些除知识之外的新收获。