A Chat Utility
The Chat application is an instant messaging utility that supports one-to-one chat sessions, private conferences and public chat rooms.
Inq is not an object oriented language. Instead, it uses the construct known as a typedef to model application entities. Part of application design will be to arrive at a set of typedefs, their relationships and life-cycle. In this way, typedefs lend themselves to Entity-Relationship modelling.
The Chat utility is straightforward enough to require only four typedefs, which together with their relationships are depicted below:
We give each one a brief explanation here and come back to them in more detail when discussing the server-side fuctionality.
The OnLine typedef models a user logged into the chat system and that may take part in a chat session represented by a ChatChannel.
An OnLine instance is created when the user signs into the chat system and destroyed when he leaves.
The ChatChannel typedef models chat session - a conversation that any number of users (represented by their OnLine instance) may take part in.
A ChatChannel whose IsPublic field is false represents a one-to-one conversation or a private conference (when IsConference is true). The PartyCount field is the number of OnLine instances taking part in the conversation and BackChatCount is the number of messages retained for replay when a user joins the channel.
Instances whose IsPublic field is true are public chat rooms that are (other than by management functions not implemented) never destroyed. Private channels are destroyed when the last correspondent leaves.
Within the chat system of course, many users can take part in many conversations. A many-to-many relationship such as this is often modelled using an entity to resolve it into two one-to-many relationships. The ChannelParticipant typedef performs this function and gives us a place to support additional useful fields.
- As we see later, in a one-to-one conversation the calling party creates the ChatChannel and a ChannelParticipant instance to represent himself in it. At this point the caller knows who he wants to call but the called party is only joined into in the conversation when the caller sends the first message. The ChannelParticipant.OtherUser field holds the OnLine.OnLine field of the called party for use when this takes place.
- The DisplayName field is used by the client GUI to identify the conversation to the user. In one-to-one conversations this is different for the two users. In the windows shown here, Alice and Bob are chatting to one another. Bob's window is top-left and Alice's is bottom-right. The conversation is represented by a single instance of ChatChannel but is known as Alice to Bob and vice-versa. We can support this by modelling the channel's display name in the ChannelParticipant typedef.
Instances are created and destroyed as participants join and leave a channel.
The BackChat typedef models a message sent to a ChatChannel. When the Client sends message text a prototype instance is created by calling the new() function and the other fields filled in. If the channel uses BackChat (that is ChatChannel.BackChatCount is greater than zero) only then is it created to become a managed instance, discussed in the section on typedefs.
When a new BackChat instance is created ChatChannel.BackChatCount is checked to see if the oldest available should be destroyed.
The Node Space
When designing Inq applications consideration is given to the node structures required to support its function. This happens at a number of levels:
- A set of typedef instances is built using read(), aggregate() and possibly groupby(). These structures can be considered similar to Object Composition however in Inq they are built at run time. While consideration of what these structures will be takes place during the modelling phase as the relationships between the entities are established, structures are built for a particular functional purpose as and when required.
- At a higher level, applications often comprise larger functional units (each hosting their required structures). Inq terms such a unit a context and the node space it manages is rooted at its context node. The emergence of what constitutes a context is often driven by the client GUI, since this is where the path from the application's root node to a context is defined. This topic is discussed in the GUI Basics section.
- What, if any, interaction there is between contexts. Script execution can switch between one context and another with the use of a func variable. We will return to this topic later in the example.
Considering these points, in the chat utility we have the following requirements:
- A context that represents a given conversation;
- A super-context of the above that represents all conversations.
Within 1. above we decide to build a structure containing:
- The ChatChannel instance
- The ChannelParticipant instance representing us in the channel;
- The list of ChannelParticipant instances representing us and everyone else in the channel;
These considerations give rise the node structure shown here:
This structure exists in both the Server and Client, however some nodes on the Client side represent the GUI items depicted. GUI construction and establishing context nodes shown here bolded, is covered shortly.