marionettejs / backbone.wreqr

Messaging patterns for Backbone applications.
Other
346 stars 53 forks source link

reqres, why? #60

Closed canvaspixels closed 9 years ago

canvaspixels commented 9 years ago

I just came across this and I completely agree. Are there plans to remove reqres? Please could somebody give a counter argument or explain a scenario of when reqres would benefit me. If this is the wrong place to put this, please point me in the right direction, thanks!

jamesplease commented 9 years ago

There are no plans to remove reqres.

You can store information on a channel using reqres, or implement decoupled systems where A interacts with B through some channel (using reqres). Although the names (request response and commands) suggest a semantic difference between the two, that isn't the case. Http, for instance, is a reqres implementation. Accordingly, reqres can be used in situations where you order a 'command' yet would like a response, as in DELETE or PUT.

jamesplease commented 9 years ago

While reqres will forever be a part of Radio, Radio may be an optional dep of marionette in v3. So if you don't want to use it, you don't have to.

canvaspixels commented 9 years ago

Thanks for your quick response James, I was just after a scenario where it might be of use on the client. Http requests/responses happen between a client and a server so it makes sense in that scenario, however I can't think of why you would use it solely on the client. Why was it built in the first place? For a real world use?

Forgot to actually add the link: http://victorsavkin.com/post/50669505752/marionette-requestresponse-considered-harmful

canvaspixels commented 9 years ago

Oh and where did the name Wreqr come from? :)

jamesplease commented 9 years ago

I was just after a scenario where it might be of use on the client.

For simple CRUD web applications, you may not need it at all. If you're building a more complex web application with lots of data and pieces, then messaging-based architecture could be useful. One situation I use it in is to store/retrieve user and auth data in my applications. With that said, I could just as easily require('path/to/user'); and go from there. I prefer channels for testing / it does feel more decoupled to me.

Etsy uses request-response – and Radio – extensively in their application. They take advantage of the fact that events can be serialized into meaningful data. Last I heard they were working on a system where they were tracking every atomic action a user makes. When an error occurs, they can send the event log back to the server and re-create the user's steps exactly as it occurred to the user. It'd be tough to do that with raw Javascript objects and plain function calls.

In the same way, the Marionette Inspector can interpret your event data and return meaningful data back to you. It can be tough to verify how many times a given action is occurring if you're simply using function calls. If you're using Events, though, all of that is presented very clearly to you.

These sorts of things, again, are more useful if you're not building a simple CRUD interface. If you have lots of moving pieces on your application – like a complex real-time sports interface, or something – then the benefits of messaging patterns (in my opinion) become more obvious.

As with most things in Backbone and Marionette, there's not much of a convention around using these patterns. Use them if you can find benefit to them. If you can't, don't use them. I understand that messaging patterns are topic that not everyone understands, nor cares for, which is why in future versions of Marionette they just might be optional.

With that said, they might just as easily become necessary for the internal functioning of Marionette. Ember adopts a magical pattern called a container, which is how all of the features of Ember are linked together – again, magically. Such a feature doesn't belong in the Backbone/Marionette world, I think, but Radio is an excellent way to accomplish the same thing in a more direct way. The specific feature that would necessitate Radio would be link clicks through a {{ link-to }} Handlebars helper communicating up to the Router.

Http requests/responses happen between a client and a server so it makes sense in that scenario

I'm curious to hear why you think request-reply makes sense in the client-server situation.

Also, a lot of criticisms – including that article – argue against very old versions of Wreqr and Marionette, and not Radio. That library is what you should be using, as, again, Wreqr is deprecated.

A quick response to that article:

Syntax is Cleaner

Radio has a cleaner syntax than Wreqr. It mirrors Backbone.Events, so it's as clean as Events. If you think Backbone.Events has a clean API (it doesn't imo), then you should also find that Backbone.Radio has a clean API.

Instead of myChannel.reqres.setHandler() the API is now, for instance, myChannel.reply()

Less frameworking

