第一次Blog作业:题目集5~7总结性Blog
一、前言
知识点总结:第五次题目集前四道题主要是对C语言写过的程序进行java重构,着重于恢复学生的编程能力,涉及正则表达式的运用,数学知识的运用以及处理错误的能力,第五道电梯题目考察算法以及逻辑分析能力,由于是第一次电梯题目,所以对类的要求不太严格,只需要一个类即可。第六次题目集主要考察类设计的能力,第三题是对上一次题目集电梯题目的第一次迭代,要考虑单一职责原则,将代码从一个类重构为多个类,比较考验逻辑分析能力,第七次题目集考察了蒙特卡洛仿真方法的简单使用,第三题是对电梯题目的进一步迭代,对类设计的要求相对上一次有所改变,要求也更加严格,在处理外部请求时需将目的楼层添加到内部请求中,对输出的要求也有所改变。
题量及难度分析:这三次题目集的题量都不是很多,少的只有三道题多的也只有五道题,老师所给的时间也非常充裕,除了每次题目集的最后一道电梯题以外其余题目都相对较为简单,最后一道电梯题目对于逻辑分析能力的要求较高,所以具有较高的难度,在第五次题目集第一次电梯题时需要花费较多时间去理解电梯的运行规律,到达每层楼时的处理要弄明白,之后的题目集再对第一次的电梯题目进行重构分析,不断优化自己代码,使用要求的类将代码拆分重写。
二、设计与分析
关于电梯题目的分析
第五次题目集中的电梯题目
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
点击查看输入输出样例
输入样例:
在这里给出一组输入。例如:
1
20
<3,UP>
<5>
<6,DOWN>
<7>
<3>
end
输出样例:
在这里给出相应的输出。例如:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
类图

类的设计分析
主要分为主类和电梯类两个类,此外还有一个关于方向的枚举。
主类运用正则表达式对输入做了处理,根据有无逗号将请求分为内部请求和外部请求,同时对输入的格式进行了要求。
电梯类的属性有最大、最小以及当前楼层数,方向,状态以及内部请求的队列,外部向上和向下请求的队列。方法包括内部请求和外部请求的入队出队方法,电梯的向上向下移动方法,是否停止的方法。开门关门方法,判断是否有向上或向下请求的方法,电梯运行方法等。
SourceMonitor的分析
点击查看分析
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory D:\作业\Java\
Project Name Elevator1
Checkpoint Name Elevator1
File Name Elevator1.java
Lines 224
Statements 156
Percent Branch Statements 25.6
Method Call Statements 69
Percent Lines with Comments 0.0
Classes and Interfaces 3
Methods per Class 7.00
Average Statements per Method 5.86
Line Number of Most Complex Method 8
Name of Most Complex Method Main.main()
Maximum Complexity 10*
Line Number of Deepest Block 30
Maximum Block Depth 5
Average Block Depth 3.15
Average Complexity 3.19*
--------------------------------------------------------------------------------------------
Most Complex Methods in 2 Class(es): Complexity, Statements, Max Depth, Calls
Elevator.addInRequest() 2*, 2, 4, 2
Elevator.addOutDownRequest() 2*, 2, 4, 2
Elevator.addOutUpRequest() 2*, 2, 4, 2
Elevator.closeDoor() 1*, 2, 3, 1
Elevator.Elevator() 1*, 8, 3, 0
Elevator.getCurrentFloor() 1*, 1, 3, 0
Elevator.getMaximumNumberOfFloors() 1*, 1, 3, 0
Elevator.getMinimumNumberOfFloors() 1*, 1, 3, 0
Elevator.handleRequests() 7*, 12, 5, 13
Elevator.hasDownRequests() 5*, 7, 5, 1
Elevator.hasUpRequests() 5*, 7, 5, 1
Elevator.isValidFloor() 2*, 1, 3, 0
Elevator.moveDown() 6*, 12, 5, 7
Elevator.moveUp() 6*, 13, 5, 8
Elevator.openDoor() 1*, 2, 3, 1
Elevator.run() 5*, 10, 5, 4
Elevator.setCurrentFloor() 1*, 1, 3, 0
Elevator.setMaximumNumberOfFloors() 1*, 1, 3, 0
Elevator.setMinimumNumberOfFloors() 1*, 1, 3, 0
Elevator.shouldStop() 6*, 6, 4, 4
Main.main() 10*, 31, 5, 23

