首页 > 代码库 > 结对项目—地铁出行路线规划
结对项目—地铁出行路线规划
结对项目—地铁出行路线规划
我的搭档:陈鸿超 14061216
https://github.com/ChengFR/PairProgramming_SubwayRoute-
会在十一期间发布新版本
结对编程体会:
结对编程的优点:
- 站在软件开发的角度,两个人共同面对同一台电脑进行开发,无论是效率还是软件质量都要超过一个人进行开发的情况。
- 对于还处于学习阶段的年轻软件开发者来说,结对编程是一个很好的互相学习的机会
- 结对编程时动力、责任感更强
结对编程的缺点:
- 对于我们来说,寻找两个人共同的时间进行结对编程有些困难。
- 一个人编程时专注力更高
- 结对编程对于两个人的同步性具有比较高的要求
搭档的优点:
- 执行力强,对于分配的任务会立刻着手去做
- 团队责任感强
- 学习能力强
优秀设计方法的实践:
Information Hiding:
根据维基百科的定义,Information Hiding是一种将设计与实现相分离的原则。该原则有两个目的:其一是面向对象思想中的数据抽象,目的在于将设计与实现相分离,其他模块对于该模块的操作不依赖于该模块的内部实现,而取决于他所提供的接口;其二就是数据的保密性。本次程序设计中,利用车站ID是Information Hiding?
Interface Design
接口设计,我的理解是做一个抽象的规范。需要查阅更多资料后再做出解释。
Loose Coupling
弱耦合,强调程序模块的内聚性,独立性。程序模块的耦合性指的是与其他模块的关联程度。耦合性强的模块之间难以独立存在,那么模块最为功能载体的基本单位的意义就不是很明显。因此弱耦合性和内聚性是一个很重要的原则。在本次程序设计中,模块的"专有性"太强,并没有很好地做到弱耦合。
契约式设计:
契约式设计的主要目的是希望程序员能够在设计程序时明确地规定一个模块单元(具体到面向对象,就是一个类的实例)在调用某个操作前后应当属于何种状态。 这在上学期的面向对象课程中就体会过。契约式设计能够明确地指出功能模块的权利、义务,这也明确了模块实现者以及调用者的行为准则。看起来很厉害。但是在实践的过程中会发现一些问题,比如契约的描述难度和严格达到契约要求新增代码之间的矛盾。Design by Contract是Eiffel语言的一个特色,因为Eiffel是唯一一种以语法形式将前置后置条件和不变式规定为被调用方代码中独立语法块的语言。而对于其他语言来说,契约设计的实践存在一定的代价。
单元测试:(转自陈鸿超的博客)
单元测试这一块,在写测试程序时遇到两个问题,始终是不知道什么原因,也无法解决,被卡了两天,虽然写了测试样例,但是没有成功运行过,也不太清楚代码覆盖率怎样。
在这里,无法介绍单元测试的结果,只能说一下我们遇到的问题与分析。
问题:
在写好测试程序运行时,一直在报下面这个错误。
测试名称: TestMethod1
测试全名: UnitTest1::UnitTest1::TestMethod1
测试源: g:\软工\结对项目\pairprogramming_subwayroute--newversion\subwayroute\unittest1\unittest1.cpp:第 12 行
测试结果: 未通过
测试持续时间: 0:00:00.409065
结果 的堆栈跟踪:
位于 subwayNet::getRouteB() (第 g:\软工\结对项目\pairprogramming_subwayroute--newversion\subwayroute\subwayroute\subwaynet.cpp: 行中) 42
位于 UnitTest1::UnitTest1::TestMethod1() (第 g:\软工\结对项目\pairprogramming_subwayroute--newversion\subwayroute\unittest1\unittest1.cpp: 行中) 28
结果 的消息: 未处理的 C++ 异常
在网上找了很多帖子,讲的都是C#的单元测试,几乎没有介绍VS2015中C++单元测试的,更不要说这种问题了,所以只能自己分析。
分析:
1. 首先我根据他的提示找到了subwayNet::getRouteB()的第42行,这一行只是调用了calculateRoute类中的一个计算方法。我想是不是这个方法有问题,于是又把测试程序修改了一下,调用了calculateRoute类另外一个不相关的函数,可还是这样的错误,这样看来就不是函数的原因,而是有其他原因,不过没找到相关的帖子,就先放了放。
2.然后我又注意了一下 未处理的 C++ 异常 这个提示,正好这次我们自己封装了异常,会不会是因为我们封装的异常有问题才导致的这个错误?于是我找到较早版本的程序,那里面还没有使用异常,创建一个测试程序之后有出现了新的问题,这次竟然连编译都过不去,错误提示如下:LNK 2019 无法解析的外部符号。 我在测试程序中所有调用正常程序的函数都报了这个错误。
3. 对于这个LNK 2019错误,我在网上看到了很多不同的原因,发现其中一个和单元测试有点关系,讲的是什么函数内联的问题。不过讲的非常少,我只能大致推测。因为我们的程序为了防止多次编译,所以.h文件中都有#pragma once 。所以在测试程序中所要调用到的类都在正常程序的Main类中编译过了,而我们的测试程序运行时也要编译一次。而这些类又只能编译一次,所以才带来了各种各样的问题。
4. 为了检测是不是上述编译问题,我就天真的把#pragma once去掉了,结果连正常程序的编译都过不去(这里我也有疑问,我运行的是测试程序,只调用了几个功能类,运行时为什么会提示Main类错误呢?难道运行测试程序时也要把原程序运行一遍)。
5. 上述分析就是我这两天找到的,不过大都是我不太懂的层面的东西,这个单元测试也做不出来了,明天就要回家了,这就算了,国庆快乐\(^o^)/(单元测试以上部分均为陈鸿超同学写的......而我今天已经回家了,恩,国庆快乐~)
UML:
程序简述:
数据的读取
1. 首先我们定义了两个结构route和station分别保存线路和地铁站的相关信息。
2. 通过读取地图文件,判断并保存下各个线路包含的所有站点,站点的邻近站点,站点所属的线路等信息。
3. 因为要做界面,所以我们要确定各个站点的坐标。在获得北京市地铁站的经纬坐标后,我们写了一个脚本,将经纬坐标转换为在GUI显示的坐标,以天安门东为中心。
路线的计算
1. 最短路线采用的是广搜,从起点搜到终点之后再倒推出路线。
2. 对于最短换乘,是通过先遍历当前线路上所有点,没有的话再从当前路线上第一个点开始进行这样的循环,找到终点之后倒推出所有最少换乘,然后从中选择站点数最少的。
3. 对于偏好,我们是记录下之前调用-b和-c的次数,通过这两个数判断-g采用最短路线还是最短换乘。
异常的封装
1. 将文件错误,参数错误等分装成异常,在程序中抛出。
API封装
Route getStations(string &name);
//最短距离寻路
Route getRouteB(string &begin, string &end);
//最小换乘寻路
Route getRouteC(string &begin, string &end);
//画图
Route getRouteG(string &begin, string &end);
string changeRouteToString(Route & route);
界面设计
利用实际经纬坐标转换呈现,用openGL实现
对不同城市地图的支持
对于不同城市,只有按要求提供给我们两个文件--地图文件和经纬度表,然后指定坐标的中心站点和两个边界站点。我们的程序就能够支持其他城市的地铁线路查询,不需要再做什么太大的修改。
我的收获:
等新版本发布后再谈收获
参考资料:
https://en.wikipedia.org/wiki/Information_hiding
http://www.zhihu.com/question/19864652
结对项目—地铁出行路线规划