结对项目—地铁出行路线规划

Posted chengfr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结对项目—地铁出行路线规划相关的知识,希望对你有一定的参考价值。

结对项目—地铁出行路线规划

我的搭档:陈鸿超 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实现

对不同城市地图的支持

对于不同城市,只有按要求提供给我们两个文件--地图文件和经纬度表,然后指定坐标的中心站点和两个边界站点。我们的程序就能够支持其他城市的地铁线路查询,不需要再做什么太大的修改。

 

我的收获:

  在新版本发布前,谈谈我目前的收获:
  本次项目的是体验结对编程的软件开发,但是事实上,由于平时时间的冲突,我和我的搭档的很多任务是分工独立完成的,尤其是很多的编码任务。在程序最早的构思阶段,和搭档一起交流,确实得到了一些灵感。相比于一个人思考,两个人一起讨论解决问题效率会更高一些,一方面是对方能带给你不同的观点和思路,另一方面是在向对方陈述的过程中,你的思路会更清晰一些,类似于小黄鸭debug法,而且对方会提出不同角度的反馈。我们这次程序设计中,我认为比较有意思,比较有亮点的地方就在于我们的地铁站坐标生成。根据我的了解,大部分组都是人工从地图上计算距离,然后一个个录入,这种方法还是比较实用的,两个人很快也可以把点全部测量完毕。然而我们的方法不同。在我们讨论的过程中,突然产生了一个灵感,就是根据北京市地铁站的实际经纬度,转化成图上点的坐标,而且我们发现竟然真的很容易找到这些地铁站的经纬度表。之后我们根据经纬度,转换为坐标,绘制地图。绘制出的地铁线路图与通常看到的线路图有较大的差别。线路不是直线,而是折线,而且二环以内的站点十分拥挤,而五环以外的站点十分稀疏,这是意料之中的。之后我们对于经纬度转坐标的函数进行了改进,使用了非线性函数,例如每个方向上的坐标绝对值开根号,结果10号线附近的线路显得拥挤。。。之后还做了其他的一些处理。最终的线路图并不好看,相比于手动绘制的地图,而且用时也挺长的(因为暂缓开通的站点缺少经纬度,花了些时间补全站点以及对图进行修正)。但是我们认为这很有意义,一方面是我们的程序的功能可以继续扩展,因为我们使用真实的坐标,我们可以提供北京市的地图置于线路图下层,为用户提供根据实际位置(不一定在地铁站附近,录入坐标可以计算附近的地铁站)推荐地铁线路的服务;另一方面是自动化总是一件好事情,虽然在小规模的数据中体现不出来,但是如果要更多地区的地铁线路图,甚至全中国的城市地铁线路图,我想这种方式的效率会高很多,至于直观的效果提升可以通过优化坐标转换的脚本实现。

 

参考资料:

https://en.wikipedia.org/wiki/Information_hiding

http://www.zhihu.com/question/19864652

 

以上是关于结对项目—地铁出行路线规划的主要内容,如果未能解决你的问题,请参考以下文章

结对项目-地铁出行路线规划程序(续)

结对项目-地铁出行路线规划程序(续)

结对项目--地铁出行路线规划程序(续)

结对项目-地铁出行路线规划程序(续)

结对项目-地铁出行路线规划程序(续)

结对项目-地铁出行路线规划程序(续)