Protocol Buffers and O-O Design

297 views
Skip to first unread message

JamesC

unread,
Jul 15, 2008, 8:58:02 AM7/15/08
to Protocol Buffers
I have a problem with the advice given in the Java tutorial -
essentially saying don't inherit from the generated classes, wrap them
instead. This seems like a terrible coding and maintenance overhead.
For example: I create a Person protocol with many fields; that gives
me accessors and setters for free. Now I want to add one more method
(eg validateZipCode). If I extend the generated classes all I have to
do is define my new method, but to wrap them I have to duplicate all
the accessors! Worse than that, if I modify my protocol I then have
to hand-modify the wrapper to match.
Have I missed an essential point here?

Alkis Evlogimenos ('Αλκης Ευλογημένος)

unread,
Jul 15, 2008, 9:27:16 AM7/15/08
to JamesC, Protocol Buffers
Yes. You most likely overuse inheritance.
--

Alkis

JamesC

unread,
Jul 15, 2008, 11:04:08 AM7/15/08
to Protocol Buffers
On Jul 15, 3:27 pm, "Alkis Evlogimenos ('Αλκης Ευλογημένος)"
<al...@evlogimenos.com> wrote:
> Yes. You most likely overuse inheritance.

OK, very brief, but not very helpful. (This is the first time in 20
years of OO design in Smalltalk & Java that I've been accused of
that!).
The tutorial says "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."
1. Break internal mechanisms how? An internal mechanism's variables
should be private, its implementation methods should be final, so how
can a subclass break them?
2. "not good object-oriented practice anyway." Says who? Why not?
How is extending a generated class different from extending any other
foreign class (eg those in the JDK API)?

Alkis Evlogimenos ('Αλκης Ευλογημένος)

unread,
Jul 15, 2008, 11:35:30 AM7/15/08
to JamesC, Protocol Buffers
There are tons of articles on the web about inheritance overuse and composition vs inheritance. That said you are free to implement software the way you think is best. It is only advise in a tutorial after all.
--

Alkis

Torbjörn Gyllebring

unread,
Jul 15, 2008, 1:42:01 PM7/15/08
to Protocol Buffers
I would guess that the advice in the tutorial is there to steer you
away from mixing up data transfer objects/holders with behaviour, that
is generally speaking a quite crap idea.
An over reliance on get/set methods are often sure signs of weak
behaviors and procedural code, not that Im in any way implying this in
this particular instance, it's just something to look out for.
But are you really sure that you want to expose the full API for a
message in your own class? does it make sense? is giving clients such
a big surface area really a good idea, what if clients of your class
start relying on implementation details of your choosen serialization
mechanism (in this case PB's) and that implementation change, do you
really want to go down that path?



On 15 Juli, 17:35, "Alkis Evlogimenos ('Αλκης Ευλογημένος)"

Kenton Varda

unread,
Jul 15, 2008, 2:34:05 PM7/15/08
to JamesC, Protocol Buffers
Hi James,

A Google search for "fragile base class" produces several articles describing the dangers of inheriting implementations (as opposed to interfaces):

http://www.google.com/search?ie=UTF-8&q="fragile+base+class"

Your validateZipCode() method sounds like something that could just be a static method in some utility class.  No need to duplicate all the accessors in this case.

JamesC

unread,
Jul 15, 2008, 2:51:16 PM7/15/08
to Protocol Buffers
Thanks Kenton and Torbjorn for your helpful comments. Of course I
would never set out to design a class model in which Person is a
subclass of PersonData. I do understand the proper use of
inheritance. What's baffling me here is the development/maintenance
use case for this this tool, particularly in an OO Java environment.
Is it:
1. Build proper OO model in tool of choice, generate objects, extract
all variables, re-code variables as Protocol Buffer source, generate
Java message classes, hand-code all the wrappers and calls to the
generated message classes in my generated model classes, hope I can
maintain it.
or:
2. Build non-OO data model, hand code Protocol Buffer source, generate
Java message classes, hand code Java objects/wrappers according to a
(separate) OO model, hope I can maintain it.
or:
3. Some other development process [please supply details]?

Once again, no way would I advocate subclassing the Message generated
classes, except that this tool doesn't seem to offer any acceptable
alternative. So, please set me straight!

Kenton Varda

unread,
Jul 15, 2008, 3:04:33 PM7/15/08
to JamesC, Protocol Buffers
This is a point of debate even inside Google.  Some people say generated protocol message classes should be used only as a helper for serialization, and should be hidden behind some more appropriate OO interface.  Others say that this just adds a lot of work, and it often works fine to just pass around the message objects themselves.  The best choice probably depends on your use case.

Jon Skeet

unread,
Jul 15, 2008, 3:55:00 PM7/15/08
to Protocol Buffers
On Jul 15, 8:04 pm, "Kenton Varda" <ken...@google.com> wrote:
> This is a point of debate even inside Google.  Some people say generated
> protocol message classes should be used only as a helper for serialization,
> and should be hidden behind some more appropriate OO interface.  Others say
> that this just adds a lot of work, and it often works fine to just pass
> around the message objects themselves.  The best choice probably depends on
> your use case.

This is probably a good time to remention that I'm planning to make my
generated protocol buffer classes in C# "partial".

While adding behaviour would be a bad idea in some cases, in others it
could be nice. For instance, protocol buffers are reasonably limited
in the types they can hold. Suppose we wanted to represent a date and
time in a protocol buffer. There are already nice .NET types which
represent dates and times, so it would be logical to have a property
of that type which converted the "raw" integer data. With partial
classes, these can be added very easily.

It's not the kind of thing I'd expect to be terribly common, mind you.

Jon

Colin Fleming

unread,
Jul 16, 2008, 4:43:58 AM7/16/08
to Protocol Buffers
Support for inheritance is something that would help us a lot as well but I need inheritance within the data objects (i.e. they can extend one another), not extending them with classes to add behaviour. We currently have a bunch of objects that are generated using JAXB - I can't change that since it's a requirement that our objects are defined using schema. I'm planning to write a JAXB plugin that allows these objects to be serialised using the protobuf format (so it will essentially generate the same code as protobufs optimised for speed). However we use inheritance fairly extensively (if anyone feels like telling me to use composition, please don't) so I'm going to have to extend the model slightly. Native support for this would be really useful for us, but I realise it's an unusual/unpopular choice.

Cheers,
Colin

Marc Gravell

unread,
Jul 17, 2008, 7:04:11 PM7/17/08
to Protocol Buffers
> There are already nice .NET types which represent dates and times

Funny you should say that; since my alternative C# implementation is
based on the runtime, I thought it handy to be able to handle DateTime
and Decimal; I've done these using unix time (unit32) and OLE Currency
(int64/sint64). An external client would have to know how to treat
them, but at least it is in the /flavor/ of the spirit of the
protocol...

Marc
Reply all
Reply to author
Forward
0 new messages