Pair Project——Elevator Scheduler
本次结对编程作业,我和付博扬同学一组,为了使作业能够更有效率地完成,针对已有的电梯调度程序,我们进行了初步的简单任务分工以及时间分配。
首先在时间分配上,两周时间看上去很多,但其实相当紧迫。
一方面,这次的项目相比以往最不同的一点是,我们要在一个已有的项目上进行代码加工,这意味着我们需要先读懂已有的程序代码,并在理解之后才能开始项目展开。由于我们之前对C#的掌握并没有那么牢靠,因此C#的相关知识学习的巩固提高也需要耗去相当一部分时间。
另一方面,由于两人并不在一个班级,之前并不熟悉,因此前期的交流配合上还是有一定的不便,不过这个问题随着项目的进行而慢慢消失。此外由于大家都比较习惯了单独编程,关于结对编程虽然老师在课上讲了很多结对配合的艺术,但真正实践起来却又是不一样状况,很多东西需要双方慢慢摸索适应,比如编程习惯比如学习时间等等都需要逐渐相互适应相互迁就。
综合以上多方面因素,经过我们俩人慎重商量之后,最终决定在第一周花四天时间读懂代码,这一过程中还要算上看书学习的时间,边学边理解。因为读代码并不需要俩人在一起配合工作,所以这对于我们逐步适应Pair Project算是很好的缓冲,既可以借这几天加深相互的了解,也省去了突然在一起工作的无所适从感。但最终表明我们还是稍微低估了这一工程的工作量,我们最后真正用了五天才把这一段工作完结,除去上课之类的其他琐事耗去的时间,虽然是比较现学现卖,效率终究还是低了点,但是这一天的差距还是在我们预料的弹性范围之内的,因此并没有对后期工作的展开造成太大的麻烦。而且相互了解适应加强交流的目的算是初步达到了。
接下来的周末两天,我们在多次一起交流了对于项目要求的理解,并讨论了如何对原有的工程进行修改以便能够在满足项目要求的情况下提升电梯运行效率的各种方案,这一系列问题探讨下来,我们在许多方面终于成功达成共识,对于代码的修改也有了大体的认识了解了。根据我们的理解,我们设计做出了第一个工作成果——UML图:
这为我们后面的代码书写打下了牢靠的基础。
第二周才是真正辛苦的工作,为了尽可能避免由于独自编写代码容易导致的对方难理解难以下手等问题,我们选择尽量多在一起进行工作,经验证明这样一大好处就是编写代码的效率显著提高。一方面,正如老师课上所说,我们都不好意思分心做别的事耽误对方的时间;另一方面,编程过程中出现有些C#方法不大懂用的时候,不编程的一方可以迅速翻书查找,然后讨论着解决。此外,这种方式下两人都不会对代码感到不熟悉,可以交替着编程,也不至于有一个人太累另一个人闲着。
又经过四天的折磨,我们的代码终于初步出炉了,下面上部分样图:
1.
2.
但这还不是结束。余下的三天我们一直忙于样例测试和代码的修改优化,还有博客的编写。。。这果断也是一个很麻烦的事情,因为总是会有样例跑得比BUS要慢。经过令人多次冷人崩溃的代码修改之后,我们才最终勉强搞定了这次的Pair Project.
总结这次的结对编程,有些优缺点在前面已经提过,这里不再重复,再补充一些:
其优点是:是我们初步掌握了与他人合作编写程序的能力;编程效率相比个人有了较大提高,像这种规模的作业在之前理应是大作业级别的,但是两个人能在两周内搞定的确很难得;还有不得不说的一点是,这也促使我们将代码写得规范化,那种自己以前单独写代码时混乱的代码格式完全就是坑爹行为。。。
其缺点是:首先最大的问题是,要求两个人都能抽出同段时间一起写作业实在是一件麻烦的事;另外,结对编程一大反效果就是,随着项目的不断深入,时间的减少,每当见到队友就会有种越来越大的无形的压力。。。
关于自己的优缺点:
优点是:比较善于表达;能够认真完成工作;很守时不迟到;
缺点是:生物钟比较混乱,学习时间不稳定
关于队友的优缺点:
优点是:办事踏实牢靠;容易沟通相处;编程习惯好
缺点是:相当低调含蓄
关于契约式编程(Design by Contract, Code Contract):
关于契约式编程,其最大的优点莫过于将双方的权利和义务捆绑在了一起。调用者和被调用者彼此必须履行义务才能够行使权利。简而言之,就是函数调用者应该保证传入函数的参数是符合函数的要求,如果不符合函数要求,函数将拒绝继续执行。如果按照契约式编程的思想编写代码,就要求我们写函数时检查函数参数。有时候是简单的判断某个参数不能为空,或者数值不能小于0。如果在项目中全面应用契约式编程,则应该有一个“契约框架”帮我们来做这些事情。
一般认为在模块中检查错误状况并且上报,是模块本身的义务。而在契约体制下,对于契约的检查并非义务,实际上是在履行权利。一个义务,一个权利,差别极大。例如下面的代码:
if (dest == NULL) { ... }
这就是义务,其要点在于,一旦条件不满足,我方(义务方)必须负责以合适手法处理这尴尬局面,或者返回错误值,或者抛出异常。而:
assert(dest != NULL);
这是检查契约,履行权利。如果条件不满足,那么错误在对方而不在我,我可以立刻“撕毁合同”,罢工了事,无需做任何多余动作。这无疑可以大大简化程序库和组件库的开发。