分析与心得
1.代码存在的问题
分支语句占比25.6%,说明我的代码逻辑较为复杂,不够简洁,存在较多条件判断等分支语句,在维护和调试时需格外关注不同分支的执行情况才可以,其中main方法复杂度过高,为10*,使得代码的可维护性和可读性较低。此外,由于没有写注释的习惯导致我的代码可读性过低,可能过一段时间后自己也看不懂了。代码块的最大深度为5,有一些嵌套结构可能不是必需的,可能会导致逻辑存在错误。
2.心得
后续我会逐渐养成写注释的习惯,增加代码的可读性,同时,也会尽量减少不必要的分支语句的使用,简化自己的逻辑,严格遵循单一职责原则。
第六次题目集中的电梯题目
题目要求:对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。
电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行。
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>。
类图

类的设计分析
主要分为主类、电梯类、乘客请求类、队列类以及控制类,此外还有一个关于状态的枚举和一个关于方向的枚举。
主类:与第五次题目集一样运用了正则表达式对输入进行处理,但是对出现多个连续的相同请求进行了处理,忽略相同的多余请求,避免了非法的输入。
电梯类:与上次题目相比遵循了单一职责原则,将不应该存在于该类中的方法和属性,例如乘客的请求处理以及队列改写到新增的其他几个类中,对请求楼层数是否有误进行了判断,保证了数据的安全性。
乘客请求类:用于表示外部电梯请求,仅包含外部请求的楼层和方向两个属性,以及对应的获取属性的方法,便于理解。
队列类:使用LinkedList来管理电梯的请求队列,提供了获取和设置请求队列的方法,以及内部请求和外部请求的入队方法。
控制类:协调电梯类和队列类的交互,包括确定电梯运行方法,计算下一个目标楼层,控制电梯移动,判断是否停靠,开关门以及移除已经处理过的请求等方法。
SourceMonitor的分析
点击查看分析
Metrics Details For File 'Elevator2.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory D:\作业\Java\
Project Name Elevator2
Checkpoint Name Elevator2
File Name Elevator2.java
Lines 345*
Statements 225
Percent Branch Statements 26.7
Method Call Statements 111
Percent Lines with Comments 0.0
Classes and Interfaces 7
Methods per Class 5.71
Average Statements per Method 4.10
Line Number of Most Complex Method 253
Name of Most Complex Method Controller.getNextFloor()
Maximum Complexity 21*
Line Number of Deepest Block 260
Maximum Block Depth 6
Average Block Depth 2.37
Average Complexity 2.92*
--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es): Complexity, Statements, Max Depth, Calls
Controller.closeDoor() 1*, 1, 2, 1
Controller.Controller() 1*, 2, 2, 0
Controller.Controller() 1*, 0, 0, 0
Controller.determineDirection() 12*, 19, 5, 9
Controller.getClosest() 8*, 11, 4, 4
Controller.getElevator() 1*, 1, 2, 0
Controller.getNextFloor() 21*, 21, 6, 19
Controller.getQueue() 1*, 1, 2, 0
Controller.move() 5*, 8, 4, 7
Controller.openDoors() 1*, 1, 2, 1
Controller.processRequests() 11*, 19, 5, 18
Controller.removeRequests() 5*, 8, 3, 11
Controller.setElevator() 1*, 1, 2, 0
Controller.setQueue() 1*, 1, 2, 0
Controller.shouldStop() 8*, 6, 4, 8
Elevator.Elevator() 1*, 5, 2, 0
Elevator.Elevator() 1*, 0, 0, 0
Elevator.getCurrentFloor() 1*, 1, 2, 0
Elevator.getDirection() 1*, 1, 2, 0
Elevator.getElevatorInstance() 1*, 1, 2, 0
Elevator.getMaxFloor() 1*, 1, 2, 0
Elevator.getMinFloor() 1*, 1, 2, 0
Elevator.getState() 1*, 1, 2, 0
Elevator.isValidFloor() 3*, 3, 3, 0
Elevator.setCurrentFloor() 1*, 1, 2, 0
Elevator.setDirection() 1*, 1, 2, 0
Elevator.setState() 1*, 1, 2, 0
ExternalRequest.ExternalRequest() 1*, 2, 2, 0
ExternalRequest.ExternalRequest() 1*, 0, 0, 0
ExternalRequest.getDirection() 1*, 1, 2, 0
ExternalRequest.getFloor() 1*, 1, 2, 0
Main.main() 11*, 33, 5, 27
RequestQueue.addExternalRequest() 2*, 3, 3, 2
RequestQueue.addInternalRequest() 2*, 2, 3, 2
RequestQueue.getExternalRequests() 1*, 1, 2, 0
RequestQueue.getInternalRequests() 1*, 1, 2, 0
RequestQueue.getQueueInstance() 1*, 1, 2, 0
RequestQueue.RequestQueue() 1*, 0, 0, 0
RequestQueue.setExternalRequests() 1*, 1, 2, 0
RequestQueue.setInternalRequests() 1*, 1, 2, 0

