首页 > 代码库 > Pair Project1:电梯控制程序

Pair Project1:电梯控制程序

12061199 程刚  &&   12061204 黎柱金

 

一、结对编程的优缺点

结对编程相对于一个人的编程有更多的优点,缺点也有很大不同。

首先,优点:

  1. 结队可以让两人可以更好的协作(也是结队的意义所在了)。让两人的团队意识和团队能力有更大提升,增加两人的相互了解与认识。
  2. 结队可以让两人相互学习,在结对中和相互合作、相互学习、相互督促,两人冲着同一个目标结对编程。
  3. 结队可以明显提高一人编程的效率,两人在一起读写代码时可以相互讨论,一人不知道的多,但是两人同时不知道的就少许多了,疑问少了,效率自然而然的上来了。
  4. 结队可以提高一人编程的正确性,两人在相互质疑相互讨论的过程中相互纠正着,特别是调度算法中,两人一同商量着更加好的算法,在不断的在讨论中改进算法,降低平均乘客等待时间。

其次,确定:

  1. 两人课程时间不是很同步,一起编程的时间受限,应协调两人的课程与作息时间。
  2. 两人代码风格不同,在代码编写中不是很方便。
  3. 两人在结队时会有不同意见,因此得相互说服对方,最好得出两人都同意的结果,其中要费不少口舌与时间。

 

二、结队组员的优缺点

1. 程刚同学:善于合作,待人真诚,善于寻找更好的算法。但是缺点却也很明显,急于求成,总是希望可以立刻完成作业。

2. 黎柱金同学:代码能力强,性格随和,肯吃苦,稳重,在一步一步中完善代码。缺点确实比较喜欢拖DEADLINE,这点和程刚完全不同,两人因此相互监督。

 

三、结队合作过程

1. 首先两人拿到题目,开始阅读老师的要求,寻找各种在要求中重要的信息,编译编程的进行。

2. 然后两人下午相约一起去图书馆进行代码读写,在图书馆中两人一起老师给的代码,相互答疑,实在不知道就只能寻找度娘了,用了一个下午将代码差不多看完。

3. 晚上,两人分别自己想好算法,那时我和同寝室的一群人在一起商量如何实现调度算法,经过讨论到凌晨3点左右,最后我们6人(隔壁寝室的 也来了两个)觉得应该将电梯作为主体,在指令没有完全完成前,最开始由一个最先的指令调动停止运行着的电梯开始运行,而从此时开始主动权就交个电梯了,电梯在每次经过一个不是disabledfloor时都要进行考虑自己是否已经满载了?如果是,将不会开门;如果否,考虑在此时电梯所在楼层是否有请求(之前未被处理的请求或者临时来的请求),如果有且指令与电梯当时状态时顺路的,开门,每进一个顺路乘客都要再计算是否满载,如果否,直到请求全部搭载完或者电梯已经满载了。如此循环四个电梯,直到指令全部完成。当然其中也许会有电梯搭载完人之后也许就停留下来,如果指令临时寻找不到顺路的电梯,那肯定会调用此时不在运行状态的电梯,以节省乘客等待时间。第二天询问黎柱金时,他的想法不同,他的想法是以请求为主体,当第一个请求出来之后,电梯前去搭载乘客,然后在过程中也许会出现顺路指令而且在第一个指令之后,于是乎电梯就需要超前扫描指令,在一段时间内寻找最佳选择,使得乘客等待时间最短,如此循环将指令全部走完。

4. 当然想到的代码并不一定就可以完全运用在代码时间编写中,要在伙伴中不断讨论、修改、尝试中不断修改算法和代码。

5. 对完成的初步代码进行测试、完善和优化,其中也不乏和其他组别的交流与比较,进一步完善代码,提高电梯效率。

6.进入电梯工程的后续步骤,开始博客的书写和代码最后时期的修改。

合作照片:

 

 

四、Information Hiding, interface design, loose coupling 的思考

1. Information Hiding:信息隐藏将程序模块化,使得每个类都似乎是一个单独的存在。在结构化中函数的概念和面向对象的封装思想都来源与信息的隐藏,因此模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序猿的私有财产,外部是不可见的。而信息隐藏原则的应用: 1 多层设计中的层与层之间加入接口层; 2 所有类与类之间都通过接口类访问;  3 类的所有数据成员都是private,所有访问都是通过访问函数实现的。

2. interface design:接口将模块的部分方法和属性一同组合起来,为了实现封装,也是上面Information Hiding的良好手段。接口控制着不同模块之间的信息传递,实现不同模块之间的相互协作,帮助信息隐藏的同时协调整个结构化的工程。因此接口设计也有许多要求:稳定性,易用性,规范性,可移植性,鲁棒性,安全性,兼容性等等。

3. loose coupling:松耦合为模块之间的依赖程度。松耦合的目标是实现模块之间的最先依赖度,在结构化工程中,模块之间的过多依赖都不利于将各模块独立起来,而且过多的牵扯会出现模块间相互导致错误的危险,一次应尽可能实现模块间代码最小化松耦合因此就必须增加抽象类和接口来实现。

 

五、Design by Contract, Code Contract

1. Design by Contract, 契约设计:

  契约式设计或者Design by Contract (DbC)是一种设计计算机软件的方法。这种方法要求软件设计者为软件组件定义正式的,精确的并且可验证的接口,这样,为传统的抽象数据类型又增加了先验条件、后验条件和不变式。这种方法的名字里用到的“契约”或者说“契约”是一种比喻,因为它和商业契约的情况有点类似。

