Tuesday, November 26, 2013

A Long Post for a Simple Rule

The other day, my buddy Ryan asked me a question about a program he was working on:
Ryan: so say I have three lists of (different) objects in a helper class to deserialize JSON to
Ryan: then these objects get saved to a database
Ryan: in the current version of our platform, all three of these lists will be populated, but in the previous version only two lists get populated
Ryan: would it be better to create a new helper object just for the backwards-compatible API call? or use a variety of if statements to check whether that one list is null or not and update the DB accordingly?
 As I mentioned in my post on the XY problem, I needed to get more into the details about the problem:
Ed: umm
Ed: depends?
Ed: you're adding a new list to this object?
Ed: or was it always there, but is sometimes filled?
Ryan: basically JSON data from a HTTP request is automatically deserialized into an object, and depending on API version a client will either send 2 or 3 arrays of objects
Ryan: would you create two different objects to deserialize to or use one object and just check whether one of the lists has been populated
At this point, I was pretty sure what it was he was trying to do. He was rewriting a service with a new API, but it had to be backwards compatible. But we were still talking about a problem one level removed from the important issue at play: changing the API.
Ed: is the api changing? is the client changing?
Ryan: the API is changing, but the client may not change
Ed: So the question you have is, On the backend of the API, do you create separate classes to represent data for APIv1 and APIv2?
Ryan: right
Ed: what does APIv1 send
Ed: right now
Ed: 2 arrays or 3
Ryan: v1 sends 2, v2 sends 3
This is a sneaky issue. One might think that changing an API to send additional data back is not really a breaking change. I mean, if they're still getting X and Y, who cares if they get Z as well?

You should care! You can't predict how someone else will use your API. Maybe they'll write some terrible code that would throw exceptions if there are three arrays returned. Even if the consumers of your API are your coworkers, you have to expect that your consumers will rely on every single thing your API does.

And so, I began to dissuade Ryan of his folly:
Ed: so if you use the same object, you'd change APIv1?
Ryan: no, v2 only extends on v1, doesn't change it
Ed: but v1 sends 2 arrays now. if you make it send 3 arrays, you are changing v1
Ryan: I'm deserializing to the same object via two different controllers in two different namespaces
Ed: doesn't matter. Don't change v1
Ed: and changing the return value, even if it means adding an always-empty array, is changing the API
Like I said, this one's sneaky. We as programmers tend to think about how we would use our own code. But an API, even if only available to a limited set of people, is a public interface, and people will do dumb things with it.

Conclusion:
Ed: a good rule of thumb is Never change the API
Ryan: yeah I guess I would be changing it, wouldn't I
Ryan: damn
Ed: yes
Ed: that concludes today's lesson

Thursday, November 21, 2013

Two Cents is Too Much: Ender's Game

It's about time I reviewed something again! Here comes Ender's Game, only the most celebrated scifi book in forever (citation needed). If you haven't read the book*, fair warning: there's a ton of spoilers below the jump. Even if you saw the movie but didn't read the book, there are still spoilers.

* And if you haven't read the book, go read it. Now. It's the only book I've bought multiple copies of solely to loan out to people to read. All of my copies are out at the moment, so you'll have to ask someone else. 

I wish I got the Federal Network with my cable package.
But before I get into the review, I wanted to unveil my new plan for reviewing things. I've been trying to find a way to encapsulate two separate axes of rating. The first is hype vs. reality, expectations vs. inevitable disappointment. The proto-idea had been bouncing around in my head for a while when I finally read the Movie Plus-Minus* post by Joe Posnanski. The idea is that we as humans judge things not by their absolute value, but rather their value relative to our own expectations. You know you've had that thought; you were so excited to eat that burger, watch that movie, read that book, that when you finally eat/watched/read it, the burger/movie/book was unable to live up to your expectations. And you've had the converse as well; picking up something you expect to be mediocre at best, only to be blown away.

* Posnanski** took the name "Plus-Minus" straight from the Fielding Bible, which makes sense, as he writes a sports blog. I prefer to call it the "Hype-O-Tron". 

** Whenever you see an asterisk followed by an italicized comment on this blog, it's a Posterisk, and I totally stole it from him. The guy is brilliant, if not for his sports writing, then for his writing style in general.

The other axis is quality vs. enjoyment. Sometimes we really enjoy terrible things. Other times, we look at world class works of art and say, "Eh, I'd rather clip my toenails" (I'm looking at you, Citizen Kane). For example, Starship Troopers is not a quality movie*. The acting is sub par, parts of the plot make no sense, and the execution of all the actors (save NPH) it pitiful. Yet I can watch that movie anytime. It's definitely a comfort movie for me.

* If you get a chance, read the book. It's so much better than the movie in terms of quality, yet it's still eminently enjoyable. 

Two axes, you say? Sounds like a job for a graph!

No one ever accused me of being good at graphics.
So you can see, Starship Troopers was far lower quality than I expected, but I enjoyed it even more than I thought I would.

Now, on to Ender's Game (after the jump, you know, to hide them spoilers).

All rights reserved. Take that!