4 ms·
Highly dynamic behavior like this is great in very clear scenarios but think carefully before using it for the majority of your program. Dynamic behaviors are
by gilgoomesh 9y ago
Highly dynamic behavior like this is great in very clear scenarios but think carefully before using it for the majority of your program.
Dynamic behaviors are gained at the loss of type safety (function calls are type checked, messages are usually not) and system coherence (just because you can add and remove components on the fly, doesn't mean that it's safe to do so). To compensate for these losses, you need to increase documentation and increase testing. Most people don't and the result is significantly less reliable code.
> Coupling between callers and responders is removed.
But the number of dependencies is the same (reference versus message type). And now it's unregulated dependency without any compiler-level contract between the two. Are the parameters still what you expected? Are the parameters in the correct format? The message type will continue to match, even if these details change.
> Messages can be dispatched to multiple subscribers
Which is great for communication that is intended to be observable but if you're using public message passing for everything, it's going to be tempting to snoop on the message bus and pull data intended for other recipients instead of passing it cleanly. Now your program is a fragile mess because everything is dependent on precise implementation details of unrelated parts of the program.
> Dependencies can be changed on the fly.
Which is another way of saying that you need to handle dependencies changing without notice. What happens if you're expecting a response but the generator of that response is removed between request and sending response? What if you get a timeout? What if you get a partial response?
- piaste 9y agoFor the first problem, union types are the clear answer (abstract marker classes can approximate it somewhat). The compiler guarantees that all sent messages conform to one of a list of possible valid message types. If the subscribers are static, the compiler can also guarantee that every valid message type has at least one handler; if the subscribers are dynamic, you're treading much more dangerous waters but at least you have a comprehensive list of possible messages to verify at runtime that each one has at least one handler. For the second concern, I agree but I would invert it: if a publisher writes messages intended for a particular recipient, that's a misuse of a message bus. You'd be better off making a regular method call in that case (nobody says the bus should solve every one of your problems). Ditto for the third - if you absolutely need a specific response to your message, don't use a message bus to send it. The challenge of message-bus-based architecture at that point becomes minimizing the number of publishers which need to make direct calls.