I finally migrated my old blog. I don’t think WordPress will ever sell-out, so it should be safe here, opposite to Posterous. Although I kept all past posts, I intend to blog more about technical topics here (relating to my job, my projects, Python, iOS and whatever else comes by). For the rest, I’ve set-up a Tumblr. You can just follow me on Twitter as I will publish everything there as well.
I have a simple proposition for you. I will help you make sense out of the data you have. For free. There’s no catch. Give me your raw data, tell me what you want to learn from it and I’ll make it so.
If you’re wondering about my motivation, it’s easy. I want to sharpen my data analysis and dataviz skills. I know there are publicly available data sets I could use to do that, but I’m not particularly interested in working with those aimlessly. I need a purpose to be motivated.
Sounds intriguing? Great, get in touch.
Alert.Us launched yesterday. It is a child monitoring application we at Wildfuse helped to develop. I was responsible for designing and building the RESTful API and the whole server-side of the product. It was a great learning experience. Here are the main points I took away:
Distributed systems are hard. This was the first distributed system I did. Although in comparison to what other people are building it’s almost a toy, still, it was hard. Even though I knew about fallacies of distributed computing and the CAP theorem, it’s still difficult to get it right the first time. This recent article sums it up nicely and I have to confest I felt a bit stupid after reading it.
When building a distributed system you’ll need all the help you get. We used AWS extensively for the whole project and I believe it was a major success factor. I have to point out especially DynamoDB and SQS. These components just work. As my ops-chops are not as great, I welcomed the fact that I could just enable them and forget about them. Isn’t this the holy grail of cloud computing?
Distributed systems are fun. They didn’t teach distributed computing at the university when I was attending and I doubt they do now. You have to learn it yourself, make mistakes and fix them, read white-papers and other people’s experiences. Learning this and working with new technologies is the fun part, but getting it finally right even more so. Unfortunately I don’t know of a good “centralized” source of information on this topic. Most of it is randomly scattered all over the Internet. For now, I’m using Prismatic to follow the news, but if you know of a good source, please share`.
A central element of the app is an activity feed. Here are a couple of tips that might be useful if you’re building it into your product too:
- Make the data structure representing a feed event as flexible and extensible as possible. In our case, the project requirements changed during development, as usual, and some of it also affected the feed. Be prepared.
- As the server and client development is independent, the client apps should have a default way (a fallback) to present new, from their point of view essentially unknown, event types.
- There should be a “beginning of time” event in every feed. It can be the date of birth of a user or the date when a user signed up. It can be used to display a welcome message. It’s also a good way to indicate that there’s nothing more in the past so the clients can stop paginating.
- Having a feed means having events ordered by time, but time is a bitch. Consumers of this API are mobile apps. Mobile means the delivery of an HTTP request my be somewhat late, both ways. Furthermore, in our case, the apps have a “freeze” feature — if there is no network connection at a given moment, they’ll won’t fail but will wait with the sending of events until the connection is restored. All these factors raise a lot of questions. Do you trust the event timestamp from the mobile clients? What if the event is too far in the past? Do you process it the “normal” way, process without “side effects” (such as sending a push notification) or do you discard it altogether? And how far in the past is too far — 10 minutes, 1 hour? What if the event timestamp is in the future? Maybe your system will be different in that you can always attach a timestamp on the server — if so, good for you. I came to the conclusion that a good enough solution is to trust mobile clients, but if they report an event with a timestamp in the future, replace it with current time. This handles most of the cases as intended.
- One thing I learnt about only after the feed was done was Activity Streams. I’ll leave it here for reference. It’s definitely something worth checking out.
Speaking of time, represent time in RFC 3339 format and keep it in UTC. Always, everywhere. This will save you a lot of headaches. RFC 3339 is a subset of ISO 8601 for use on the Internet; hence it is friendlier. Follow the “Be strict in what you send, but generous in what you receive” rule — accept time with any timezone offset but send out time in UTC.
Log like crazy. The bare minimum you should log is errors (d’oh), requests, responses, response times, all 3rd party integration points interactions (especially response codes and response bodies!) system state transitions, but feel free to add to this list. You can never log too much. Log in a machine readable format — JSON works pretty well. Ideally, all logs should be publicly accessible and searchable. If you don’t do any kind of analysis on your logs, you can safely delete them after ~7 days. This timeframe is enough to answer even late questions about what went wrong.
Similar rules as for logging apply for measuring. The more you measure, the better. What gets measured, gets managed, right?
Read Release it!
Always have an up-to-date documentation of the API. In my opinion, a feature isn’t done until the documentation for it is written. I followed this rule closely. We even had an agreement that if there’s an implemented but undocumented feature of the API or a mistake in the docs, I owe a drink to the dev who found it. I never had to buy one. I got into the habit that the first thing I did after a commit was to update the docs. Accept it as part of the work. It pays its dividends — I saved a lot of time answering questions from the client developers just by pointing them to the docs. We kept them on the GitHub wiki and it worked quite well, but services like Apiary.io might work even better.
Even if you have the best documentation, there will still be information that will get lost. For example, one developer may come up with an enhancement other platforms may benefit from too or a change request comes in. A central messages board of some kind with this info aggregated would help. We didn’t have one (hence some information got “lost” or didn’t reach everyone involved in time), but it seems to me the Stripe way of having every email CCed to email groups would work well for us here. Have you encountered this problem during your carreer? I would love to hear how others are approaching it.
Help client developers as much as possible. Sometimes I feel frontend devs have it even harder. They have to face crazy demands of multiple parties and ever-changing feature request. I know, I’ve been there too. The last thing they want to face is a half-assed API. Ease the pain of development of your fellow comrades, they’ll love you for it.
Utilize the capabilities of HTTP to its fullest. I’m still amazed how well HTTP works for “modern day” use cases. Sure it’s not perfect, but it goes a long way. Be pragmatic rather than dogmatic about using HTTP. Tip #1: use the User-Agent header to identify the device type, operating system and client version/build number (e.g. “iOS 5.0; App v0.82 (1554)”). It helps when debugging. Tip #2: use Accept-Language to determine the locale of the resource. Works like a charm.
If you want to learn more about the design of HTTP APIs, I strongly recommend following the api-craft group and people like @johnsheehan, @kinlane, @mamund or @mikekelly85 on Twitter; surely, you’ll find others. If you know about “distributed systems” people on Twitter I can follow, please let me know, either in comments or tweet me.
Errors are the third class citizen of any interface; nobody wants to deal with them. Not enough care goes to crafting proper errors, but this is a mistake. It’s when things break your API consumers need most help. Proper error handling distinguishes good APIs from great. If you follow the recommendations outlined in this blog-post, you’ll be one important step closer to having a great API.
Since we’re dealing with HTTP here, be sure to take advantage of it. Always respond with a 4xx or 5xx status code when an error occurs. If you’re sending 200 OK, you’re doing it wrong. Make sure the payload is of the same content type as the rest of your API, whether you’re using JSON, XML, HTML or any other format, otherwise you’ll create a headache for API consumers. Be sure you send the appropriate
Content-Type header (optionally respecting the
Accept header). Most of this is covered in this great training video from Layer7.
A title, description and an error code is the bare minimum you should send. The title and description are components of the error message which I write about in the next section.
As mentioned earlier, HTTP already provides us with a set of error codes and for simpler APIs, these work great and are sufficient. If you need more granular reporting, add another field to the payload which holds an application-specific error code. Have a document online with a detailed description of every application error code and add a URL pointing to it to the error payload (h/t to John Sheehan for bringing this out in the comments) This greatly helps when debugging less obvious error states.
Hence, a good error coming from an HTTP API might be similar to this:
Anatomy of a good error message
A good error message should be as specific as possible. Don’t use general terms as “Something went wrong” or “Error occurred”. That’s obvious. An error message should help the user recover from it. Provide hints to what went wrong, if something is missing, not well formed or conflicting. You’ll get bonus points for giving instructions on how to actually fix the error.
Also, keep in mind who’s the intended audience. Most API errors will be seen by developers, so you can “talk” to them in more technical terms. Some, however, may bubble up to regular app users, keep that in mind. In this case, send the title and description localized, according to the
Finally, don’t be afraid to write the error message in a human way, it will appear less frightening. UPDATE: Check out this great answer on StackExchange.
It goes without saying that all errors should be logged. What I found useful is to log the full HTTP request and the application stack trace. Have this log available online and add a new field to the error payload containing a link to the encountered error. The API consumers can then paste this link in their bug report. It makes debugging and cooperation between developers much easier.
Error states are an important part of every interface. Treat them as such, don’t ignore them. Users of your API will praise you.
The fourth and final part in the mini-series about online education.
Professor Ng knows very well how to teach. The lectures were well structured, interesting and the principles of a given topic were communicated effectively. Coursera doesn’t make the same mistake as Udacity; lecutres are usually 10–14 mintues long with an occasional in-lecture quiz. Assignments for the ML course were stimulating and rewarding. Not that taking the ML course will make you a full-fledged data analysit (although some might argue otherwise), but you’ll learn the basics and get pointers to what to learn next.
It’s the same story with the rest of Coursera courses. They are fun and engaging, you’ll learn a great deal and know where to look next if you want to dive deeper in that particular subject.
From the technical standpoint, Coursera is not as advanced as Udacity (e.g. rewinding lecture video is a pain), but they’ve created a great paltform for online education. Plus, they are tailoring it to each course needs.
This, together with perfect content, partnership with top world universities, broad choice of topics make Coursera my online education platform of choise.
For some interesting behind the scenes info, watch this TED talk by Daphne Koller, Coursera co-founder.
This is the third part of a short series about my experience with online education.
I took two Udacity courses – Design of computer programs and Intro into statistics.
There are things I like about Udacity and things I don’t. Unfortunatelly, those that I don’t like are the important ones for a online education platform.
The good things are that there are wise people building the platform. Technically, it is very good. I like that they use the Youtube player or the smooth transition between video playback and in-lecuture quizes. In some programming courses, you have a Python interpreter directly embedded in the browser window. They also built relationships with potential employers of Udacity “graduates”. All of this is smart and helpful, yet it doesn’t help with the main problem.
Udacity is not a good place to learn.
In my opinion it is mainly because of the format of the “lectures” – 2 minute videos are just too short and, as crazy as it might sound, I had trouble keeping my attention focused exactly because of this. Two minutes is not enough to pass on any principle. You try to keep it them in your head but the constant video switching suck. It interupts your train of thought.
Also, it doesn’t help that you can’t easily see the code or examples written previously and so you get stuck thinking “Why is it this way? What did the lecturer mean? How is it supposed to work?”. If you are not thinking exactly the same way as the lecturer, you’re going to have trouble following him.
The 2 mintue videos are at the heart of Udacity as you can hear from Peter Norvig in this TED talk, yet I hope they change it, and also improve on the other problems I’ve encountered. Until they do, I’ll prefer sites like Coursera.
This is a pre-commit hook I use in my Python projects.
Nevermind my feak bash-fu, in the end the script does what I want it to – the three following things:
- First, it checks if I haven’t forgotten to add a new module to the requirements.txt file. Most of the time this works like a charm with virtualenv and pip. The only drawback is installing modules in local experimental branches – these modules are not necessary in upstream branches and so they don’t belong to requirements.txt yet. When you switch back and want to commit in an upstream branch, the pre-commit hook fails. However, this is easily avoidable by using the
--no-verifyoption of git commit.
- Second, it runs pyflakes on all the .py files in the repository. If there’s something pyflakes doesn’t like, the pre-commit hook fails and shows the output of pyflakes. There’s one case which is ignored and that is using the _ (underscore) function from the gettext module as install makes it available everywhere. Pyflakes documentation is non-existent and I guess there’s no way to create a configuration profile for it, so I had to resort to this hack.
- Finally, since I deployed code with forgotten
set_trace()calls a couple of times, the third thing the script does is it checks for these and prints out the file and line number if it encounters any.
I keep this file as a part of the repository, making a symbolic link to it in .git/hooks/pre-commit. Make sure the file is executable.
Do you have similar stuff in your VCS hooks? Is there anything I could improve in mine? I’ll be glad to see your tips in the comments.