OO Blog Assignment 2: Week 5-7 Homework Summary

(1) From the aspect of multi-thread coordination and synchronization control, analyze and summarize the design strategy and its changes from the three operations.

5th assignment: Multithreaded elevator

It basically copied the design strategy of the "producer-consumer" model in the courseware, and designed InputHandler as a producer thread, Scheduler as a consumer thread, and RequestQueue as a tray. Producers and consumers work concurrently to improve efficiency. At the same time, each elevator is designed as a thread, because the operation of each elevator does not interfere with each other. InputHandler and Scheduler are created by the main thread, and the three elevators are created by Scheduler, so that the scheduler can obtain the status of the elevators. But this strategy is not optimal.

6th assignment: file monitoring

This is probably the worst assignment I've ever written.

The thread-safe SafeFile class is constructed according to the courseware method. A synchronized access file state and file write method are implemented. However, for each record-type request, a separate file is created to write, which goes against the original intention of training.

Design a "monitor" thread for each request to directly view the status of the corresponding file, which is quite different from the design idea of ​​the instruction book. This makes it difficult for programs to cope with large-scale changes such as path-changed.

In general, there is no synergy between threads this time. Synchronization control is also limited to access to file state.

7th assignment: taxi dispatch

The design strategy of this assignment is basically the same as that of the fifth assignment. The input processing thread is the producer, the scheduler thread is the consumer, and the request queue is the tray. Each taxi is a thread, still created by the scheduler.

Write a thread-safe SafeFile class for outputting text files. The taxi information requested by passengers and participating in order grabbing is written by the scheduler, and the taxi running status is written by the taxi thread, which realizes thread coordination.

 

(2) Analyze your own program structure based on metrics

1) OO program code measurement

5th homework:

class name number of attributes number of methods code size main/run method scale Reviews
Elevate_5 0 1 27 17  
Elevator 14 7 176 40 The elevator control logic is complex.
Floors 2 4 24    
InputHandler 10 6 158 15 Too casually written, many properties are better suited as local variables.
Request 4   59    
 -CarryRequest 1 3      
 -FloorRequest 1 3      
RequestQueue 6 4 56    
Scheduler 7 8 209 40 The last scheduler code is preserved.
Tray 3 4 76    

6th homework:

class name number of attributes number of methods code size main/run method scale Reviews
Detail 4 3 64    
FileState 4 3 26    
InputHandler 9 6 107   similar question
Monitor 8 2 60 30  
SafeFile 2 15 110   Wrote more methods for testers
Summary 4 3 64    
TestDrive 0 1 15    
TestThread          
Trigger 3 8 94   design problem

7th homework:

class name number of attributes number of methods code size main/run method scale Reviews
_Point 2 7 40    
CHandler 9 4 76 32  
CityMap 4 4 114   Algorithm code is relatively long
FHandler 2 4 55    
Queue 3 3 49    
Request 3 3 24    
SafeFile 2 5 57    
Schedule 6 6 146 44 Scheduling method mixed with output code
Taxi 16 9 204 40 Run method with lots of output code
TestDrive 0 1 18 12  

3) Class diagram of each operation

The 5th assignment: Since the instruction book gave the reference class diagram of the last elevator, my design basically followed the instruction book. But the Tray class didn't play its due role, it just simply cached requests. A better approach is to cache the elevator status at the same time, update it when the elevator is running, and read it when the scheduler needs it.

The 6th assignment: It's very badly written, and it is suspected of "noodle code". The responsibilities of the Monitor and Trigger classes are not clear, and the code for Summary and Detail is heavily reused.

The 7th operation: Many places refer to the 5th operation (multi-thread elevator). The responsibilities of each class are relatively clear.

4) UML collaboration diagram (from top to bottom are the diagrams of the 5th, 6th, and 7th operations)

5) Design principle check (for the 7th job only)

DIP (Dependency Inversion Principle): High levels do not depend on low levels.

The program has two channels to obtain input, one is to obtain a city map through a text file, and the other is to obtain a car-hailing request through the console. My program did not abstract and generalize these two approaches, resulting in poor adaptability of the program to changes in input methods.

