结对编程
一、结对编程的优点和缺点
结对编程的优点
(1)在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力。
(2)对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
(3)在心理上, 当有另一个人在你身边和你紧密配合, 做同样一件事情的时候, 你不好意思开小差, 也不好意思糊弄。
(4)在企业管理层次上,结对能更有效地交流,相互学习和传递经验,能更好地处理人员流动。因为一个人的知识已经被其他人共享。
(5)结对编程让两个人所写的代码不断地处于“复审”的过程,正如前所述,复审是不断地审核,提高设计和编码质量的过程,结对编程让复审随时随地发生,这样才能及时地发现问题和解决问题,避免把问题拖到后面的阶段。
结对编程的缺点
(1)由于相互之间不是特别了解,所以需要一段时间去磨合,这也会降低编程的效率。
(2)结对编程在有些时候反而会降低效率,比如在处于探索阶段的项目,需要深入地研究,在这种情况下,一个人长时间的独立钻研是有必要的,两个人反而不好。
(3)如果验证测试需要运行很长时间,那么两个人在那里等待结果是有点浪费时间。
雷元勇:缺点 容易浮躁,如果调试一段程序老半天调不出来的话就会很恼火,然后脑子越来越乱,影响团队的进程。
二、 Information Hiding, interface design, loose coupling
1、 信息隐藏
在一个稍微复杂的程序中,或是软件中,局部变量的名称可能碰巧和一个全局变量相同,而我们又误把这个局部变量作为全局变量使用了。信息隐藏是减少这类偶然性复杂度的一个有效手段
对预防发货函数而言,输入参数,输出参数描述了它的边界。对于类而言,公有属性和公有方法描述了它的边界。边界以内的即是被隐藏掉的信息。信息隐藏是抽象数据类型,类等之所以存在的一个比较主要的理由。但信息隐藏并不只在使用抽象数据类型和类的时候才有意义。定义接口的时候,甚至实现的时候信息隐藏这一原则同样可以发挥作用。
2、 接口设计
面向接口编程在这次结对编程非常重要。在MVC中,视图是观察者,模型是被观察者,当模型状态改变时,调用所有观察者的Update方法,通知视图模型有变,视图在Update方法里写下响应代码,完成操作。通过这个方法,视图和模型就可以在仅依赖接口的情形下进行交互,而不必强耦合,而且在模型不变的情况下,视图可以随意替换。我们首先想到的就是:定义一套公共的接口,方便各个模块之间的通讯。这极大的提高了结对编程的效率
3、 松耦合
在我们的代码设计时,不用担心会破坏其它地方的代码。这种类与类之间依赖性低的设计方法,使一个类与另外一个类仿佛隔开了,它们之间只是通过消息来联系的,所以设计一类时,可以不用担心破坏另外一个类。当代码有改动时,可以不用大规模的改动我们的代码,我们只用定位于一个出问题的模块,然后对其进行更改就好了,而且能做到不改变其它模块的服务。
三、契约式编程
契约式编程
契约式编程不但可以使开发人员的思维更清晰,而且对于提高程序性能很有帮助。值得一提的是,它对于并行程序设计也有莫大的益处。
契约是减少大型项目成本的突破性技术。它一般由 Precondition(前置条件), Postcondition(后置条件) 和 Invariant(不变量) 等概念组成。.NET 4.0 除上述概念之外,还增加了 Assert(断言),Assume(假设) 概念。
契约的思想很简单。它只是一组结果为真的表达式。如若不然,契约就被违反。那按照定义,程序中就存在纰漏。契约构成了程序规格说明的一部分,只不过该说明从文档挪到了代码中。开发人员都知道,文档通常不完整、过时,甚至不存在。将契约挪移到代码中,就使得程序可以被验证。
四、算法
这个算法的基础是我修改了一下Elevator类的接口,在该类中增加了一个List<IRequest> Reqs成员,即让每个电梯都管理自己的请求队列,而不是在Scheduler类中管理全部请求。
我设计的算法的第一个关键点是,首先简单模拟了一下人们在选择电梯时的一些考虑,修改了Program类DrivePassenger()方法:
if( !elev.DisabledFloors.Contains((uint)p.SourceFloor) && !elev.DisabledFloors.Contains((uint)p.TargetFloor) )
这是判断电梯能否到达乘客的所在层和目标层,如果满足上述的if语句,依次进行如下判断:
1、if (elev.Reqs.Count == 0):如果当前某个电梯是没有任何请求的(即停在某一层不动),乘客优先选择这个电梯。
2、if (elev.CurrentStatus.CurrentDirection == Direction.Down && p.TargetFloor < p.SourceFloor
&& p.SourceFloor < elev.CurrentStatus.CurrentFloor ||
elev.CurrentStatus.CurrentDirection == Direction.Up && p.TargetFloor > p.SourceFloor
&& p.SourceFloor > elev.CurrentStatus.CurrentFloor):
这个是在判断顺路情况,比如说,乘客要从4层到8层,现在有两台电梯,第一台电梯的方向向上正路过8层,第二台电梯的方向向上正路过3层,这样乘客就会选择第二台电梯。
3、如果1、2都不满足,那么就会根据elev.Reqs.Count()的最小值选择一台电梯(可以直观理解为选择排队的人最少的电梯)。
第二个关键点是修改了Elevator类的NextAvailableFloor(int p, Direction d)方法。通过这个方法,可以让电梯根据自己请求列表Reqs选择出下一个目标层。
主要的算法在于判断顺路情况,比如说电梯现在正在向上路过5层,要去9层,这时电梯先后收到两个请求,第一个请求是去3层,而第二个请求是去8层,通过这个算法,尽管第一个请求的请求时间要早于第二个请求,电梯还是会把当前目标从9层改变为8层,把9层作为第二个目标,把3层作为最后一个目标。
以上设计的算法实际是简单模仿了现实生活中电梯的运行方式以及乘客选择电梯时的考虑。
五、unittest