标签:设计 内容 lis with 可见 错误信息 width 组合 目的
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 15 | 10 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 60 | 90 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 0 | 0 |
· Design | · 具体设计 | 90 | 100 |
· Coding | · 具体编码 | 420 | 500 |
· Code Review | · 代码复审 | 120 | 140 |
· Test | · 测试(自我测试,修改代码,提交修改) | 90 | 150 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 0 | 0 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 0 | 0 |
合计 |
这次的项目涉及到了前后端两个部分,为了实现前后端的分离,我们首先将前后端的职责进行了明确的划分。
由此,这个项目的前后端就清晰的分离开了,具体表现在
然后,根据最终产品的功能需求,我们在后端模块中设计了如下几个核心接口
相比于上次的实现,这次的计算模块只增加了一个接口类,用于供前端调用
相比于上次的内容,这次增加了线段和射线,其本质是对直线的左右边界做了限定,所以我们采用扩展原有的Line
类的方法来支持本次对扩展。
本次扩展对Line
类添加了左右边界的属性
这样,原有的核心计算方法依然可以正常工作,只需在计算出具体Point
交点时对其坐标进行判断即可,即所有线都按直线计算,然后再使用自身的边界对结果进行筛选
此外,这次添加了异常处理功能
这部分是使用c++
自身的异常机制来进行实现的。
我们首先针对题意分析出了一系列可能的异常情况,然后分别在可能出现异常的代码段进行了异常抛出,同时,我们在后端抛出异常时会设定好其中的异常信息,从而使得前端只需捕获异常,然后向用户回显其中的异常信息即可
而对于输入处理方面,我们采用了C++11
的正则表达式来处理,根据题目的要求,我们指定了一系列的正则表达式,对每种图形的输入都做了检查,当检查失败时同样会采用抛出异常的方式来进行处理
对比上次的实现,这次对浮点数的处理做了一些优化
之前采用的是long double
直接hash
和==
运算,不仅hash
耗时较长,而且会存在精度的问题,为了解决这些方面的问题,这次对浮点数的处理进行了优化
首先根据题目给出的数据范围,我们大致估计出了数据精度只需在float
即可,所以我们首先使用了float
来代替long double
进行hash
操作
虽然这样可以加快hash
操作的速度,但是精度问题依然没有解决,会出现0.999999999
和1.000000000
的问题,所以为了解决这个问题,我们采用了\(\epsilon\)的计算方式。
即对每个浮点数先在高精度上加一个极小值,然后再将其截断为float
,这样像上面提到的问题就解决了。
通过上面一系列处理,不仅hash
计算耗时问题解决了,同时也解决了精度问题,一举两得。
上面是VS性能检测器的分析结果
在上一次个人项目中,count_line_with_line
的主要耗时点在compare
和hash
上,而如今在计算函数内容没有大变动的情况下,get_intersection_with
和compare
与hash
的耗时基本持平,由此可见这个优化带来的收益还是很大的。
契约式编程在多人开发中使用较为广泛,其主要特点就是开发建立在规约之上,所有人共同制定统一的代码规约,其一般包括
基于团队定制的一系列规约,每个人都只需要注意自身是否完成了规约中规定的内容即可,而不需额外的顾虑。
这种方式的好处是显而易见的,每个人根据自身开发范围相关的规约进行开发,而无需考虑额外的事情,由此肯定会带来代码耦合度的降低以及团队开发效率的提升。
但同时这个方式也存在一些弊端,首先,规范的制定是一件很难的事情,规范强调其稳定性,如果规范频繁发生变动,那么所有相关的开发人员都要受到影响。其次,为了是自身完成的代码满足规约,一般会采用一种防御式编程的方式进行开发,这种方式的特点为广用Assert断言,会使得代码变得比较冗杂。
而在我们这次结对开发中,我们在前后端接口上使用了这种方式,我们先根据需要完成的功能共同探讨了后端需要给前端提供的接口,制定了接口的输入输出以及异常的规范,然后再进行开发,前后端可以同时进行,效率很高。
针对这次的项目新增的一些功能以及异常处理方面,我们也对第一阶段的项目的测试做了很多补充和扩展
上面唯一没有测试的类是main所在的类,因为在UI方面和exe方面进行了相应的测试,也因为和文件的输入输入相关,单元测试起来会比较受环境影响,所以这里并没有进行相关的测试。
/*
两个线段,他们可能只有一个端点相交
*/
TEST_METHOD(TestTwoSegmentIntersecInEnd) {
Line line1("S 0 0 1 1");
Line line2("S 0 0 1 -1");
std::vector<Point> result = line1.get_intersection_with(line2);
Assert::AreEqual(1, (int)result.size());
}
/*
两线段共线,且有一个公共交点(端点)
*/
TEST_METHOD(TestTwoSegmentInSameLineHaveOneIntersection) {
Line line1("S 0 0 1 1");
Line line2("S 1 1 2 2");
std::vector<Point> result = line1.get_intersection_with(line2);
Assert::AreEqual(1, (int)result.size());
}
/*
两线段共线,且无交点
*/
TEST_METHOD(TestTwoSegmentInSameLineHaveNoIntersection) {
Line line1("S 0 0 1 1");
Line line2("S 2 2 3 3");
std::vector<Point> result = line1.get_intersection_with(line2);
Assert::AreEqual(0, (int)result.size());
}
上面是一部分测试代码,可以看到,我们针对一些边缘情况进行了较为全面的测试,涵盖了每一种组合情况,同时,为了便于出错时进行bug修复,我们对比较重要的测试进行了注释解释,从而便于后期维护。
这次的异常处理我们主要考虑了下面几种
针对上面这几种异常情况,我们都会将相应的错误信息包装在exception中抛出,让UI做回显
/*
圆半径异常
*/
TEST_METHOD(IllegalCircleRedix1) {
auto func = [] {
Solution s;
s.add_component("C 0 0 0");
};
Assert::ExpectException<std::exception>(func);
}
/*
非法字符输入(小写字母,特殊符号)
*/
TEST_METHOD(IllegalCharacterInput1) {
auto func = [] {
Solution s;
s.add_component("l 0 0 1 1");
};
Assert::ExpectException<std::exception>(func);
}
/*
输入点重合
*/
TEST_METHOD(PointCollision1) {
auto func = [] {
Solution s;
s.add_component("L 0 0 0 0");
};
Assert::ExpectException<std::exception>(func);
}
/*
两线段共线,且有多个交点(部分重合),期望抛出异常
*/
TEST_METHOD(TestTwoSegmentCoverPart) {
auto func = [] {
Line line1("S 0 0 3 3");
Line line2("S 1 1 5 5");
line1.get_intersection_with(line2);
};
Assert::ExpectException<std::exception>(func);
}
/*
各种坐标超限
*/
TEST_METHOD(ArgumentOutOfBound1) {
auto func = [] {
Solution s;
s.add_component("C 100001 0 1");
};
Assert::ExpectException<std::exception>(func);
}
关于这次结对编程,我们采用的是VS的Live Share和QQ屏幕共享来进行的。
首先是Live Share,这个功能很强,但是因为网络的问题,一般40-60分钟持续连接后就会出现卡顿,优点是可以同时开发以及编码。
而QQ屏幕共享的优点是基本没有卡顿,但是缺点是画质较差且不能同时编辑,指出具体某行代码时也有些麻烦
结对编程的优点:
结对编程的缺点:
我的优点:
我的缺点:
搭档的优点:
搭档的缺点:
标签:设计 内容 lis with 可见 错误信息 width 组合 目的
原文地址:https://www.cnblogs.com/Nocturne/p/12546038.html