...

Yes, commit messages can be fun!

Today is April 1st. A perfect day for pranks and jokes and a little bit of fun. In that spirit, I want to share a reminder that commit messages doe not have to be dry and boring. It’s OK to spice it up a bit and have some fun. In that light, I want to share a commit message I worked with recently that I think embodies the best practices of a commit message (clear, understandable, narrative form), but also is just fun to read. Some irrelevant technical details have been removed.


The problem

When I looked at the output JSON file, I noticed that the value was always the string null. You would think that would break parsing, but of course, the Gson library interprets the word null as a null reference to the object. And yet this worked for other objects and even for this same object in other sections of code!

After some digging, it turns out that there are two culprits to this crime:

  1. First culprit: We are setting up the object to persist in this section using Java’s double-brace initialization. That kind of inline property initialization works miracles in sane languages like C#, but apparently in Java where the type system is wonky, initializing your properties inline results in an anonymous type and (according to this blogger) dead kittens. Fair enough.
  2. Second culprit: But when you pass said anonymous type to Gson.toJson(), it will not break. It will not throw. It will not complain. It just happily returns a string saying null. Workaround? If you pass in the destination type, everything serilializes fine.

Those are the two co-conspirators in the crime (certainly none of the blame falls at the feet of my own bad code, right?) But enough talk. Demo anyone?

MyObject myObject1 = new MyObject();
myObject1.setMessage("Hello world");
System.out.println(new Gson().toJson(myObject1));
// Prints "Hello world"

MyObject myObject2 = new MyObject() ;
System.out.println(new Gson().toJson(myObject2));
// A kitten is dead. Prints "null."

MyObject myObject3 = new MyObject() ;
System.out.println(new Gson().toJson(myObject3, MyObject.class));
// A kitten is dead. But at least is still prints "Hello world"

The solution

Look, no one likes dead kittens. But lots of people like me come from a background where the language doesn’t create an anonymous type just so you can set properties (why Java why?). So we have to assume that some of the objects passed in to our serialization code may be full of dead kittens.

A dead kitten is bad enough. But it’s even worse when it goes undetected for several days (like it was in my case). You see problems in your application and you know there’s something wrong but you can’t tell exactly where the smell is coming from and you start removing your drywall. By returning the word null, that’s exactly what we’re doing. Instead, we should let the caller know right away that they’ve got a problem and save them the unpleasant surprise later.

So I pulled the Gson dependency and abstrcted it into a class creatively named JsonConverter. That class interacts with Gson and when Gson serializes the @NonNull input object to null, we know that someone fell in the felinicidal trap so we can throw a proper exception to let them know they either need to get orthodontal on their code and start removing braces (ba-doom sh), or else they need to pass in the destination type because we can’t have nice things in Java.


If you were offended by jokes about dead kittens, please direct your ire to https://explodingkittens.com/contact.

--- ---