Json Messaging with C# Part 3: Message Handling – Obvious Code

Json Messaging with C# Part 3: Message Handling

In part one of this series on JSON Messaging in C#, I looked at building self serialising and deserialising messages.
In part two, I discussed some of the options in identifying received message types.

In this, final, post, I want to look at handling differing types of messages in a simple and scalable fashion.

In the last post, after receiving and deserialising a message, I used code such as

01
02
    public bool HandleMessage(byte[] messageBytes)
03
    {
04
        MessageTypes type = JsonMessage.GetMessageType(messageBytes);
05
        //This will not be very scalable or at least not particularly readable when 
06
        //you have many message types.
07
        switch (type)
08
        {
09
            case MessageTypes.Handshake:
10
                return HandleHandshake(HandshakeMessage.From(messageBytes));
11
            case MessageTypes.Response:
12
                return HandleResponse(ResponseMessage.From(messageBytes));
13
            default:
14
                throw new InvalidOperationException($"Type {type} not handled");
15
        }
16
    }
17

As the comment in this code states, employing large switch or, even worse, if elseif codeblocks will start looking quite awful after about 10 or so different cases. The code may be fairly regular to read, however all the extra information can make it difficult to parse quickly.

I, and indeed most programmers, have done this at some stage of their careers / hobby. It’s nothing to feel bad about, just enjoy the warm fuzzy feeling of satisfaction when you work out how to do it better, careful refactoring, in my opinion, is one of the highest pleasures of being a developer.

The code, above, will also require all the Handle methods to be added to this class. This is a path that can lead very quickly to the God Object Antipattern (cue dramatic musical sting).

The obvious answer to this problem is, of course, have you handlers elsewhere – and, respecting the Single Responsibility Principle, preferably not in a single class.

This can be done in many ways, of course, and it would be churlish of me to suggest I have, in any way, the objectively correct answer. What I do have, however, is a pattern that works for me, and I have implemented successfully on many projects, and has become standard in some of the teams I have worked with.

To start, I want build an interface for a Handler for each message. The exact signature of this will depend on your exact requirements, however it will usually look something like this:

1
2
    public interface IMessageHandler
3
    {
4
        string Tag { get; } //or, as discussed before, enum               
5
        bool HandleMessage(string json);
6
    }
7

The interface, above, has two elements, the Tag of the message and the handling method.

As discussed earlier an enum could just as usefully be used instead of a string, but here it must be the same datatype as the message it is handling.

In this case, the interface would (using the enum type MessageTypes from the last post) look like this:

1
2
    public interface IMessageHandler
3
    {
4
        MessageTypes MessageType { get; } 
5
        bool HandleMessage(string json);
6
    }
7

In the examples to follow, I will, indeed, stick to using enums.

The HandleMessage Method is returning a bool, this is intended to indicate the success or failure of the handling of a message. I have also, on occasion, built an Outcome Class to include Messages and possible Exceptions raised during handling, however for the sake of brevity, will stick to a boolean in this example.

Next I will write a routing class, a class that all messages go to be handled. Such a class could easily fall prey to if / switch explosion, as well as suffering God complexes, but I shall, hopefully, avoid this.

01
02
    public class MessageHandlers
03
    {
04
        Dictionary<MessageTypes, IMessageHandler> _handlers;
05
 
06
        public MessageHandlers()
07
        {
08
            _handlers = new Dictionary<MessageTypes, IMessageHandler>();
09
 
10
            AddHandlers();
11
        }
12
 
13
        private void AddHandlers()
14
        {
15
 
16
        }
17
    }
18

To start with I add a Dictionary to hold all the individual message handlers, keyed by the MessageType (or Tag) of the incoming message.

In the constructor of this class, I instantiate the handler Dictionary, and call a method AddHandlers.

In the AddHandlers method, we could add code like this:

01
        private void AddHandlers()
02
        {
03
            ResponseMessageHandler responseMessageHandler = new ResponseMessageHandler();
04
            _handlers[responseMessageHandler.MessageType] = responseMessageHandler;
05
 
06
            HandshakeMessageHandler handshakeMessageHandler = new HandshakeMessageHandler();
07
            _handlers[handshakeMessageHandler.MessageType] = handshakeMessageHandler;
08
 
09
            //... and so on
10
        }

This is, of course, perfectly valid, and I have done it before. It does, however, add a lot of noise to the method, much as an if else or switch block would, making it harder to parse quickly, searching for any given handler.

The parsing of code could be made simpler, by grouping the newing up code separately from the assigning to the _handlers, as below:

01
        private void AddHandlers()
02
        {
03
            ResponseMessageHandler responseMessageHandler = new ResponseMessageHandler();
04
            HandshakeMessageHandler handshakeMessageHandler = new HandshakeMessageHandler();
05
 
06
            _handlers[responseMessageHandler.MessageType] = responseMessageHandler;            
07
            _handlers[handshakeMessageHandler.MessageType] = handshakeMessageHandler;
08
 
09
            //... and so on
10
        }

This, again, is perfectly valid, and I have done it before. Doing this, however, does mean you have to add two separate lines when adding new handlers, in areas further and further apart in the code the larger it gets. It’s not a big problem, but limiting cognitive friction keeps a code base friendly.

What I now tend to do is the following:

01
        private void AddHandlers()
02
        {
03
            Add<ResponseMessageHandler>();
04
            Add<HandshakeMessageHandler>();
05
            //... and so on
06
        }
07
 
08
        void Add<T>() where T : IMessageHandler
09
        {
10
            T item = Activator.CreateInstance<T>();
11
            _handlers[item.MessageType] = item;
12
        }

Now we have and AddHandlers method that is, largely, just a list of Handler names, with the only noise the repeated word Add.

Some may complain that using Reflection is slow and wasteful, but this, in my opinion, is not a valid critique, as this code is only run when the MessageHandlers object is contructed – it is not intended to run in any loop.

In this series, I have demonstrated in building objects that simply serialise and deserialise without requiring external utilities (outside of JSON.Net, I guess), how to identify them when received, and how to build handling code that is modular and scalable.

Thanks for reading, and please feel free to leave comments, however constructive criticism is appreciated if you disagree with me.

Leave a Reply

Your email address will not be published. Required fields are marked *