Tuesday, November 18, 2008

Thrift vs Protobuf object creation patterns, or: the builder pattern

The protobuf object creation API is beautiful. However designed it did a good job. Not that the thrift one is bad, its actually simple and straight forward and much more flexible, but this flexibility is a loaded gun that one can shut his own foot with. Its strange a bit since it seems that Thrift is heavily inspired by protobuf, yet it did no adopt few key elements from it.

The protobuf API successfully confronted conflicting needs:

  • Make business objects immutable (thread safety etc., Scala and Erlang took it to the extreme)
  • Make it flexible to create a business object. For example, if I have ten fields in the objects, all optional I want to allow some of the fields not to be set. Alas! I want it to be an immutable object. Do I need to have factory methods/constructors of all the permutations?!
  • Don't have factory methods/constructors with many parameters. There will be numerous bugs which the compiler won't catch for having the developer mixing up values. For example when there are seven integers in a row and the product and member ids order got mixed up.
The protobuf solution is a nice builder pattern. The builder is a write only interface, like a java bean with only setters. After one finished setting all the values, an immutable object is built (see sample code). It seems co cover all the above requirements.
The only caveat is performance, thought its probably very marginal. The time to create a sample business object is:Protobuf 0.00085 milli > Thrift 0.00051 milli >POJO 0.00032 milli
the builder pattern does have its cost, but consider that its less then a nano second and the number of protobuf objects created in a transaction is probably few orders of magnitude less then creating POJOs.

Protobuf

MediaContent content = MediaContent.newBuilder().
setMedia(
Media.newBuilder().setUri("http://javaone.com/keynote.mpg").
setFormat("video/mpg4").
setTitle("Javaone Keynote").setDuration(1234567).
setBitrate(123).addPerson("Bill Gates").
addPerson("Steve Jobs").setPlayer(Player.JAVA).build()).
addImage(
Image.newBuilder().setUri("http://javaone.com/keynote_large.jpg").
setSize(Size.LARGE).setTitle("Javaone Keynote").build()).
addImage(
Image.newBuilder().setUri("http://javaone.com/keynote_thumbnail.jpg").
setSize(Size.SMALL).setTitle("Javaone Keynote").build()).
build();
Thrift

Media media = new Media();
media.setUri("http://javaone.com/keynote.mpg");
media.setFormat("video/mpg4");
media.setTitle("Javaone Keynote");
media.setDuration(1234567);
media.setBitrate(123);
media.addToPerson("Bill Gates");
media.addToPerson("Steve Jobs");
media.setPlayer(Player.JAVA);
Image image1 = new Image();
image1.setUri("http://javaone.com/keynote_large.jpg");
image1.setSize(Size.LARGE);
image1.setTitle("Javaone Keynote");
Image image2 = new Image("http://javaone.com/keynote_thumbnail.jpg",
"Javaone Keynote", -1, -1, Size.SMALL);
MediaContent content = new MediaContent();
content.setMedia(media);
content.addToImage(image1);
content.addToImage(image2);

0 comments:

Creative Commons License This work by Eishay Smith is licensed under a Creative Commons Attribution 3.0 Unported License.