Home Blog All Benefits of a Message Manager
November 17, 2023
215
11 minutes of reading

Benefits of a Message Manager

You have a large and successful project that is constantly growing and developing. But appearance and ease of use do not in any way show what such a necessary product consists of. And only developers understand the full depth of the Mariana Trench. What do I mean by this? Let's go in order.

What does a program written using OOP consist of? Of course from classes. Each class is responsible for its own functionality (ideally), which it should implement. And naturally, classes must interact with each other, exchanging data or using the functionality of another class. And this interaction is the architecture of the application.

It would seem that everyone understands these elementary and basic things. But building good architecture in practice is not easy. And there are no ideal architectures, at least I haven’t come across them yet.

How to understand whether architecture is good or not? It's simple. If you add new functionality to a project without any problems and you don’t have to change the logic of class interaction, the architecture is good. And vice versa. The more changes you make to the interaction of classes, the worse the architecture.

What is the result? If the architecture is bad, then the developer has to do more work, implementing not only new functionality, but also editing the application framework. As a result, additional errors, debugging changes and many other bad things.

So how do you make good architecture? The universal tool for this is experience and knowledge. The first depends only on you, but I will try to tell a small part of the second below, based on my experience.

Our company uses a message manager on a project. And using the most basic principles: one class - one functionality, one method - one action, plus a message manager, we can, roughly speaking, add new functionality and expand the project without much effort. Naturally, there are exceptions, since the project is not small. However, using a message manager simplifies the architecture so much that these issues are reduced by orders of magnitude. This is what I want to tell you about the message manager.

What is a message manager?

Now I will describe things that most programmers should know. In principle, the title itself already contains the answer to this question. This is the dispatcher that distributes messages. This component is built on the Mediator pattern. The task of this intermediary is to transfer the message from the sender to the recipient. Both in words and in the diagram everything looks very simple.

Well, a reasonable question arises: how can this simplify the architecture? It's simple. When using a message manager, classes do not need to know about each other. The classes only need to know about the dispatcher itself and the message that those classes can operate on. This allows you to simplify the interaction of classes with each other and, as a result, simplify the application architecture. I'll try to explain in more detail.

Bold plus of the message manager.

The main advantage of the message manager is its purpose, i.e. that's why it was invented. As I wrote earlier, its main task is to remove the dependencies of objects from each other. Using the message manager we don't need references to the recipient in the sender. All the sender and recipient need to know is the specific message format.

So what exactly can we improve with the message manager? The very first thing that comes to mind is events. Let's say we have the following event:

public class A
{
    public Action<object> OnDoIt;
}

And we subscribe to it.

public class B
{
    public void Init(A a)
    {
        a.OnDoIt += DoIt;
    }
}

And we need to immediately write this:

public class B
{
    ...
    public void Deinit()
    {
        a.OnDoIt -= DoIt
    }
}

As you all, I hope, know, if you do not unsubscribe from an event, the signed object will not be deleted from memory. The consequences also, I suspect, you understand. And if you think that this is nonsense and not a problem, then I will say this. I have come across a situation many times when they forgot to unsubscribe and, moreover, the subscription was copied and pasted and they forgot to correct plus to minus. The result was hilarious.

So how can a message manager help here? First, class B does not need to know about class A. Therefore, we will not bind one to the other, and if class A is no longer needed, the garbage collector will delete it without problems. All we need is to agree on a message format that class A can send and class B can receive and process.

This begs the question, how does the message manager know that class A is sending a message to class B? Well, that’s why he’s a dispatcher so he knows. I will not describe the insides of the message manager here. This is the topic of a separate article. However, a simplified scheme of work looks like this.

Class A must have a link to the message manager. And class B must subscribe in the dispatcher to the message it needs. And when class A sends a message to the dispatcher, the dispatcher forwards this message to class B, which is subscribed to this message. And here you can say: “So, what’s the difference? Both there and there a link is needed. Both there and there you need to subscribe. And the classes will be dependent on the message manager." It seems logical, but there is a nuance.

If you implement the message manager correctly, the garbage collector can easily remove the signed class when it is no longer needed. Even if we forget to unsubscribe the class. Next, classes only need one link, and that is the link to the message manager. Classes do not need to know about each other.

Let's compare. Let's say we have three classes A, B, C. Classes B and C should respond to an event in class A. And class C should respond to an event in class B.

public class A
{
    public Action<object> EventInA;
}


public class B
{
    public Action<object> EventInB;

    public void Init(A a)
    {
        a.EventInA += ProcessA;
    }

    public void Deinit()
    {
        a.EventInA -= ProcessA;
    }

    private void ProcessA(object messageA)
    {
        ...
    }
}


public class C
{
    public void Init(A a, B b)
    {
        a.EventInA += ProcessA;
        b.EventInB += ProcessB;
    }

    public void Deinit()
    {
        a.EventInA -= ProcessA;
        b.EventInB -= ProcessB;
    }

    private void ProcessA(object messageA)
    {
        ...
    }

    private void ProcessB(object messageB)
    {
        ...
    }
}

As you can see, as before, in order to process class events, we need a reference to an object of this class. And for class C we need A and B. What if there are a couple dozen such classes. Don't you think it's real? Here's a simple example.

Vehicle driving program. When a car is driving, various events occur: a turn to the left, the gas pedal is pressed, fifth gear is engaged, the brake is pressed, etc. How many events do you think will happen when the car moves? Clearly more than two dozen. And there is a class that reacts to all these events, processes and writes them to the database. It turns out he must subscribe to all these events. And what will this subscription look like?

Now let's look at the message manager example.

public class MessageDispatcher
{
}