分析与心得
1.代码存在的问题
分支语句占比达26.7%,代码中存在大量条件判断逻辑使得代码复杂度明显提高,容易存在逻辑错误的问题,与上一次相比,同样存在缺乏注释的问题,最复杂方法控制类的getNextFloor方法,复杂度高达21*,其中包含了过多的条件语句,极容易存在逻辑错误导致运行不出来的问题,最大代码块深度为6,同样说明我的代码存在较深的嵌套结构。
2.心得
养成写注释的习惯,增加代码的可读性,注意if-else条件语句的使用避免代码过于复杂,提高代码的可维护性。
第七次题目集中的电梯题目
题目要求:对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类。
电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>。
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)。
类图

类的设计分析
主要分为主类,电梯类,控制类,队列类,乘客类,此外还有一个关于状态的枚举和一个关于方向的枚举。与上一次题目集相比,将乘客请求类改为了乘客类,严格遵循单一职责原则。其中主类,电梯类和队列类与上一次题目集基本一致,没有额外修改。
控制类:与上一次题目集相比略有修改,增加了返回两个楼层中距离电梯当前楼层较近的楼层的方法和处理请求的方法,对请求的移除处理有所修改,将已处理过的外部请求的目标楼层转换为了内部请求,其他方法大致不变,逻辑稍有修改。
乘客类:包含乘客的起始楼层和目标楼层,以及根据起始楼层和目标楼层确定乘客的移动方向的方法。
SourceMonitor的分析
点击查看分析
Metrics Details For File 'Elevator3.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory D:\作业\Java\
Project Name Elevator3
Checkpoint Name Elevator3
File Name Elevator3.java
Lines 342*
Statements 226
Percent Branch Statements 26.1
Method Call Statements 110
Percent Lines with Comments 0.0
Classes and Interfaces 7
Methods per Class 6.14
Average Statements per Method 3.79
Line Number of Most Complex Method 209
Name of Most Complex Method Controller.getNextFloor()
Maximum Complexity 23*
Line Number of Deepest Block 223
Maximum Block Depth 7
Average Block Depth 2.36
Average Complexity 2.81*
--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es): Complexity, Statements, Max Depth, Calls
Controller.Controller() 1*, 2, 2, 0
Controller.Controller() 1*, 0, 0, 0
Controller.determineDirection() 16*, 19, 4, 16
Controller.getClosest() 8*, 11, 4, 4
Controller.getElevator() 1*, 1, 2, 0
Controller.getNextFloor() 23*, 22, 7, 23
Controller.getQueue() 1*, 1, 2, 0
Controller.move() 5*, 8, 4, 7
Controller.openDoors() 1*, 1, 2, 1
Controller.processRequests() 8*, 14, 4, 16
Controller.removeRequests() 6*, 13, 4, 12
Controller.setElevator() 1*, 1, 2, 0
Controller.setQueue() 1*, 1, 2, 0
Controller.shouldStop() 6*, 7, 4, 6
Elevator.Elevator() 1*, 5, 2, 0
Elevator.Elevator() 1*, 0, 0, 0
Elevator.getCurrentFloor() 1*, 1, 2, 0
Elevator.getDirection() 1*, 1, 2, 0
Elevator.getElevatorInstance() 1*, 1, 2, 0
Elevator.getMaxFloor() 1*, 1, 2, 0
Elevator.getMinFloor() 1*, 1, 2, 0
Elevator.getState() 1*, 1, 2, 0
Elevator.isValidFloor() 3*, 3, 3, 0
Elevator.setCurrentFloor() 1*, 1, 2, 0
Elevator.setDirection() 1*, 1, 2, 0
Elevator.setState() 1*, 1, 2, 0
Main.main() 8*, 25, 5, 21
Passenger.getDestinationFloor() 1*, 1, 2, 0
Passenger.getDirection() 5*, 6, 4, 0
Passenger.getSourceFloor() 1*, 1, 2, 0
Passenger.Passenger() 1*, 1, 2, 0
Passenger.Passenger() 1*, 2, 2, 0
Passenger.Passenger() 1*, 0, 0, 0
Passenger.setDestinationFloor() 1*, 1, 2, 0
Passenger.setSourceFloor() 1*, 1, 2, 0
RequestQueue.addExternalRequest() 1*, 1, 2, 1
RequestQueue.addInternalRequest() 1*, 1, 2, 1
RequestQueue.getExternalRequests() 1*, 1, 2, 0
RequestQueue.getInternalRequests() 1*, 1, 2, 0
RequestQueue.getQueueInstance() 1*, 1, 2, 0
RequestQueue.RequestQueue() 1*, 0, 0, 0
RequestQueue.setExternalRequests() 1*, 1, 2, 0
RequestQueue.setInternalRequests() 1*, 1, 2, 0

