/ Papers / The Messaging System in RCOS.java |
Outline of C++ system.
The conversion to Java lead to a very procedural based solution. This was due to it being derived from the C++ system and the lack of knowledge in how to produce object orientated based system.
Initially any object that implemented "SimpleMessageHandler" would register to a given post office. The job of the post office was to record the registered objects and send the messages to the registered objects.
The system relied upon the base object type "Message". This object contained a Source, Destination, Type and Body. The first three were strings and the body an Object. The post office object would use the destination to parse the send object to the appropriate registered object. The type attributed would be used by the receiving object to determine whether it handled it or not. The body was used to store any primitive (in their object form) or complex data types.
The system relied upon the following common methods:
SendMessage(Message) - The message is sent to the Post Office.
ReceiveMessage(Message) - Checks to determine whether the object is
valid and passes it (if okay) to ProcessMessage.
ProcessMessage(Message) - In a series of if-then-else statements it
checks to see what type the message and proceeds to do some action if it
matches.
The benefits of this pattern are:
1/ Reduction in the amount of code by removing many long and complicated
if-then-else statements. The determining factor of whether an object
processes a message is not based on arbitrary conditions.
2/ Coherence within a particular message object. The code for
each message is contained inside the appropriate message.
3/ Complicated objects or primitive data types can be used inside the
object without casting or creating ad hoc external objects.
4/ New messages do not require new code to be added to handle the message;
rather the message is modified instead.
5/ The determining factor of whether a message was handled was based
on arbitrary conditions.
6/ Increased encapsulation of data and implementation hiding.
When the visitor pattern was implemented a simplified the process message to a few lines of code for each receiver. The message object interface to outside code became well defined, attributes were kept encapsulated and access was allowed via methods.
Related to the MVC Pattern is double dispatch.
Now there are adapters of the abstract classes. Each abstract
class contains a “doMessage” for each possible receiving class. The
adapter class implements the respective abstract class with empty methods.
Each message then extends the adapter class and overrides only the necessary
methods.
Each command in the RCOS.java system is decoupled i.e. the button pressed invokes a messaging object that performs the task rather than performing the task directly. This enables object performing the task to save any relevant information before executing so that it may be undone at any time. Meanwhile a listener object records all of the operations that have occurred.
In RCOS you have a Message Object:
doMessage(receiver type) – stores state and carries out some operation
based on receiver type.
undoMessage(receiver type) – undoes operation based on receiver type.
boolean undoableMessage(receiver type) – returns true of false if message
can or can't be undone.
Post Office Object:
Vector vMessages – Vector of messages which can be undone.
sendMessage() – sends message to all Post Offices.
localSendMessage() – sends message to local objects listening.
undoMessage() – sends an undo message to all listeners.
This is implemented to ensure that:
By design RCOS.java has a large hierarchy of class files. The Animator package is split by operating system components i.e. Animator.CPU, Animator.Disk, etc.
Operating system, animators and universal sections divide the messaging
system. The operating system and animation sub-systems have their
own post office designed to send message to each other and to registered
components within the designated area.
Reduction in and elimination of overlapping the usage of the messages. By clearly defining who receives the message and what it contains the removal of several unneeded messages (due to overlapping with other messages) could occur. There was also the case where objects (especially animators) would determine which object was sending the message to determine whether they should process the message or not. This indicated that there were messages that were being used for two or more purposes. These were also eliminated.
Ownership of messages is easier for two reasons:
Objects are not cast when received. The default messaging object had only one message contents object (Object) that was then cast to the required type e.g. Integer, RCOS defined object like RCOSProcess, etc. Instead each object contains the required content type. No casting is needed.
The removal of the code blocks within the series of if-then-else and
moving them to separate methods led to a greater formalisation of what
each object within the system was to perform. Also, the appearance
of common methods and data structures lead to the improvement of code reuse.
Similar sections of code that were used to process two or three messages
were converted into methods for reuse. Where appropriate these were
made publicly or privately accessible.
Implementing of the Visitor pattern to other areas of RCOS.java.
Such as the CPU and Kernel.