public class A
{
    public void Init(MessageDispatcher md)
    {
    }

    public void ProcessA()
    {
        md.SendMessage(messageA);
    }
}


public class B : IMessageClient
{
    public void Init(MessageDispatcher md)
    {
        md.Subscribe(MessageA, this);
    }

    public void ProcessMessage(IMessage msg)
    {
        // Обработка сообщений
    }

    public void ProcessB()
    {
        md.SendMessage(messageB);
    }
}


public class C : IMessageClient
{
    public void Init(MessageDispatcher md)
    {
        md.Subscribe(MessageA, this);
        md.Subscribe(MessageB, this);
    }

    public void ProcessMessage(IMessage msg)
    {
        // Обработка сообщений
    }
}

Beauty? All we need is a link to the message manager. We can subscribe to hundreds of messages from other classes without knowing anything about them.

Let's look at another example where a message manager can be useful. There is a class A, which has a class B that performs processing of certain data. And the functionality of this processing needs to be called in class C. How it will look in the classic version. We will need to either delegate the call to the processing method of class B from class A, or return a reference to class B. Let's take the first option.

public class A
{
    private B b;

    public void Init()
    {
        b = new B();
    }

    public void ProcessB(MessageC messageC)
    {
        b.ProcessB(messageC)
    }
}


public class B
{
    public void ProcessB(MessageC)
    {
        // Обрабатываем данные
    }
}


public class C
{
    public void Init(A a)
    {
    }

    public void ProcessC()
    {
        a.ProcessB(messageC);
    }
}

As you can see, we again need links to classes that implement the desired functionality. Plus additional code on delegation. What if these classes are in different libraries and they shouldn’t know about each other? Then we will have to create interfaces. More additional code.

But what will it look like with the message manager?

public class MessageDispatcher
{
}


public class A
{
    private B b;

    public void Init()
    {
        b = new B();
    }
}


public class B : IMessageClient
{
    public void Init(MessageDispatcher md)
    {
        md.Subscribe(MessageC, this);
    }

    public void ProcessMessage(IMessage msg)
    {
        // Обработка сообщения
    }
}


public class C
{
    public void Init(MessageDispatcher md)
    {
    }

    public void ProcessC()
    {
        md.SendMessage(messageC);
    }
}

And again beauty. The classes are independent of each other. They don't know about each other at all.

So what do we end up with?

I gave small examples of how standard implementations can be replaced with the Mediator pattern, which is implemented by the message manager.

As I wrote at the beginning, our company uses a message manager on a project. The project uses a plugin system and has functionality for restarting plugins. Roughly speaking, when restarting, all plugins must be deleted and created again. And since our plugin classes are not bound to other classes by events and strong links, they are deleted by the garbage collector without problems. Which does not lead to memory leaks. We have established this through repeated tests. And this moment allows further development and maintenance of the project without regard to the problem of memory loss.

If we take our message manager specifically, it gives additional flexibility in message processing. For example, we can process messages one by one asynchronously in a separate thread or synchronously in the current thread. We can also set priorities for message handlers, i.e. indicate which of the handlers will process this message first, which second, etc. After processing a message, we can interrupt its further processing so as not to waste time calling other handlers registered to process this message. The ability to return the results of message processing has also been implemented.

Simply put, you can create a message dispatcher with the functionality you need, which will be more convenient and flexible than regular events.

For me personally, using the message manager brings me a kind of pleasure. It simplifies a lot of things, including labor costs.

Minuses?

Every medal has two sides. Firstly, to use the message manager, you need to tune your brain to this logic. For some, this may seem difficult, but when a dispatcher’s work scheme is formed in your head, this minus will immediately turn into a plus. You immediately realize the simplicity and ease. Those. This is a minus, let's say, for beginners.

Also, quite often there is a need for extra code for additional message processing.

What else? When debugging, it is not possible to go line by line and track the sending and receiving of a message in a simple way. Debugging in the forehead will not work.

There may be other disadvantages that I forgot, but I will say this. For me, the pros outweigh the cons of using a message manager. If your situation is different, then this pattern is not suitable for your project and you need to use something else.

Why did I write all this?

It's simple. I wanted to share my experience using the message manager. Perhaps someone will discover the message manager or look at it from a different angle and will also have fun in development using this useful thing.

All the best and good luck.

BitHide Team

Rating of this article

1 voice. Rating 5 / 5
  1. 5
  2. 4
  3. 3
  4. 2
  5. 1

Page Contents

Top articles

November 14, 2023
Articles
How to accept crypto for your business
Feeling lost about introducing crypto processing to your business model? Here are recommendations to find the perfect fit...
Read more
September 14, 2023
Articles
Hot wallets vs. cold wallets: What is the difference, and which is safer?
Business challenges for corporate workers now involve finding a solution for crypto storage. This article delves into the...
Read more
December 1, 2023
BitHide updates
Release 2.30
Read more
November 14, 2023
Articles
How businesses can protect their cryptocurrency funds from loss
Worried about protecting your crypto funds? BitHide has the answer! Discover handy and easy-to-follow tips on how to...
Read more
July 1, 2023
BitHide updates
Release 2.23
We are pleased to announce new updates to our BitHide wallet, which will greatly simplify working with cryptocurrencies....
Read more

Relatedarticles

May 2, 2024
Articles
Payment gateway: selection and selection criteria
Selecting the right payment gateway for your business is a key step in determining the efficiency of online sa...
Read more
April 4, 2024
BitHide updates
Release 2.34
Read more
March 3, 2024
BitHide updates
Release 2.33
Read more
SEE MORE

Got a question?

Ask them in the feedback form. A BitHide specialist will get back to you as soon as possible.