分析与心得
1.代码存在的问题
分支语句占比达26.1%,说明代码中存在大量条件判断逻辑导致代码逻辑复杂,增加理解和调试难度,同样缺乏注释使我的代码可读性极差,最复杂的方法是Controller类的getNextFloor方法,Maximum Complexity为23,方法内包含大量的条件判断、循环嵌套、逻辑分支,导致代码逻辑错综复杂,难以理解和测试。
2.心得
养成写注释的习惯,增加代码的可读性,注意if-else条件语句的使用避免代码过于复杂,提高代码的可维护性,在一些多层嵌套的循环中,如果满足某个条件就可以直接结束循环或者进入下一轮循环,可以提前进行判断并返回,避免不必要的内层循环执行。
三、踩坑心得
由于之前没有接触过怎么难的题导致一开始我看到题时是有点懵的,根本不知道如何下手,并且由于畏难心理一度产生了想放弃的想法,但是在老师将思路发给我们以后,我开始慢慢尝试,虽然最后我依旧没有将题目做出来,但是在尝试的过程中我也有了很多的收获,同时也踩了不少的坑。
1.
由于一开始没有理解题目是将第一个匹配到的请求清除使得内部请求3被提前清除导致最后电梯停在了6楼没有正确下到3楼,到达某个楼层时应该只看内部请求的首个请求是否楼层相符,而不应该根据是否包含该楼层数来清除内部请求。
错误代码

