-
-
Save ifandelse/2152463 to your computer and use it in GitHub Desktop.
| // Below are FOUR possible examples of publish method signatures for the upcoming v0.6.0 release. | |
| // Each one is using a simple "data" object (containing Alex's first and last name, since we were chatting as I wrote the gist) | |
| // It's also worth bearing in mind that this is the top level API publish (where you don't have a handle to a channel already) | |
| // you'll still be able to say var channel = postal.channel({ channel: "someChannel", topic: "someTopic" }), and then call publish off that later | |
| // 1.) Single Payload, envelope is special member | |
| /* | |
| PROS: | |
| one object to publish (data/env) | |
| focus is on "DATA" being published - nice for consuming dev? | |
| CONS: | |
| potentially more difficult to extract envelope and data into separate args w/o perf hit of delete | |
| */ | |
| postal.publish({ | |
| _envelope: { | |
| channel: "myChannel", | |
| topic: "my.topic", | |
| timeStamp: new Date() // this is provided by postal when msg is published | |
| } | |
| firstName: "Alex", | |
| lastName: "Robson" | |
| }); | |
| // subscriber | |
| postal.subscribe({ channel: "myChannel", topic: "my.topic", callback: function(data, envelope) { console.log("Got yer datumz"); } }); | |
| // 2.) Single Payload, envelope is payload, published data is under "data" prop | |
| /* | |
| PROS: | |
| one object to publish (data/env) | |
| in-line extend for enrichment style patterns | |
| easier to pull data off of envelope object to pass to subscriber with (data, envelope) signature | |
| probably the most performant option when it comes to code execution on the publish side | |
| CONS: | |
| data is a sub object on publish (subscribe has option of separate args) | |
| */ | |
| postal.publish({ | |
| channel: "myChannel", | |
| topic: "my.topic", | |
| timeStamp: new Date(), // this is provided by postal when msg is published | |
| data: { | |
| firstName: "Alex", | |
| lastName: "Robson" | |
| } | |
| }); | |
| // subscriber | |
| postal.subscribe({ channel: "myChannel", topic: "my.topic", callback: function(data, envelope) { console.log("Got yer datumz"); } }); | |
| // 3.) Two Arg Approach (data, env) - current v0.6.0-RC | |
| /* | |
| PROS: | |
| explicit separation of data and env ? | |
| no perf hit on separating data/env into separate args into subscriber callback | |
| focus is on the data being published, env is secondary | |
| CONS: | |
| more typing | |
| potentially less readable than above approaches | |
| the most common use case will have the second arg being just an object literal specifying topic, seems heavy | |
| */ | |
| postal.publish({ | |
| firstName: "Alex", | |
| lastName: "Robson" | |
| }, | |
| { | |
| channel: "myChannel", | |
| topic: "my.topic", | |
| timeStamp: new Date(), // this is provided by postal when msg is published | |
| } | |
| ); | |
| // subscriber | |
| postal.subscribe({ channel: "myChannel", topic: "my.topic", callback: function(data, envelope) { console.log("Got yer datumz"); } }); | |
| // 4.) Two Arg Approach (env, data) - current v0.6.0-RC | |
| /* | |
| PROS: | |
| explicit separation of data and env ? | |
| envelope data first might be more expressive in reading? | |
| CONS: | |
| more typing | |
| potentially less readable than single arg approaches | |
| the most common use case will have the first arg being just an object literal specifying topic, seems heavy | |
| */ | |
| postal.publish({ | |
| channel: "myChannel", | |
| topic: "my.topic", | |
| timeStamp: new Date(), // this is provided by postal when msg is published | |
| }, | |
| { | |
| firstName: "Alex", | |
| lastName: "Robson" | |
| } | |
| ); | |
| // subscriber | |
| postal.subscribe({ channel: "myChannel", topic: "my.topic", callback: function(data, envelope) { console.log("Got yer datumz"); } }); | |
| // OR reversed subscriber callback args (to match the publish order) | |
| postal.subscribe({ channel: "myChannel", topic: "my.topic", callback: function(envelope, data) { console.log("Got yer datumz"); } }); |
I like publish( { args }, { message } ) because I am likely to have wrappers that build the meta-data for me and just publish my own data. Like
var publishAwesomeMsg = function( msg ) {
var defaultHeaders = { channel: "blah", topic: "blahblah" }
postal.publish( defaultHeaders, msg )
}
@LegoMaster - good point. Postal currently supports that via a ChannelDefinition object, so you'd do something like this:
var awesomeChannel = postal.channel("blah", "blahblah") // v0.6.0 will change this to postal.channel({ channel: "blah", topic: "blahblah" });
awesomeChannel.publish(msg);If that's in place, does that work out well for you?
That's how we're doing it now, so I guess that would work just fine. So no change for me then ;) Do whatever you want!
I like option #2. The readability improvements alone sell me on it and I definitely like the ease of enrichment.
I don't like 3 and 4 because if you are going to generate your two args separately you are probably thinking in terms of using a wrapper per @LegoMaster in which case you'll likely use a ChannelDefinition object anyway.
I don't particularly like 1 because (super scientific) it feels awkward to me. 2's focus on data being a sub object feels like how jQuery does it with .post or .ajax.
Personally, I'm inclined towards option 2. It feels very familiar, and mental friction is generally what I worry about most in any given API.
Gentlemen - HUGE thanks for weighing in on this! Per this thread, and several one-on-one discussions, I've pushed the latest revisions to v0.6.0RC here. The readme reflects the latest API (and the fiddle link on the readme is updated as well). For this release I will be putting together a real website (soon, at least) with full-on API docs as well.
The TL;DR is option 2 above was used for the top level postal.publish signature, but you still have the fallback to use (topic, data) or (channel, topic, data). The publish on the channel has a 1 arg signature that can either be the plain data object you want to publish, or an envelope (it inspects the object for "topic" and "data", and if they're found, it's an envelope).
The channel's subscribe call just takes the callback, but if you subscribe from the global postal object (i.e. - you didn't already have a channel handy), then you have to pass in an options hash that has channel, topic and callback defined on it).
-Jim
Awesome! I'm late to the party but I agree on all accounts.
Great job
@rauhryan - thanks for weighing in man!
My vote is for #2 - It's simple to read, the work is done for you on the subscriber callback and should you need to follow an enrichment pattern, extending the message data can be done inline with the creation of the hash on publish.
Even though it is a small amount of typing increase, I also like the use of hashes in this case as it makes the semantics of the arguments crystal clear to anyone who happens to be reading the code, regardless of their familiarity with Postal's API.
Parting thought - hopefully API changes will be low impact because it's surface area in your application code should be relatively low. If you have tons of explicit calls to your messaging API in the application, you might be missing the opportunity for better encapsulation and code re-use.