If I was building a very large web application, I might find more abstractions to be more useful. Etsy's app, for instance, is very complex. It's probably very useful to them that they have so little coupling going on between components.

Coupling

I don't understand why any of the points listed here relate to coupling. I'll respond to them one-by-one:

Both versions are synchronous.

Return a promise.

Both assume that there is only one handler for a particular request.

This is the very definition of the request-reply messaging pattern. This isn't something that Derick Bailey dreamed up...it's an established pattern in software development.

Both versions are decoupled from the object that actually processes the requests.

I don't understand this

If the favouriteLanguages handler in the reqres version fails to process a request, the userProfile module won’t be able to recover.

Maybe I'm misuderstanding this, but the userProfile module will only be unable to recover if you fail to include that in your code? Is this not like saying "Failed promises prevent your code from recovering!" when the solution, of course, is to include a .catch callback?

reqres is a global

Do not use the global channel (aka, the one on the application), as it is deprecated. Create topic channels using Radio.channel()

var routerChannel = Radio.channel('router');

A few other notes:

Oh and where did the name Wreqr come from? :)

It's a terrible name, which is why I rewrote it and branded it "Radio," which I found to be more expressive of what it's doing.

jamesplease commented 9 years ago

If I was building a very large web application, I might find more abstractions to be more useful. Etsy's app, for instance, is very complex. It's probably very useful to them that they have so little coupling going on between components.

Let me elaborate on this again.

Abstractions can be used to reduce complexity as an application grows larger. For instance, if all that my webpage is is a gallery showing a few thumbnails, then maybe an abstraction like jQuery is sufficient to write code that is clean and organized. There aren't enough problems there to require something like Backbone or Marionette. A step up from there is a simple application like Gistbook. This is more complex than a gallery, so including Backbone and Marionette – extra abstractions – actually made the code that I wrote simpler and easier to maintain.

I think messaging-based architecture is yet another layer of abstraction that becomes more useful at a stage beyond applications like Gistbook. At my last job, we made apps like this:

I wasn't big on messaging patterns back then, but I wish I had been! I think it really would have cleaned up my code with all of those moving pieces. There were literally 50 things happening each second in those apps, and without messaging patterns the code I wrote got to be pretty messy. I would have also loved to have been able to use the Inspector with those Events to get an idea of how information flowed through the app.

In any event, just to reiterate, I don't think that messaging patterns are ever necessary. I just think they can help sometimes in particularly complex situations. But there are always many ways to do things :)

samccone commented 9 years ago

:book:

jamiebuilds commented 9 years ago

To tack on to that epic response @jmeas gave, I also want to say that Radio provides you with very low level api on which you can build all sorts of cool tooling. I recently built an error handling library with it at work. Using Radio it's only 0.8kb.

canvaspixels commented 9 years ago

Thanks for that very in depth response. I'm a lot clearer on this now.

Re: I'm curious to hear why you think request-reply makes sense in the client-server situation. I'm not sure, I guess because they are more disconnected?

jamesplease commented 9 years ago

I'm not sure, I guess because they are more disconnected?

Heh, yeah. They are disconnected – and often times you want them to be – which is why a messaging patterns seems to make sense. The point I was trying to make here, if you didn't catch it, is that if you want to have disconnected pieces on the client (again, think big apps), then you might appreciate evented architecture there, too.

canvaspixels commented 9 years ago

Yeh, I got it thanks :) just my concern (similar to that blog post author's) is that people not doing big apps, say small to medium, start using it willy nilly and adding complexity for not really much/if any benefit.

jamesplease commented 9 years ago

is that people not doing big apps, say small to medium, start using it willy nilly and adding complexity for not really much/if any benefit.

Indeed, indeed. We're working on a huge overhaul to our documentation. We'll be sure to make it more clear going forward!

samccone commented 9 years ago

@jmeas you should publish your response under the blogggg https://github.com/marionettejs/blog

jamesplease commented 9 years ago

I already started on a response to another anti-reqres blog. I'm not that interested in spending time content on our blog til it's a little better :(