views:

206

answers:

4

I have another argument with a friend of mine.

Consider having a need to design a simplistic JSON-based protocol, which is basically used to send sort of events (messages) between parties.

Say, something like

 { event_id: 1, chat_message: "Hello" }
 { event_id: 2, group_id: 3, presence: "online" }
 ...

I propose to keep this protocol just like above, while my friend proposes to do something like:

 { event_id: 1, details: { chat_message: "Hello" } }
 { event_id: 2, group_id: 3, details: {  presence: "online" } }
 ...

His argument is that just like TCP and, say, HTTP are at different layers of "responsibility", this protocol should use "details" sub-object in order to keep data separated.

Another argument he has is that handlers that handle matched event, should not know anything about "routing" information (things like event_id).

My arguments are:

  1. We're increasing length of each message (and network traffic, this might be important for a system that exchanges with a lot of messages) for the sake of hiding this information from handlers
  2. Handlers do actually need to know "routing" information, say, to answer them properly:

    this.replyTo(event['event_id'], reply); // or...
    this.replyTo(event, reply);
    
  3. Even if we'll need to hide event_id and stuff like that from handlers, we can just strip them out before passing to handlers and thus still save on traffic

This protocol is quite simple and is not supposed to be used by anybody else.

What do you think?

+2  A: 

Favor simplicity...

Properness will be needed when you are writing a specification, a distributed system, and one that will be used in many different circumstances outside of your control.

Being Pragmatic, it is oftentimes better to use the "power of the language" and just write code to handle each case. Don't abstract unless you need to.

Keep it simple. Keep it quick. Keep it clean.

You do not know what it may need to evolve into (features or performance), and the more abstraction you have, the harder it will be to re-factor.

gahooa
exactly, that sounds very close to what I think
Yurii Rashkovskii
In this case to keep simple one demonstrated part means to make complex and less flexible another part.
Andrew Dashin
+2  A: 

Once upon a time when the ARPAnet was still new and IP was still a germ of an idea, someone said "Oh, gee, a 32 bit IP address is plenty -- four billion addresses? No one will ever need that. Hell, we can split them up into different address types, there's plenty of room."

Little did we know, 25 years later, that it would be an issue.

And don't even talk to me about domain naming.

The point is this: you need to think about what can change. Making this into a hierarchy of name spaces just for elegance's sake is unnecessary and wasteful, and when your extra layer doesn't provide any more information content, then why bother.

On the other hand, if you're doing it to make your code less sensitive to changes in the problem, or to make the implementation noticeably easier or less error prone, then it might well be worth it.

So there's your answer: is it just to be more elegant, or does it have other advantages?

Charlie Martin
+4  A: 

After long experience at big project I must strongly disagree with gahooa's and Charlie Martin's suggestions. There is big tension between agile and classical approach. Their suggestions can look like agile but I can't agree. If you design something, never design it in way that you know is wrong even just now. It's not agile, it's dumb. I can't believe you think that your requirements will not change in future so keep doors open and refactoring impact minimal. When in your current design event is handled by different subsystems as event type dispatcher -> router to group -> final event handler/storage or whatever, keep change in each subsystem with minimal impact to each other. Best afford for me is design protocol like onion peels bud don't design it to each subtle detail outside your current requirements. It's agile.

You arguments:

ad 1. It is premature optimization. If you really need minimize traffic, use binary protocol instead ;-) Other way cost/benefit of ti is wrong.

ad 2. It is work for internal program instrumentation, not for protocol itself. It is wrong design especially in Erlang. Your handler should not return directly to destination but to some router (typically back to dispatcher) which keeps socket ownership and similar. It looks like premature optimization again!

ad 3. I prefer opposite approach. Provide minimal dataset to subsystems to minimize side-effects, simplify (unit) testing and avoid seduction to use approach from 2. point. Extend if necessary. Don't do it in opposite way.

P.S.: Why you don't name your event but use ids? Premature optimization again?

Edit: Ids are clarified, those are event numbers but not event classes. There should be another class key.

Hynek -Pichi- Vychodil
1. Who said JSON can't be packed into a binary? :)
Yurii Rashkovskii
2. In order for router to route message, it needs to know where it should route it to. I am not saying that message should be returned directly to destination, not at all! I believe I explicitly said it should go through router. replyTo() method is actually a shortcut for router
Yurii Rashkovskii
3. Exactly. Extend if necessary. Add "details" if necessary. So far I haven't seen a reason to add it :)
Yurii Rashkovskii
P.S.: because using names for numbers is dumb :) event\_id is meant to be a sequential id, not type of message (which will be specified in event\_class or something like this)
Yurii Rashkovskii
ad ad 1. When you will pack to binary why care of deepness?
Hynek -Pichi- Vychodil
ad ad 2. Why you not wrap your event handler into some wrapper which will take care about receiving and replying instead doing it explicitly in it? Why not separate communication from message details mangling? I know it is difference in functional and OO approach and I'm used to think functional.
Hynek -Pichi- Vychodil
ad ad 3. Same thing as above. May be difference in functional and OO approach. I naming it "pickaxes which manages stocking" OO design pattern. I don't like it. It complicates testing and needs more mocking than necessary.
Hynek -Pichi- Vychodil
ad P.S.: Well, mine mistake. I did not seen event_class there and event_id is only one which can play this role what I have seen.
Hynek -Pichi- Vychodil
Hynek, you misstate my position. I argue that you *should* consider possible future changes, and design to leave yourself room for realstic ones. NO one can plan for all POSSIBLE changes, and if you did, you'd never finish a "Hello, world". So you must make some sensible decision.
Charlie Martin
A: 

These are two right solutions. If you really have to worry about network traffic your solution is acceptable. But you have also to remember that code maintenance takes the bigger part of code's lifetime, so making the code cleaner today you'll probably save some time in future (already mentioned maintenance).

In my opinion you should have good arguments founded on strong facts to think about such sort of optimizations.

Andrew Dashin