name:

在为类、实例变量命名时我尽可能遵循“顾名思义”,但是走向了另一个极端。我将一个记录点信息的类命名为“Point”,结果后来发现有java.awt.Point这个类,使用GUI时很不方便。无奈之下我将自己写的类改名为“_Point”,花了一部分时间改名字。在顾名思义的同时,也尽量不要取过于简单、大众化的名字,否则容易与JAVA类库重名,造成麻烦。

另外,eclipse建议包名首字母小写,类名首字母大写,作为初学者还是遵守得好。

 

(3)分析自己程序的bug

第5次作业:

所有的“正确请求测试多线程功能”样例均有错(公测未发现或是被发现bug)。

问题所在的类是Scheduler。

被发现了一个CRASH是由于想向文件写入结果,但文件已经关闭导致的。这暴露出我对于多线程同步控制尚未掌握,且自己构造的测试样例太宽松,很容易露出破绽。

从设计结构角度分析,我把所有的电梯调度方法全写入一个调度器类。Scheduler类的代码规模更是破了200行,远远超过其它类。

在总结课上,我才了解到有更加均衡的实现方式。总调度器只负责将请求分配给不同的电梯,而每部电梯对应一个专门的调度器负责排请求的执行先后顺序。这种方式显然更合适,既是遵循均衡原则,又符合实际的应用场景。

第6次作业:

对方没有进行公测,且没有发现bug,故不作分析。

第7次作业:

被发现了一个bug,为新增节点“等待状态下出租车的运行不具备随机性”。

问题所在的类为Taxi,方法为run_edge

这个bug被发现在情理之中,因为我曾经尝试过实现出租车的随机运行,但是失败了(出租车发生了瞬移)。最终改成了一版确定性运行的方法。

(4)分析自己发现别人程序bug所采用的策略

很多学生(包括我)在编写多线程程序时遇到的一个技术难点就是如何让程序正常结束(在eclipse下是在控制台上方看到<terminated>)。尽管这不是指导书的硬性要求,但是能够正常结束的程序势必带来更好的用户体验和更强的鲁棒性。如果被测者没有在readme中对程序的结束进行说明,或是说明能结束但实际上没实现的,则可以报告bug。

边界条件是在编程过程中需要着重考虑的。一些在实际情况中完全有可能出现,但编程者很难考虑到的测试点上往往容易发现bug。第7次作业我通过构造“乘客请求起始坐标正好是出租车所在位置”的样例,成功发现了别人的bug。

后期的作业不但注重程序正确性,而且对程序设计原则也提出了要求。测试者可以阅读被测代码,发现其中不符合设计要求的部分,予以扣分。

 

(5)心得体会

1)线程安全

在线程安全方面,重点是把握课上重点讲过的“生产者-消费者”模型,学会将共享对象的存取方法设置为同步化的,以及方法内部具体的写法。拿到指导书之后,在分析程序需要哪些对象、对象之间关系时,必须额外考虑哪些对象需要被共享的问题。无论是自己写被共享类的代码,还是包装为线程安全类,都要想清楚哪些方法需要保证原子性,并使用synchronized关键字。

2)设计原则

从第7讲开始,课后作业将程序设计原则也纳入了作业要求和互评范围。设计原则与程序的正确性没有直接的关系,而是为了让程序具有较好的可读性、可扩展性。在软件开发行业,用户需求发生变更是经常遇到的事件。遵循课上讲过的一些设计原则可以增强程序的可扩展性。在需求变更时,只需要对原有程序进行有限的修改,而不是推倒重来。自己在3次电梯作业中,后面的作业往往不能有效利用前面作业的代码,原因在于自己没有在一开始构造一个良好的设计,没有遵循设计原则。另一些原则是为了程序可读性,因为将来我们开发的程序只是一个大项目的一部分。不但要保证别人放心调用,而且最好在代码中清楚写出自己的逻辑。可能经过后面几次作业的训练,我能够更深入地理解设计原则。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325200685&siteId=291194637
Recommended