Questioning the Use of Google Protocol Buffers

GottaWonder.jpg

Being new at a job means trying to fit in. At least it does for me. After you've been around and seen how things are done, and why they were done that way, you can start to critique what's going on. Short of that, you're a clear outsider looking in, and your statements are written off as "...well... if you really understood how we do things here..." and dismissed. So I've been trying to understand the usage of 29West as the messaging system and Google Protocol Buffers on top of that.

I can see the many advantages of Google Protocol Buffers:

  • Language independence
  • Transmission protocol independence
  • Automatic class code generation

But if you look at these classes, they are really very thinly wrapped objects with simple setters and getters and no real place to put higher-level methods on top of the data package.

I can also see that any good messaging system has the exact same capabilities. 29West is no exception, and in it's API you can package up elemental datatypes, shoot them out, and pull them out at the receiving end in an entirely different language.

Sure, 29West is a single transmission protocol, but that's the point of settling on a standard messaging platform for the organization: you want to have one, and only one, messaging system you have to deal with. Given that you make this selection, it seems like overkill to use Google Protocol Buffers to package up the data into a generic byte stream 'payload' in a 29West message.

I suppose if 29West had adopted this, or Google Protocol Buffers had a 29West 'wrapper', it might make sense, but neither does exist. It's just payload packaging on top of a system that already handles the problem of payload packaging quite well.

And as I'm thinking this I read in their C++ tutorial:

Protocol Buffers and O-O Design Protocol buffer classes are basically dumb data holders (like structs in C++); they don't make good first class citizens in an object model. If you want to add richer behaviour to a generated class, the best way to do this is to wrap the generated protocol buffer class in an application-specific class. Wrapping protocol buffers is also a good idea if you don't have control over the design of the .proto file (if, say, you're reusing one from another project). In that case, you can use the wrapper class to craft an interface better suited to the unique environment of your application: hiding some data and methods, exposing convenience functions, etc. You should never add behaviour to the generated classes by inheriting from them. This will break internal mechanisms and is not good object-oriented practice anyway.

They echoed the exact thoughts I was thinking at the time. This is a "data encapsulation" system for transmission on multiple protocols. It's not advisable to subclass these guys because the generated code could get changed at any time and break your code -- so it's really just a data 'packager'. Which is nice, if you need it. But why do you need it if you have a messaging system that does this already?

Answer: You don't.

In the applications I'm looking at, it's clear overkill. There's no added functionality, and just added overhead. If there were the chance that we'd need to use a different transport in the future, then that would be something. If we were abstracting away the 29West messaging so that it could be changed out easily, that would be something. But we're not.

I can see this as something that someone wanted to do - no real need - just a want. That's a pretty thin reason to make organizational standards.

Who knows... maybe there's a reason for it that completely evades me at the time. But I don't think so. I think Google said it best:

...they don't make good first class citizens in an object model.

and if that's the case, and you've already standardized on a messaging system that does this same packaging, why would you choose to use them?