修改后的正确代码

2.没有大局意识,太过于关注一些无伤大雅的细节,对于最后关门后是否有空行太过于关注,明明答案并不需要将空行处理但是我却在此纠结,之后会尽量培养我的大局意识,不在一些无用的细节上花费大量时间。

3.开始写代码前没有认真理清楚思路,对需求没有进行仔细分析,一拿到题目就开始写代码,导致写了一些根本没有用到的无效方法,甚至一开始根本没有意识到,还是在答案不正确后重新整理思路的时候才发现一些没有用到的方法,在之后练习时我会先理清楚自己的思路,对需求进行仔细分析,在编写一些方法时仔细思考是否是有用的代码,不做无用功。
4.代码过于复杂,一些方法包含了太多的if-else语句和循环语句增加了代码的复杂度,甚至导致代码的逻辑出现错误,同时也不利于理解和代码的维护,同时由于自己没有写注释的习惯,在后续对代码的迭代重构时甚至自己都不理解自己之前的思路,在之后的练习中会尽量减少条件语句和循环语句的使用,养成写注释的习惯。
以下为包含过多if-else语句和循环语句的代码:

四.改进建议
1.注释方面
养成写注释的习惯,增加注释占比,以此来增加代码的可读性,既可以帮助自己在一段时间后仍可以理解自己的代码,与此同时,可以帮助他人看懂自己的代码,以此帮助自己优化代码。例如:在电梯题目的Controller类的getNextFloor方法中可以避免过多的if-else语句连自己都看不懂的情况发生。
2.分支语句方面
尽量减少分支语句和循环语句的使用,降低代码的复杂度,避免由于过多此类语句导致逻辑发生错误,增加代码的可维护性。例如:重构电梯题目的Controller类的getNextFloor方法,减少if-else的使用。
3.单一职责原则方面
严格遵循单一职责原则,将第一次电梯题目的电梯类进行改写,不要把所有方法都放在这一个类中,还有就是之后两次题目的一些方法的职责也过多,改写代码将方法改写成多个小方法。
4.需求分析方面
要重视需求分析,拿到题目后先对需求进行仔细分析,不要一上来就开始敲代码,这样可能会导致存在一些无用方法,需求分析往往是最重要的。
五.总结
1.知识收获
通过这一阶段的学习,从最初的只使用一个电梯类编写代码到使用电梯类,控制类等多个类实现编程,我对单一职责原则有了更深的体会,明白类设计对编程的重要性。从一开始拿到题目就开始敲代码到认真分析题目思路后再开始编程,我明白需求分析对编程的重要性,避免了一些无用方法的出现。对数据输入是否合法的处理让我对正则表达式的运用有了更好地理解。三次电梯难题锻炼了我的逻辑思维能力,我学会将实际问题通过编程来逐步实现,对于编程有了更深的理解。我明白软件工程这个学科不只是编程,还要进行需求分析,将实际问题拆解为可实现的代码逻辑。
2.心态锻炼
最初面对电梯难题时,我十分迷茫和不知所措,根本不知道如何下手,并且由于畏难心理一度产生了想放弃的想法,但是正是我的坚持锻炼了我的心态,即使最终没有通过测试点,但是在这个过程中,每一次的运行结果与预期结果逐渐相似的过程中,我的自信心逐渐增强,即使面对一次又一次的失败,我也毫不畏惧,我的内心也逐渐强大。我明白编程的过程中面对难题是不可避免的,但是我们只要勇于尝试,就可以不断突破自己。
3.进一步学习和研究
对于条件语句和循环语句使用的减少方面,我还要不断学习和研究,学会运用其他方法来代替它,努力研究提高代码的可维护性,可复用性和可扩展性,使代码更容易理解,增强我的逻辑能力。同时,我还要进一步调高自己调试代码的能力,努力通过不断调试使得代码进一步完善。

浙公网安备 33010602011771号