项目 | 内容 |
---|---|
这个做业属于那个课程 | 班级博客 |
这个做业的要求在哪里 | 做业要求 |
我在这个课程的目标是 | 学习软件工程相关知识,锻炼软件开发能力。 |
这个做业在哪一个具体方面帮我实现目标 | 完成我的项目,体会单元测试和PSP流程 |
做业正文 | 做业正文 |
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
·Estimate | 估计这个任务须要多少时间 | 60(7.2%) | 40(阅读具体要求,完成了博客框架) |
Development | 开发 | ||
·Analysis | 需求分析 (包括学习新技术) | 120(14.5%) | 90(c++复习,相关插件资料阅读) |
·Design Spec | 生成设计文档 | 60(7.2%) | 30 |
·Design Review | 设计复审 (和同事审核设计文档) | 10(1.2%) | 10 |
·Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10(1.2%) | 10 |
·Design | 具体设计 | 60(7.2%) | 30 |
·Coding | 具体编码 | 180(21.6%) | 90 |
·Code Review | 代码复审 | 60(7.2%) | 60 |
·Test | 测试(自我测试,修改代码,提交修改) | 120(14.5%) | 90 |
Reporting | 报告 | ||
·Test Report | 测试报告 | 60(7.2%) | 30 |
·Size Measurement | 计算工做量 | 30(3.6%) | 20 |
·Postmortem & Process Improvement Plan | 过后总结, 并提出过程改进计划 | 60(7.2%) | 30 |
合计 | 830 | 530 |
因为对C++的诸多特性没有很好的掌握,预估时对每一个部分的时间估计都过于宽松。实际完成时间大体会比预估少1/3-1/2。html
刚拿到题目时,考虑如何计算两条直线的交点。模拟解方程的过程过于复杂,且不够简便,因而考虑其余方法,搜索资料后发现能够采用计算几何的方法,利用向量求解交点。ios
参考1:直线交点c++
参考2:圆交点git
总体结构如上,开始设计时基本决定分两类,Point(点类,包含点的减法,叉乘与点乘方法)/Line(线类,包含求该对象与另外一线对象交点的方法),并决定采起map/queue分别存放交点与已读入的直线。github
完成初版后,为了改进性能对原始设计进行了一些修改,最终的类结构以下所示框架
class Point { public: double x; double y; Point(); Point(double _x, double _y); Point operator -(const Point& b)const; double operator *(const Point& b)const; double operator ^(const Point& b)const; bool operator <(const Point& b)const; bool operator ==(const Point& b)const; };
#pragma once #include "Point.h" #include <vector> #include <set> #include<iostream> using namespace std; class Line { public: Point s; Point e; Line(); Line(Point _s, Point _e); void intersect(set<Point>* pointset, const Line& b); };
因为总体逻辑比较简单,并未对关键函数绘制流程图。函数
单元测试方面,则是对点类与线类的每一个方法分别进行测试,确保在给定数据范围内的正确性。着重测试了求交点的intersect方法,利用随机数生成数据,并利用Geogebra画图求得交点的数值解,进而保证了intersect方法的正确性。工具
性能改进与单元测试编写共150分钟,性能
经过性能分析工具,对原始代码进行分析,发现本来使用的交点map插入前须要调用find方法判断是否已存在该交点。所以放弃map转而使用set+trycatch块,将消耗时间大量减小。单元测试
最终的性能分析图如图所示,其中Intersect方法占用时间最多(90.45%)
void Line::intersect(set<Point>* pointset, const Line& b) { Point res = s; if (sgn((s - e) ^ (b.s - b.e)) == 0) { return; } //判断平行(本应判断是否重合,因为本题不会出现重合状况,故舍去部分代码) double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e)); res.x += (e.x - s.x) * t; res.y += (e.y - s.y) * t; //计算几何求交点过程 try { pointset->insert(res); }catch (exception e){} //利用set的不重复特性,添加交点结果至set中 }
关键代码为Line的intersect方法,说明在注释中。
for (int i = 0; i < n; i++) { if (cmdin) in >> sub >> x1 >> y1 >> x2 >> y2; else cin >> sub >> x1 >> y1 >> x2 >> y2; Line tempLine = Line(Point(x1, y1), Point(x2, y2)); if (i != 0) { for (Line b : lineVector) { tempLine.intersect(&points,b); } } lineVector.push_back(tempLine); } if (cmdout) out << points.size() << endl; else cout << points.size() << endl;
外部调用则集成在IntersectLine函数中,如上所示,其主要部分是一个二重循环,对每个读入的Line,与以前读入并存在lineVector中的Line依次求交点。
消除 Code Quality Analysis 中的全部警告
单元测试数目:
覆盖率:
查看后添加了一部分单元测试,但没有增加,因为覆盖率与代码正确性无必然关系,所以没有再添加单元测试内容