Last week at Shopify we had a this thing called FedEx Days (or something similar) where we were given 2 days to work on any project we wanted. After having looked at the Jhopify library, and trying to patch it, I figured that API bindings for Shopify could be solved better. I had worked with the Shopify API before when I first started working at Shopify while I was still doing Android dev there. Since then though, nothing really came of it.
I had taken a few lessons from that experience and decided to use that knowledge to create a tool so that Android devs could spend less time writing boilerplate API code, and more time solving problems. I also wanted to ensure that I could provide as much of a one-to-one mapping to the API as possible. This meant one thing, Java Beans. I looked at the API and looked at a blank Article.java file and cringed. There has to be a better way to do this; and of course there is! You see, I remembered reading something from the Pragmatic Programmer. It’s something along the lines of “If you have to write repetitive garbage, why not have a computer do it instead? Voila! Code Generators!”.
Thankfully, the Shopify API provides some pretty good example output and I figured I would use this as a tool. With the Shopify examples that I had so gracefully copy-pasta’d into some ‘fixtures’ that I was intending on using for tests I then proceeded to use them as training data.
So I fired up my default system text editor (TextMate, though emacs would’ve been preferable… no time!) and started hacking out some ruby. First step was to get all the POJOs/beans written up, then I’d tackle actually getting the API to work. This was pretty straightforward; read in the data, turn it into a hash, infer the data types and apply the various private members and their getters/setters, add annotations, etc.
But it dawned on me. What if the Shopify API for say, Articles were to ever change? I could just manually add the new changes, but that sucks. This reminded me of another problem I had when doing some iOS/core data work about a year ago which has much of the same problem, which was solved. The tool that solved the iOS problem is known as MOGenerator. The way the tool works is by inspecting your data model and creating intermediate classes with all the boilerplate, then adds a subclass where you can add custom code. It makes the promise that if you ever put custom code in the _yourModel (or whatever syntax it uses), MOGenerator will gladly come in and overwrite all of it. So I figured that taking a similar approach for the Shopify models would be fine, and would also save a bunch of time/worry.
With all that working and tests running green on some simple and more complex data types, I then proceeded to create the API bindings. I decided to go with a tool called CRest which makes mapping API endpoints far simpler. After writing the first endpoint I again realized that this could be generated as well, mind you not as elegantly. Not all endpoints map out in a manner that is as simple as the beans, but I figured this is the best way to get at least some form of API wrapper working. So making some really basic assumptions, I also generated all the endpoints. These probably won’t work as elegantly as the beans did, but it should be a starting point for anyone wanting to work with the API.
So all in all, I was able to get hundreds of lines of code written up in about 200 lines of ruby. Though we need to keep in mind that much of that ruby code consists of huge blocks of text and not actual logic. If I were to remove all of that, I’d say this was accomplished in even fewer lines, perhaps 100? I’m hoping to have the code publicly available on GitHub soon. Just need to get a tutorial/demo app written up, unless you don’t care, then I may be able to convince some people to release it as is.