Small Things Matter

Usability is a big topic but sometimes it can be very small things. Say, one line of JavaScript (well, jQuery in this case):


This is a small big thing that is ridiculously easy to implement and yet so underused.

I’m currently slowing down the feature development on the MixifyRequests-site and concentrating on little finishing touches like this in preparation of an official 1.0 launch. I already did one release concentrating on reducing technical debt (by improving the codebase in general, adding more tests, etc.) and now I’m kind of doing the same with UI and copy.

This is usually the part of software projects that gets neglected the most due to tight deadlines and budgets, so it’s fun to be able to do it with no hurry.

(This post was originally posted to my other blog called Spinning Code.)

How Real Life Data Can Kill An Idea

I had an idea to add tweets from registered DJs to the site homepage to give it more fresh and dynamic feel. So I hacked together a small script that fetched latest tweets from all of the DJs using Twitter API. After taking a quick look of the data, it was quite obvious that in practise, this wouldn’t be a very good addition to the homepage.

This is what I saw:

Database Screenshot of Tweets

When you think about it, it makes sense. Most DJs aren’t really interested in Twitter or other social media (except sites like SoundCloud and Mixcloud, which in contrast are very important and much used), they just feel that they need to be there because everyone else is and promoting yourself is hard. Their tweets are mostly just plain adverts of upcoming gigs and very little actual content. DJs create their content as music, not as tweets.

This is actually a good example why it’s important to have deep understanding of the field in order to being able to create good services for it. I’m not yet very familiar with the whole DJ scene yet, which is why I often ask dumb questions from experienced DJs who have been in the business for decades. But I’m learning every day.

(This post was originally posted to my other blog called Spinning Code.)

Quick Guide To Using python-twitter

Twitter doesn’t have an official Python client for it’s REST API (which requires authentication for every query) but there are plenty of third party options. One of them is python-twitter, which is implements full API but lacks a decent documentation.

Here’s a full and working code on how to get a list of public tweets for a given screen name and an example of how to convert tweet dates from strings to datetime objects:

 import twitter  # You'll find these from access_token_key = ''      # Twitter API key access_token_secret = ''   # Twitter API secret consumer_secret = ''       # Twitter Access token consumer_key = ''          # Twitter Access token secret  # this functions needs 4 parameters or it will raise following exception: # AttributeError: 'Api' object has no attribute '_Api__auth' api = twitter.Api(     consumer_key=consumer_key,     consumer_secret=consumer_secret,     access_token_key=access_token_key,     access_token_secret=access_token_secret )  # this follows the REST API reference: timeline = api.GetUserTimeline(screen_name='djUninen', exclude_replies=True)  for tweet in timeline:     print tweet.text  # finally, tweet.created_at returns a string, not a timestamp # to convert the string into a datetime object, do this: from datetime import datetime tweet_timestamp = datetime.strptime(tweet.created_at, "%a %b %d %H:%M:%S +0000 %Y") 

One last exotic error to be aware of is an exception which says “Timestamp out of bounds”. It means that the environment clock is too far away from the actual time. For example if you’re running a local virtual machine which messes up its clock when the host goes to sleep, you might see this. (Note to self: how about finding a permanent fix for the god damn clock.)

(This post was originally posted to my other blog called Spinning Code.)

On Flying Starts

What a start for a blog to end up on the homepage of Hacker News on the first day (with a short post about Django UI). The good: it’s surprisingly easy to install a cache plugin to WordPress. The bad: this blog is not hosted on the server (because I don’t want to install PHP on it) so I missed a great chance to stress-test it.254 Concurrent Users in Google Realtime Analytics

To stay with the topic on flying starts, I’ve been quietly readying the first tool, a site for taking and making requests in Mixify events, for its official launch. I opened the site for public three weeks ago and I’ve been working on it ever since. I’m keeping detailed public release notes to keep the users updated and also for myself as a way to get a feel of the progress.

Most non-DJs and furthermore non-Mixify users probably have no idea what this tool actually does, so let me explain it quickly. Mixify is a Web site where DJs can play for a live audience by streaming sound (and possibly also video) from their computer to Mixify which distributes it to listeners. Listeners can join these live events and chat with the DJ and other listeners. Many DJs take requests but it can sometimes be cumbersome trough the small chat window that can update really fast if there are lots of listeners actively chatting. MixifyRequests is a site where a DJ can make a request event and get the requests in a nice, organised way with a easy to use admin controls for marking requests played etc. Users can also vote for each others requests and there’s a bunch of other features, too. So that’s the idea in a nutshell.

MixifyRequests Homepage v0.9a

I did the first part of the development in one 10 day sprint, with the idea of getting the first alpha version online in whatever state it would be after 10 days. (Because real developers ship.) The first release had one big showstopper-bug[^1] which was due to my lazy testing of Facebook sign up process, but otherwise everything worked fine.

[^1]: Where users who signed up everywhere but from the homepage would get a 500 error after first login because the login view respected ‘next’ parameter that would redirect them past the view that created an app-spesific user profile of which everything on the site assumed to be there. Thanks to Sentry I was informed about the bug immediately and got a hotfix in place in about 20 minutes but it had already affected dozens of users of which few of them didn’t come back that first night.

