Honestly I've never looked at amplify (didn't even know about it). I had looked at postal before but it had a dependency I was trying to avoid in a project I was previously working on. I was also hoping to expand msngr.js to more areas (messaging across browser windows, messaging between client and server, ActiveMQ, etc).
Also my curiosity in writing one as I originally wrote one almost two years ago called intend.js but, because of my job, I very rarely get time to write open source stuff so it took a while to move to msngr.js, refactor and release.
We moved away from the pub/sub model in our app. It became too difficult to manage all the pub subs happening across modules, especially in a large project with many team members. We're restructuring our app to be better organized and to use a live-binding library.
I'm really interested in how this model scales, so could you please explain a bit what was difficult to manage in pub/sub ? I would imagine that if your topics and channels are well-defined and documented in one place, and the modules also declare what topics they pub/sub, one would get clear boundaries for maintenance.
> if your topics and channels are well-defined and documented in one place
That's the problem. It's hard to get this done. Developers like to develop, it's like pulling teeth to get us to document things. I've found its much easier and faster to have a codebase that speaks-for-itself, in a way.
Don't get me wrong, we definitely do document things. But the miniscule things like implementation details are just too small to be worth spending time on.
We've been in production for about 7 years now. Our team has pretty much completely turned over in that time. Knowledge and conventions get lost, much better to have the codebase dictate how things should be done. A developer will read the code+comments before they read the documentation.
Hmm how to explain live-binding... Angular's $scope and CanJS' Observables are examples of live-binding. Basically, you can pass around a live-binding object and changes made to it in one module are immediately reflected in another. Whereas with a pub/sub model, you publish messages out to a hub and it is up to the module to decide how to react to the message.
A good example of how we use live-binding is with sessions. We have a global live-bound object that holds the session data. Each module that needs to use session info simply refers to this global object. If we perform an API call that returns 401 and kills the session, our API module kills the session object and all our modules immediately respond to this change. We don't have to declare any listeners, or subscribe to any pubs; we just use the object.
> Basically, you can pass around a live-binding object and changes made to it in one module are immediately reflected in another.
This can work pretty good up to certain level but after that this can go out of hand pretty quickly. The cascading effect will become hard to debug.
> Whereas with a pub/sub model, you publish messages out to a hub and it is up to the module to decide how to react to the message.
At least it is at one place to modify and debug. This is loosely coupled. You can easily decide how to react based upon messages. Very easy to introduce new workflows or use cases.
> We have a global live-bound object that holds the session data.
Looks like you are sitting on something that is waiting to explode soon. Global objects are evil
> This can work pretty good up to certain level but after that this can go out of hand pretty quickly. The cascading effect will become hard to debug.
Totally agree, we recognized this before we began using them. They are used for common elements between modules, and we don't hold a lot of data with them.
>At least it is at one place to modify and debug. This is loosely coupled. You can easily decide how to react based upon messages. Very easy to introduce new workflows or use cases.
Maybe. With pub/subs you still need to go hunting for a rogue publish.
With my session example, we use the session object to display the user's name in various places. It's easy to use the session object to do this; I can just stick it in the view. With pub/subs, I would have to listen for the publish and then update the view, and I would have to do this in many modules. Turns a 0 line operation into a 5-line one.
> Global objects are evil
Not true at all! A session is a global thing, isn't it? Why wouldn't it belong in the global context? Edicts like "global objects are evil" end up paralyzing your development and you will sometimes have to do even more evil things to get around them.
>With my session example, we use the session object to display the user's name in various places. It's easy to use the session object to do this; I can just stick it in the view.
Correct. No need for pub\sub here since data is coming from server and we are not manipulating it. Pub\sub is required in scenarios where actions are taking place on client side like user registration, forgot pwd or ordering a product etc
> A session is a global thing, isn't it? Why wouldn't it belong in the global context?
Absolutely. Session is more of a read-only object after once set on the server. I know some people use it to store objects and that is not right.
I constructed this hypothetical object just to give an idea about an evil entity. Some developers would set certain properties in certain functions. It would definitely show zombie behaviour at certain times.
I enjoyed our conversation. Thanks for being so nice with your response.