契约设计的核心思想是对软件系统中的元素之间相互合作以及“责任”与“义务”的比喻。这种比喻从商业活动中“客户”与“供应商”达成“契约”而得来。例如: 
  1.1 供应商必须提供某种产品(责任),并且他有权期望客户已经付款(权利)。 
  1.2 客户必须付款(责任),并且有权得到产品(权利)。
  1.3 契约双方必须履行那些对所有契约都有效的责任,如法律和规定等。 
  2. 同样的,如果在面向对象程序设计中一个类的函数提供了某种功能,那么它要: 
  2.1 期望所有调用它的客户模块都保证一定的进入条件:这就是函数的先验条件—客户的义务和供应商的权利,这样它就不用去处理不满足先验条件的情况。 
  2.2 保证退出时给出特定的属性:这就是函数的后验条件—供应商的义务,显然也是客户的权利。 
  2.3 在进入时假定,并在退出时保持一些特定的属性:不变式。 

 

3.优点:

3.1获得更优秀的设计:
更系统的设计 契约式设计鼓励程序员思考诸如“例程的先验条件是什么”这样的问题,这样有助于程序员理清概念。更清楚的设计 使用者和提供者之间的权利和义务得到了共享,同时获得了清晰的描述。更简单的设计 程序的先验条件清楚地描述了使用该程序的限制,而且非法调用的结果也很清楚,所以我们鼓励程序员不要开发过于通用的程序,而要设计小巧的、目标专一的例程。

3.2提高可靠性
(1)编写契约可以帮助开发者更好地理解代码
(2)契约有助于测试(契约可以随时关闭或者启用)

3.3更出色的文档
(1)契约乃是类特性的公用视图中的固有成分
(2)契约是值得信赖的文档(运行时要检查断言,以保证制定的契约与程序的实际运行情况一致)
(3)契约是精确的规范,同时也可以作为测试的可靠指导

3.4简化调试
契约能把错误牢牢地定位

3.5支持复用
(1)出色的文档
(2)正确运用了复用代码的运行时检测

4.缺点:断言可以看做是契约式设计的一个缩影或者是一部分,因为你不可能做DBC所做的一切事情。断言不能沿着继承层次往下遗传。如果你重新定义 了某个具有合约的基类方法,实现该合约的的断言不会被正确调用(除非你再新的代码中复制他们),你必须手工调类不变项,基本的合约不会主动实现。

 

2. Code Contract,程序代码合约:

程序代码合约是.NET Framework 4.0的新功能,它是微软对契约式编程(Design by contract)概念所提出的一种解决方案,主要由前置条件(Preconditions)、后置条件(Postconditions)、与对象不变式(Object Invariants)这三大契约所构成,可以很容易的为程序代码加入验证程序代码,降低程序的错误发生率,提高程序的质量,也可以整合单元测试,减少单元测试的工作量,甚至整合文档管理器,让产出的程序文件更为详细 。

使用Code Contracts主要可让我们享有下列四项特点:
  1、提升自动测试程度
  2、静态验证
  3、执行阶段验证
  4、文件产生

六、UML

 

UML是由VS生成的,由于工程较大,图也不是很好表现出来模块之间的联系,但是大致可以看出。

七、算法

    我们的程序控制台只输出平均等待时间,由于乘客过多会导致控制台输出的前期的时刻TICKS由于信息过多流失,避免控制台输出的缓冲设置,我们将这些内容输出到log.txt中,希望助教和老师看到!!!

    我们的算法进行的优化幅度不大,但是比较符合实际情况。

    调度策略如下:总体的思想仍然是一条路走到底,但是并不在每一层都停。当有人在门外按下按钮(上/下)之后,所有顺路的电梯都会对其作出响应,最快到达者有优先承载权。然而因为每个电梯的情况不一,乘客还需要进行选择。这里乘客选择的策略和以前一样,只要电梯符合要求就上。当乘客上了电梯之后,其他之前对其响应的电梯就可以放弃这名乘客了。

    在我们的算法中,我们假设调度器是不会“预知未来”,也不会“读心术”的。也就是说:1. 在某个时候,调度器只能知道到目前为止的所有请求,而不是将未来的请求一并读入以寻求“最优时间”;2. 调度器不会知道乘客想去那一层。所以对于乘客的电梯外请求,是让乘客选电梯,而不是电梯选乘客,否则就有作弊之嫌疑。

    由于电梯事先不知道乘客要去哪个楼层,所以只能让所有可能的电梯都去迎接这名乘客。而每个人都是贪心的,不会顾全大局,也无暇去做计算(比如转两次电梯会不会更快等等),所以首先到达的符合条件的电梯,就直接上了。

    题目要求的最优平均时间,却有可能导致总时间变长。比如,我们可以忽略某个顺路请求(因为他会浪费电梯上其他人的时间),而到最后再回来接他。这样乘客等待的时间就增加了,投诉信会更多。

    我们希望算法是通用的,所以并未对题目特定的电梯情况做优化处理。

    我们设计的算法,一方面出于上面的考虑,另一方面是由于能力和时间有限,所以仅能将效率提高一点点。下面是题目自带测试样例的结果对比:

 

测试样例

Ours

TA

Passenger1

192.5

217.05

Passenger2

782.996

949.133

Passenger3

1231.804

1426.373

Passengers

127

249

Pair Project1:电梯控制程序