结对项目博客
Posted 陈鸿超
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结对项目博客相关的知识,希望对你有一定的参考价值。
组员:陈鸿超
程富瑞
代码:https://github.com/ChengFR/PairProgramming_SubwayRoute-
一.结对编程分析
照片:
(忘了照了,十一大家都回家就算了)
结对编程的优缺点:
优点:
- 毫无疑问,两个人在一起解决一个问题想法更多。比如这次作业站点坐标的确定,之前一个人的时候,想法是手输或者写个算法自动计算,当然这个算法就会很难,不一定做的出来。而两个人在一起商讨时,他突然找到了一张北京站点的经纬表,看到这个我就想到了找一个站点做为中心点(0,0),再找两个最远站点,这样根据他们三个就可以换算出所有站点的坐标。很准确,而且最重要的是简单多了。
- 分配好任务之后,每个人的工作量就比较轻了。
- 互相借鉴学习对方的编码风格。
缺点:
- 自己的一些想法不能快速准确的传达给对方。
- 就这次而言,我们两个人都通读了完整的代码,在看到对方代码时效率难免有些低。
- 毕竟编程时不在一起,沟通起来有些麻烦。
个人优缺点:
因为之前用java比较多,所以写代码比较注意按功能进行封装。不过除了课上学到的知识以外,课外知识太匮乏,真的是感觉什么都不会。
二.如何利用好的设计方法
Information Hiding
对于信息隐藏,应该在数据建立的阶段就创建一种规则,使用一些ID来代表这些数据,当然也要记录下ID与相应数据的对应关系。在后面的操作中,对输入都可以转换为ID,然后对ID进行操作,输出也用ID表示。只有在最终展现给用户的阶段才将其转换为具体的数据。
Interface Design
接口的设计包括两个方面,一个是在编程时为了规范功能相似的类而定义的接口,这类接口的实现重点在于总结出相似类的共同点,然后将共同点其封装在接口中,让这些相似的类都根据自身情况去实现这些共同点;另一方面的接口设计则是为了提供给测试和外部程序使用,这方面就要做好封装的工作,让每个功能都能独立运行,不依赖与其他模块,有正确的输入就能出正确的结果。
Loose Coupling
对于这一点,主要还是尽量的对各种功能,实现这些功能需要用到的一些代码都进行封装,各司其职,尽量减少功能之间的依赖性。让每一个功能模块在输入正确的情况下就能够产生正确的输出,而不关心其他模块是否正确。这样才能在修改某一功能时尽量不对其他功能的代码造成影响。
三.契约式编程
其实契约式编程在大二下的OO课上接触过,感觉他其实更像是一种编程习惯。按照契约式编程的要求,每个方法都得有明确的前置条件,后置条件和不变式,其实也就是明确他的输入、输出已经中间的实现过程。
优点:通过这种格式化的规定,使用契约式编程写出来的程序,每个方法都会非常容易测试、Debug以及功能修改。而且这样写出来的代码清晰易懂,非常方便以后的维护与功能升级。同时,在最初的编程过程中,只有确定好了这三个条件,代码写起来也会简单很多。
缺点:麻烦,这种编程方式限制了方法的灵活度,必需要按照这种统一的格式,有时候还会带来内存和时间的额外开销。
这我们的作业中,对于那些封装在内部的各种功能函数,我们没有使用契约式编程这种方式,因为这是我们内部可见的,对格式的要求不高。而在包装提供给外部调用和测试用的API功能接口时,我们使用了契约式编程的方式,前置、后置和不变式都比较统一,这样方便了对这些接口的理解与使用。
四.Unit test
单元测试这一块,在写测试程序时遇到两个问题,始终是不知道什么原因,也无法解决,被卡了两天,虽然写了测试样例,但是没有成功运行过,也不太清楚代码覆盖率怎样。
在这里,无法介绍单元测试的结果,只能说一下我们遇到的问题与分析。
问题:
在写好测试程序运行时,一直在报下面这个错误。
测试名称: 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. 因为要做界面,所以我们要确定各个站点的坐标。这一点我们是写了一个函数,以天安门东为中心,根据一个站点经纬度表换算出各个站点的大致坐标,得到一个坐标文件。然后读取该坐标文件保存各站点的坐标。
(二) 路线的计算
1. 最短路线采用的是广搜,从起点搜到终点之后再倒推出路线。
2. 对于最短换乘,是通过先遍历当前线路上所有点,没有的话再从当前路线上第一个点开始进行这样的循环,找到终点之后倒推出所有最少换乘,然后从中选择站点数最少的。
3. 对于偏好,我们是记录下之前调用-b和-c的次数,通过这两个数判断-g采用最短路线还是最短换乘。
(三) 异常的封装
1. 将文件错误,参数错误等分装成异常,在程序中抛出。
(四) API封装
1. 为了单元测试,我们专门建了一个类subwayNet封装好了需要用到的几个功能接口,上述UML图中有详细介绍。不过因为测试程序始终运行不起来的原因,这点也没用到。
(五) 界面设计
1. 因为我俩都是小白,不懂GUI设计。从同学那了解到openGL最简单之后我们就选择它。不过还是因为第一次接触,做的有点丑。
(六) 对不同城市地图的支持
1. 对于不同城市,只有按要求提供给我们两个文件--地图文件和经纬度表,然后指定坐标的中心站点和两个边界站点。我们的程序就能够支持其他城市的地铁线路查询,不需要再做什么太大的修改。
以上是关于结对项目博客的主要内容,如果未能解决你的问题,请参考以下文章