I decided to do kind of a soft launch by only telling about the site to few selected DJs and by placing a disclaimer on top of every page with a note saying “This site is not officially launched yet. Use it and have fun, but please do not advertise this yet in bigger scale. Thanks!“. So far this has worked really well and the userbase has been steadily growing at a rate of about 1-3 new users every day. Thanks to a small number of real users actively using the site, I’ve gotten loads of good usage data, and most importantly, I’ve been able to find and fix good number of bugs emerging from situations only real users can get to. (It never ceases to amaze me how actual users always find ways to break code that was supposed to be tested really well.)

After the first sprint and the initial production push I changed the development cycle more towards daily productions pushes with the help of feature switches. Last week I sent out an email to all active DJs of the site asking volunteers as future betatesters. Got a few and now I can test and roll out new features in a controlled manner independently of production pushes. Feature switches enable me to keep the development branch in Mercurial very close to stable branch and push bugfixes,  not yet polished code and new features on the site daily without exposing anything to the public before the code is ready and tested (live with betatesters). When I want to publish a new feature, I go to the admin, flip a switch, and it’s live. Boom! Also, if there are any problems, I can just as easily flip the feature off again, and fix the problem with no hurry. Feature switches are awesome. There are lots of different apps for Django for doing this, I chose Gargoyle (mainly because couldn’t figure out how to get the newer version called Gutter working). Big props to Disqus folks for yet another awesome Open Source app.

If you’re interested in following the development of site by this lone music loving Django developer, check out @slipmatio on Twitter, on Facebook and, of course, keep in touch with this blog. And if you have been, thanks for reading this far!

(This post was originally posted to my other blog called Spinning Code.)

Django UI in 2005 vs Django UI in 2014

I stumbled across my favourite ever tech talk, the legendary Snakes and Rubies event where Django met Rails, back in 2005. One thing caught my eye while re-watching every minute of the 3-hour event: the Django Web site and the Admin Site app look almost exactly the same today than they did 9 years ago.

Screen capture image from as it was in 2005

Still image of from the Snakes and Rubies video, 2005.


Screen Shot 2014-09-17 at 22.50.28, 2014.


Still image from Snakes and Rubies video

Still image of Django Admin Site from the Snakes and Rubies video, 2005.


Screen Shot 2014-09-17 at 22.58.44

A screencapture of one Django Admin app (in Finnish — it still talks also Welsh, among others), 2014.


I don’t want to comment this in any other way but to notice that it’s quite amazing that still looks so good and I actually like using it every single day — it works really well. Way better than most newer homepages of other open source projects.

Granted, the Admin app looks a bit more dated, but not too much. And for its purpose, it too works still really well.

Wilson Miner is one kick-ass designer.

And Wilson, it’s not just a Web site. 🙂

(This post was originally published on my other blog called Spinning Code.)

Why I Love Python And Hate Java

Java and Python processes

These backgroundtasks running Java processes — after tuning for minimun memory consumption — eat 20 times more memory than my whole Python Web app. Nice.

(This post was originally published on my other blog called Spinning Code.)

My Stumblings With Logstash And Kibana

I’ve started a project of building a Web toolkit for DJs and in the process I’m constantly learning more about running a Web server [^1]. Being a huge data nerd one of the first things I wanted to install on the Linode VPS were Logstash and Kibana. Lots of data. Lots of pretty graphs. Drool.

[^1]: I’m a language geek. And, being a nerd and pythonist, I’m stealing my writing style from Django. How nerdy is that! In a related note, English isn’t my native language (hello from Finland!) and I know that I’m not very good at writing English. But I try. And I am a language geek.

And it was supposed to be easy.

But based on 15 years of experience, it very seldomly is.

Logstash and Elasticsearch-backend installed nicely (on Ubuntu 14.04 Server) from a .deb package, Kibana was basically all-manual install from source, but it’s JavaScript and a NginX vhost is very simple to config, so it wasn’t so bad. First test inputs worked perfectly and the first little bits of data were already making the Kibana look cool. How nice!

But after adding some initial configuration files to gather logs from NginX, Apache and syslog, Logstash wouldn’t collect data when started from init script. I was dumb enough not to try running it with –verbose flag, so it was only after a couple of hours (yes) head scratching, an unhelpful visit to Logstash irc channel, and a post to google user-group and a very fast and helpful answer when I figured out that I needed to set up a SINCEDB_DIR environment variable for the script to know where to store its internal metadata. Somehow that seemed really weird problem to have for a program that had been installed as a service from a .deb package.

In an unrelated learning experience, I had hard time figuring out how the Logstash configuration files work. The documentation let me thinking that I was supposed to write one config file with input, filter and output section for every log I wanted to consume. But it turns out that while you can have multiple inputs and filters, you only should have only one common output section for all of the logfiles (if you want to collect all of the logs to one same place). I figured this out only after the data was showing multiplied in Kibana. So eventually I ended up collecting all of the configs in one big file with huge input section covering all of the logs I wanted to parse, huge filter section matching the inputs, and one small output section that forwarded everything to the Elasticsearch backend.


But at the end of the day,  I got myself an awesome, beautiful frontend to all of the server logs. And yet another a reminder that I’m not a true nerd but a wannabe.

(This post was originally published on my other blog called Spinning Code.)