C++ – Good practice using signals and event driven system

asynchronous-programmingboostceventsignals

I am using signals (specifically Boost signals2) to create an event driven protocol API and model.

Most elements have their own signals, and there are usually multiple of each element.

Consider a basic entity, a user; amongst others, the user may leave the system, so I need to have a leave signal.

The question is, should the user object itself be passed to the signal handler? I.e.:

class user {
    signals<void(user&)> on_leave;
    //...
};

If there was std::bind and lambda then this decision would be easier to make, but with those passing the user back seems rather redundant, i.e.:

user.connect_on_leave(
    [](user& u) {
        //well I could already refer to user if I wanted to
    }
);

And same with binding, I could do something like this

user.connect_on_leave(std::bind(my_hander, std::ref(usr));

Also, generally speaking, is it better for each signal to just pass to the user whatever it's concerned about, or have some sort of message type which all signals operate with?

And my final question: at what point should I stop normalising data? If several signals share the same "payload", is it better to have separate signals like,

on_change_name(str)
on_msg_sent(str)
on_leave(str)

or

on_action(action, str)

Best Answer

When sending messages/events across a system, you should use specialized data messages for the payload.
If not, if for example your user class changes, everything that listens to messages that have a user as payload, could be affected by that change as well.
As to your question about normalizing: it's not because the signals share the same payload now, that they always will in the future. Reusing messages (or message parts) introduces a form of coupling which could hinder you later on when events need to evolve separately from one another.

Related Topic