Archive

Archive for August, 2010

Avoiding religion in programming

August 15th, 2010 14 comments

Thou Shalt Rend Software and Religion Asunder

Steve McConnell, Code Complete Second Edition

There are numerous infamous religious wars in the world of programming. Windows vs. Unix, Windows vs. Mac, IDEs vs. text editors, Emacs vs. vi, Python vs. Ruby, where to put the curly brace, spaces vs. tabs, 2 spaces vs. 4 spaces; the list goes on ad nauseum. The fact that these arguments never end shows that there is no “true” answer. Usually it comes down to personal preference, which is fine. The problem comes when programmers become bogged down in the arguments, and begin to see their side as “the one true way”. Anyone using the other method is an infidel and must be converted or crushed. Of course, this is often just tongue-in-cheek banter, but all too often it goes further than this.

Most of my friends probably have a preference either way for Coke/Pepsi, and some have explained to me their reasoning. But none of them have ever tried to tell me that I’m drinking the wrong drink, because that would be silly (I hardly ever drink Coke or Pepsi, but that’s a moot point).

Alex Martelli wrote a fantastic essay about the differences between Ruby and Python on comp.lang.python. He makes a thorough comparison, noting what is shared and what is different. He also gives his opinion on why he prefers the Python way, while noting that it is only his opinion (speaking on implicit calling of functions vs. requiring empty parentheses: “I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-). “).

The upshot of all this is my vow to avoid all religion in programming. This is something I’ve been doing gradually for a long time. At one point I only ever used Windows, but reading The Pragmatic Programmer convinced me to try Linux. I started off using IDEs (NetBeans, Visual Studio), but then moved to Emacs. I’ve recently started learning Vim properly, and haven’t decided yet which I’ll pick as my primary editor (because you still need to have favourites!). I’d got to a point where I’d virtually declared Python the One True Language — this led me to start learning Ruby. I use 4 spaces for indentation in Python, and 2 in Ruby. I use spaces instead of tabs because tabs are silly and anyone who doesn’t think so is silly too :). When I use JavaScript I put braces on the same line as the control statement, because that’s what Douglas Crockford told me to do. I do the same thing everywhere else because I prefer it visually.

Now, I know there are a lot of enlightened programmers out there who already work in this way, so good work. But to all the others, have a look through the list of wars at the top of this post, and see whether you might be able to cross over to the dark side, however briefly, and try out your enemy for a bit. At least then you can give an objective argument about why you prefer one over the other (which always beats “x is teh suck”). Hopefully though, you’ll find that these things just aren’t worth arguing over.

Categories: Programming Tags:

Nike: all your runs are belong to us

August 3rd, 2010 1 comment

I like to run, and I like tech, so obviously I like to measure and graph my runs. So I use Nike+. Unfortunately, Nike+ has a rubbish pure-flash website (rant: do people still make pure-flash sites? This is 2010!).

I want a way to get to my run data without having to use Nike’s website, so I’ve decided to code something up. I’m learning Rails at the moment, so I’ve decided to do this as a Rails app. In this post, and probably some subsequent posts, I’ll be showing my progress.

Step 1: getting the data

First off, we need some way of getting the data from Nike. This post on labs.interfacedigital.co.uk shows how to get the raw run data through Nike’s public API. The two URLs we’ll be using are this one for getting a summary of all runs:

http://nikerunning.nike.com/nikeplus/v1/services/app/run_list.jsp?userID=#{user_id}

and this one for getting the details of a single run:

http://nikerunning.nike.com/nikeplus/v1/services/app/get_run.jsp?id=#{run_id}&userID=#{user_id}

The all runs XML looks like this:

<plusService>
  <status>success</status>
  <runList endIndex="-1" startIndex="0">
    <run id="1752070113" workoutType="standard">
      <startTime>2010-02-28T13:24:40+00:00</startTime>
      <distance>6.264</distance>
      <duration>4067000</duration>
      <syncTime>2010-02-28T14:34:16+00:00</syncTime>
      <calories>470.0</calories>
      <name/>
      <description/>
      <howFelt>3</howFelt>
      <weather>2</weather>
      <terrain>1</terrain>
      <intensity/>
      <gpxId/>
      <equipmentType>sportband</equipmentType>
    </run>
    ...
  </runList>
</plusService>

Step 2: read the data

I’m doing the following in a Rails model called Run. The underlying table has fields for the necessary run attributes. I’m not going to go into this in detail because this isn’t a Rails tutorial.

require 'open-uri'
require 'rexml/document'

...

attributes = {
 #:attr         #xml tagname
  :distance   => "distance",
  :start_time => "startTime",
  :duration   => "duration",
  :calories   => "calories"
}

open(all_runs_url) do |f|  #open the XML file using the open-uri library
  doc = REXML::Document.new f.read  #create a new REXML object
  doc.elements.each("plusService/runList/run") do |run_info|  #iterate over 'run' elements
    run_id = run_info.attributes["id"]  #get the Nike id of the run
    run = find_or_initialize_by_run_id(run_id)  #get a new Run object, either from an existing record
                                                #in the database or create a new one

    attributes.each do |key, value|  #iterate through attributes hash, which maps object attrs to XML tags
      run.write_attribute(key, run_info.elements[value].text)
    end

    run.calculate_avg_pace  #work out the average pace
    run.save
  end
end

calculate_avg_pace looks like this:

def calculate_avg_pace
  self.avg_pace = duration_in_minutes / distance_in_miles
end

and uses the following virtual attributes:

def duration_in_minutes
  duration / (60.0 * 1000)
end

def distance_in_miles
  distance * 0.62
end

At some point I’ll refactor so miles/km is an option, but for now I just want to get something working. So far though, so good:

First run listing

First run listing

Next steps will be to make the numbers look a bit nicer, for example by showing average pace in mm:ss. Other than that, who knows?

Links

Categories: Programming Tags: , ,