我们组比较特殊。。三人结对
github:https://github.com/qingchanghan/WPFUI_Metro
po一张照片:
石浩然,韩青长、陈彦吉
(台式机真的很高端,分屏贼帅)
一、结对编程的优点和缺点:
- 缺点:
- 当结对编程的双方能力、性格、关注点有较大差距,且deadline紧迫时,不能更好地发挥结对编程相互指导的作用。
- 优点:
- 随时沟通交流,当遇到复杂的代码逻辑时,两个人比一个人能更好地理清代码思路。
- 一个人乱了另一个人不会乱,或者很难出现两个人一起乱,正确率整体、代码质量很高。
- 可以实现编程接力,在确定好todo项目后,可以交接工作,续航时间更长。一节更比六节长。
- 在心理上相互鼓励相互支持,在取得阶段性进展后,喜悦×n,贼开心。
二、每一个人的优点和缺点:
- 石浩然:心胸宽广,学习能力强,解决问题有独特的思路,但是由于完成个人项目时没有考虑到自己的代码会被他人用作扩展的基础,因此代码逻辑较复杂。
- 韩青长:学习能力强,实践能力强,目前没发现什么缺点。
- 陈彦吉:没什么优点。。缺点是心胸狭隘,比较怕麻烦。。
以下为结对项目博客中的共同部分
三、INFORMATION HIDING
- 当开发一个完整的程序时,可将程序的每个组成部分封装在一个模块中,每个模块尽量少地对外展示模块内部的数据与对数据的处理,以此提高代码的复用性、可维护性。减少外界可见的信息,以保持模块的独立性,以此降低耦合 。
- 从具体实现来说,我们确保某些成员变量和功能为private,并尽可能保证高层类只会调用底层类中特定的几个可供外界访问函数,而将其他方法封装在内部,限制了高层类对底层类的调用。
四、INTERFACE DESIGN
依稀记得OO曾经上过这个。。
接口设计一共有六大原则。原则说的都很清楚。。但是具体我们如何使用还是要多摸索。。
以下整理自博客:
- 单一职责原则
根据实际需求划分职责,尽量做到职责单一 - 里氏替换原则
所有引用基类的地方必须能透明地使用其子类的对象 - 依赖倒置原则
高层模块不应依赖底层模块,两者都应依赖其抽象
抽象不应该依赖细节,细节应该依赖抽象 - 接口隔离原则
接口尽量小,不要建立大接口,同时接口中方法尽量少,将接口隔离起来,将整体框架进行有效划分。 - 最少知识原则
跟information hiding有异曲同工之妙,此原则的使用可以降低程序耦合 - 开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭,编程前对不同的模块确立明确的逻辑分工,为变化预留位置
但是我们这一次由于大结构简单,因此没有设计接口,所以这些原则没有得到很好的实践。。希望能在以后的团队项目中积累相关经验
五、LOOSE COUPLING
- 尽可能全面地把握耦合度的高低,平衡好耦合和内聚程度,以确保可读性、服用性、可维护性的提升
- 不可一味强调低耦合,例如程序中发生变更概率很小的地方,不宜强行低耦合。
- 还有程序中一些为大函数服务的小函数,小函数本身是依附大函数存在的,本身不会和其他模块建立过多的依赖关系,此时在耦合度上最好也做相应折衷(好吧。。主要是因为我怕麻烦)
六、DESIGN BY CONTRACT
- design by contract把类与被调用类之间的关系看作契约,规定了双方的权力与义务,这一方法被认为是构建OO软件系统方法的核心。
另外, 我们通过一些知乎回答了解到的契约式设计: - 目的: 在设计程序时明确规定一个模块单元在调用前后应当处于何种状态,属于一种设计风格或是语法规范
- 思路:强调前置条件、后置条件和不变式,当违反这些操作时程序会抛出异常。
- 优点是:契约式编程使代码标准化、规范化,提高了程序工程化程度。
同时,对于测试者,在我们这次作业中,我们通过在不满足前置条件的情况下抛出异常,便于测试者测试。
- 缺点是有点麻烦。。
七、单元测试与代码覆盖率
这次结对编程,由于函数之间的调用关系较为复杂,因此我们仅对最主要的几个函数进行了测试如下是测试函数 。
一般来说通过assert.areequal方法可以测试大多数运算操作的值是否正确
[TestMethod()]
public void ReadDataTest()
[TestMethod()]
public void BuildGragphTest()
[TestMethod()]
public void FindNearestTransStaTest()
[TestMethod()]
public void DijkstraPathTest()
[TestMethod()]
public void BFSPathTest()
[TestMethod()]
public void MakePathSectionTest()
[TestMethod()]
public void isSameLineTest()
[TestMethod()]
public void GetLinkedStationsTest()
[TestMethod()]
public void GetShortestLinkedStationsTest()
另外,我们也测试了功能函数在遇到错误的输入时是否按照规定情况抛出了我们事先设定的异常,
我们设定了如下的异常:
1.某些情况下操作返回的空值引发的空引用异常
2.站点名称输入错误的站点输入异常
3.地图文件没有被正确开启的文件未被打开的异常
4.地图文件内部格式不符合规范的异常
5.内存溢出的异常
八、UML类图
九、关于我们的附加题和程序的一些特色
- 我们一开始完成了一个winform开发的版本,比较粗糙,但实现了基本功能,之后采用了石浩然同学通过WPF开发的界面,简洁美观,功能强大,不得不说他确实花了很多心思在UI上,这里特别鸣谢石浩然同学
- 关于我们的附加题。我们只需要一开始读入的txt按照我们要求的格式,并且提供一张与txt文件对应的地铁线路图,我们就可以实现其他城市的出行规划。
- 这里说一下我们的实现方法:txt文件中除了站点和线路,还要有每个站在线路图中的坐标,我们后期要根据这个坐标在图上显示相应的站与动画效果
- 在winform版中,我们将站点设置为按钮并固定在了地图上,用户可以通过点击地图或输入文本框来设置起点和重点,在WPF版中,由于鼠标的点击时间与图片的拖动绑定了,因此我们省去点击地图的功能,只能通过输入文本框来进行。
- 石浩然同学比较厉害,完成了-a的功能,并通过多线程,实现了程序可在后台计算-a,同时在前台计算用户的其他请求,当计算完成后再输出-a结果。不得不说他真的很厉害。。。特别鸣谢。。
十、个人总结
- 因为我们这一组是三人结对,所以比起两人结对,我们可能更偏向团队编程一些。在被deadline追赶的这几天里,我深刻地认识到了自己性格上的缺陷。
- 由于代码复审给我留下的印象不是很好,导致我可能对他存在一些偏见,当在决定使用他的代码为基础扩展时,我有一些抵触情绪,后来因为为了修复他的代码他和另一位同学给代码做出了较大修改,我的抵触情绪加剧了,但是不论是最后的UI还是功能,他的贡献确实是排在第一位的。这里确实要说一句辛苦了!
- 在结对中,我想的更多的可能是取舍的问题:代码简洁与代码高效是我们追求的两个维度,但是在很多情况下这两个难以两全齐美,所以在真正开发而且deadline紧迫时,我们应该怎样做取舍?根据什么做取舍?如何保证我们取了大的,舍了小的,不让自己亏本?以及以后团队编程中的一些编程规范的问题。
- 于是我想,这次结对编程对我来说可能更多的是对团队编程的一次预演,如何融洽团队,调节自身情绪,跳出偏见,公平公正地看待问题是我目前来说需要注意和改进的。以及这一次结对编程我做的真的很少,希望团队任务中我能多承担一些任务。