February 19, 2014

Don't group your problems

At some point in the early afternoon, I got a to-do list. I had the project manager in a screen share showing me the problems she was seeing, and in another window a tech lead giving me feedback on a Github pull request. They were all mostly linked to this one component, so with three new items on my list, I thought, hey, I can refactor this and take care of all of them.

Wrong.

By mid-afternoon I was hopelessly mired, with a new template taking a ridiculous number of arguments, and at the same time Not Working At All, and I couldn’t figure out which of the several parts I had in the air was causing the problem.

Instead of bulling through, though, I finally learned something. I stopped, and threw away all the changes I’d made. I looked at just one item on the list, the pull request feedback. It was just changing some IDs on some tags. I changed the IDs and updated the pull request. Simple.

Next item. A status indicator shared between windows wasn’t cleared if one window was closed while in an error state and another one was opened. I had been trying to reset it on window close in my Brand New Super Component, but instead I figured out how I could essentially initialize it on window open without touching the existing component. (In the process I learned a little about how to call controller methods from a route in Ember.js, which was a bonus.)

Now I had two items cleared off the list, and I was free to fix the third in any way that worked. And, yes, I created a new component slightly different from the original one, but now I only had to solve one problem, so my new one was not as ambitious and didn’t require as many complicated changes. And it worked.

We’re gonna make an engineer out of me yet.

Posted by pjm at 7:08 PM | Comments (0)

February 4, 2014

Bootstrapping exercism.io

I posted a few days ago about starting out with exercism.io, a platform for doing coding exercises and having your solutions workshopped by others.

It turns out that exercism is an interesting illustration of a classic social-software platform: scaling.

The mechanics of exercism work like this: you submit your first exercise solution. Then you wait for feedback, and iterate. Once you’re satisfied with your solution, you can mark the exercise finished, and once you’ve marked a solution finished, you can start giving feedback to others on that solution.

If you’ve submitted a solution to an exercise, you can start another one in that language, even if you’re still iterating on the first one. This makes a lot of sense, because it turns out that you may be waiting a while for feedback. Essentially, there’s no barrier to joining the site and starting to do exercises, but because you need to have completed an exercise (possibly iterating three, six, even ten times on it) before you can start critiquing others, every exercise is almost guaranteed to have a much higher number of programmers submitting solutions than programmers reading and critiquing.

This can get pretty frustrating for a beginner. I sat on my first Ruby exercise for almost a week with no feedback until I got some. I iterated, and waited another four days until I got a “looks good” which I took as enough reason to mark it completed. (My submission for the next exercise has been sitting for six days without feedback.) I have three Coffeescript exercises waiting for critique, and one each of Ruby and Coffeescript waiting for me to start working on solutions.

The only way around this is for those of us who’ve finished any exercises at all to provide as much feedback as we can to others, and try to increase the pool of readers that way. I’m making an effort to provide as much feedback as I can to others working on that exercise, but probably what I’m doing is creating more work for whoever has completed the next exercise. The Ruby community is clearly larger than Coffeescript - whenever I look there seem to be around 70 active Ruby solutions waiting for feedback, but often there aren’t any Coffeescript solutions. So if I want others to be reading my Coffeescript, I need to be critiquing theirs…

ETA: And after I hit publish, I look at Twitter and see they’re aware of the problem.

Posted by pjm at 8:55 AM | Comments (0)

January 26, 2014

My new coding workout

I’m not going to detail the web-surfing path which led me to discover exercism.io, but I am going to explain why I like it.

The concept is this: exercism by itself is a small command line utility. When you run exercism fetch it gets you a programming exercise, which amounts to a README file and a test suite. The website describes how to set up the command line utility, and how to run the tests in each language supported. It uses GitHub for authentication and to serve the activities; I suspect there’s some git involved in storing the completed solutions as well.

The interesting part is what you do once you have the activities. You don’t just write code to make the tests pass, although you could. You submit your code to the site, and people who have previously completed the activity critique it. There’s a lot of effort put into emphasizing that this should be constructive criticism, and so far it looks like it has been. You get to respond to the criticism or iterate your solution to incorporate it (hence the constructive criticism; it’s more like you’re workshopping your code than being graded on it).

Currently 12 languages are supported, mostly of the “trendy” variety. Perl5 is offered but not PHP. Go, Clojure, Haskell and Scala are offered but not Java or C.

I’m using Coffeescript a lot in my new job, so I’m using these exercises to get my mind used to the idioms of that language rather than leaning heavily on its Javascript basis. I’ve also started doing the Ruby exercises; it looks like there’s a much deeper user base in Ruby, and maybe more exercises there as well (it’s hard to tell until I get deeper). My motivation for trying Ruby is not that I think I need practice but that I think the exercises may teach me some new ways of approaching problems in any language, whereas in Coffeescript, so far, I’ve understood how to solve the problems, but not how to solve them in a Coffeescript way.

This isn’t a site for learning a language; if you’re not at least competent as a programmer the first exercise is going to be frustrating. The parallel with a spoken language would be a “conversation class” rather than a “teaching class”. I’m debating starting the process in Javascript, as a complement to the Coffeescript work; Python is another language where I only barely know it, but might benefit from some work in the idiom.

Posted by pjm at 8:34 PM | Comments (0)

June 27, 2013

Target your recruiting

I’m debugging some Javascript on a page which embeds a Prezi slideshow. It turns out that one of the scripts Prezi loads writes this to the Javascript console:

If you find digging around in stuff like this fun, you might want to take a look at our job page: http://prezi.com/jobs/ :)

I have to wonder if they find anyone this way, but given how specific it is—it’s unlikely this message reaches anyone who wouldn’t be at least a little qualified—and how low the cost, it’s a pretty efficient recruiting message.

Posted by pjm at 2:52 PM | Comments (0)

June 5, 2013

JavaScript testing for Rails 3.2 by integrating Jasmine

I wanted to write unit tests for JavaScript components of the Rails application I’ve been working on recently, and intended to use the Jasmine framework to do it. However, I found a lot of conflicting information about what the current incantations are for making this work properly, and a near-total lack of documentation for my particular setup. Consequently, I’m documenting my process here, in hopes that it will help someone else.

The application uses Rails 3.2 (actually 3.2.13 at the moment). I made a false start using the jasmine-rails gem, but in the end I had two big problems with that: the rake task which was supposed to run the tests couldn’t find the Jasmine library, and while Rails was able to mount the Jasmine engine, it wasn’t loading the scripts I intended to test.

I dumped that branch and went back to master and started over. Following the tip on the Jasmine page linked above, this time I tried using jasmine-gem. (It was v1.3.0.) I installed it as directed on the gem’s README page, specifically by adding gem 'jasmine' to the project’s Gemfile, running bundle install, and then rails g jasmine:install and rails g jasmine:examples.

(In the end I didn’t commit any of the code generated by the jasmine:examples generator, but it was illuminating.)

The gem then suggests starting a server with rake jasmine, and sure enough, that worked. It took a bit to get the server seeing the code to be tested, however. This involved tweaking the spec/javascripts/support/jasmine.yml file to include the proper set of scripts. Specifically:

  • The src_dir value needed to be public/assets. This Stack Overflow question pointed me in the right direction. I had to add a manifest file (i.e. assets/application.js) to the src_files array as well in order to include the script containing the code I wanted to test.
  • I needed jQuery to be available to Jasmine. jasmine-jquery turned out to be the solution here, not because it itself is useful (although it is) but because it pointed out that I needed to add jQuery to my src_files file. (It isn’t in my manifest because I’m loading it from a CDN.)

Now I had running Jasmine tests. (Once I wrote the tests, of course, within the spec/javascripts directory. More on this at the end.) However, my rspec unit tests for Ruby code run automatically when I change the relevant files (either the code, or the test code which tests it) so I don’t need to kick off a test run to see if I broke something. I use Guard for this. (Currently v1.6.2.) I wanted Guard to run my Jasmine tests as well, so I’d get the same kind of instant feedback for JavaScript that I get for Ruby.

For this I wound up installing guard-jasmine. (This was v1.16.0.) Once that was in my bundle (add to Gemfile, run bundle install, rinse, etc.) I ran guard init jasmine and it added a block to my Guardfile to watch the JavaScript files and Jasmine specs.

Running this was a little trickier, however, because once again I needed to train it to find the code I wanted to test against. This required me to install jasminerice (v0.0.10), even though I don’t need that gem’s primary function. Once I had that in my bundle and had created a spec/javascripts/spec.js.coffee file (essentially a manifest file for my Jasmine specs) and a placeholder spec/javascripts/spec.css file, this worked fine. I had to restart Guard to make sure it found and started a Jasmine server properly, but it was running the specs I’d written previously with the free-standing Jasmine and they were passing.

Now, about that test code:

There was a step 0 to this process which I had previously stumbled on but hadn’t really faced before, which was that in order to test JavaScript, one must have testable JavaScript. A recent article in A List Apart addressed this quite nicely; in short, instead of the usual written-three-lines-at-a-time soup of jQuery functions that normally come along with a Rails application, you want to build real JavaScript objects; then your test code can instantiate those objects and run assertions against their behavior.

Posted by pjm at 1:59 PM | Comments (0)

May 16, 2013

Running the 118th Boston Marathon

If you want to run the 2014 Boston Marathon (a.k.a. the 118th), you have a tough road in front of you. I’ve had a few people ask for advice for getting in. Until we hear more from the BAA, it boils down to: first, get a BQ. Second, get the best BQ you can. Third, pay attention.

There is a lot of discussion about the B.A.A. making allowances for the 118th, relaxing the standards or raising the entry cap. I’ll address this later. Until an official announcement is made, we’re playing by the usual rules, except that there are several thousand runners—those who weren’t able to finish the 117th when the finish line shut down—who will be offered automatic entry, thus beginning to fill the field before registration even opens.

If you already have your BQ, that makes things easier. If you don’t have a BQ, you’ll need to chase one (and if you do have one, you may still want a better time; I’ll get to that later too).

Chances to chase standards are pretty sparse right now. The reason is pretty simple: in most of the country, it’s already too hot to run a fast marathon, and if it isn’t, it will be soon. Entry is scheduled to open in September, so there may be a chance to run a BQ in September (the actual opening date hasn’t been announced yet), but October is almost certainly too late.

It sounds like relatively few people are trying to jump in marathons right away, which is sound; it may be possible to finish a marathon on a month’s training, but running a BQ is not that easy for most.

If you can be ready within six or eight weeks and can travel anywhere, some options open up. There’s Grandma’s in Minnesota, if that hasn’t filled; that’s in mid-June. Likewise the Mayor’s Midnight Sun Marathon in Anchorage, Alaska. There are plenty of races on the calendar but many of them are e.g. trail marathons, actually known for being challenging due to heat, or otherwie tough qualifiers. (There should be extra points for anyone who gets a BQ at the Johnny Miles Marathon.)

Even if you’ve got a BQ under your belt already, the increased demand for the 118th may pose a challenge. It’s been a few years since a BQ meant your entry was assured; more recently, faster is better. Essentially, the faster your BQ, the earlier you get to register, and the more likely your registration will be successful. Therefore, there are BQs, good BQs (5-10 minutes faster than cutoff) and really good BQs (10+ minutes faster than cutoff).

If you’ve got a really good BQ, you’re probably in. If you’ve got a good one, I wouldn’t make promises, but you’re probably OK. If you don’t have a good BQ, you might want to think about improving it. For that, you’ll want to look deep into the summer, even into early September, with the idea of getting into great shape in the summer and hitting one out of the park as close to the registration opening date as you can. You could do worse than to look at Clarence DeMar for this one. (Someone needs to come up with a circuit of races named for Boston champions.)

Finally, pay attention and be ready to change plans if things come up which help you. I’ve already heard of one pop-up marathon scheduled for late summer expressly to give people a shot at qualifying; odds are there will be more. Look for one with a speedy, certified course (I can’t emphasize this point enough), chip timing, and an early-morning start (or other accommodations for heat). It may even be a good idea to have a Plan A and a Plan B.

Now, about the BAA: One thing they understand is that while they own the Boston Marathon on paper, in practice it’s a sort of public trust. They are going to do whatever they can for the 118th, and I expect they are exploring the option of a one-time raising of the entry cap. (The idea of a lottery, the way they ran it in 1996, has been floated as well, but in my opinion that’s not going to go over well if they can’t first allow in all the BQs who wish to run, so if I wanted to run I would be looking for a BQ before I put my hopes in a lottery.)

The hangup is that the field limit is not set arbitrarily by the BAA; it’s a limit more or less imposed on them by the towns the course passes through, principally Hopkinton, which has to support the starting area. Hopkinton becomes the running community’s public urinal for a few hours every April and bears it with remarkable good grace, but they have much less open space now than they did in 1996. Staging 30,000 or 40,000 runners through that town, if it’s allowed to happen, will take a lot of time and patience.

If the cap is lifted for the 118th, we will all owe the towns, especially Hopkinton, a greater-than-usual debt of gratitude. So watch where you relieve yourself, please, and where you toss that empty gel packet. (I am still finding empty gel packets on the Natick roadsides a month after the race.)

The BAA is still clearing up the mess from the 117th, and they have a half-marathon to think about in October. I would not expect an announcement about the 118th until late June at the earliest, and July or August is more likely. Stay tuned, and if you want to run, start staking out that really good BQ.

Posted by pjm at 7:45 PM | Comments (0)

February 23, 2013

"Vehicle Protection Center": stay away!

Paper spam, today. An official-looking mailer (fold side edges, then remove top stub to open) starting with bold, underlined text, “THIS LETTER IS TO INFORM YOU that if your factory warranty has expired, you will be responsible for paying for any repairs.”

Read that sentence again, because I did. Rephrase it: “If your umbrella is closed, you will get wet when it rains.” When I read obfuscation like that, I get suspicious immediately. All caps PLEASE CALL IMMEDIATELY in the next block of the letter really raises my hackles, just because I get ornery when I feel like I’m being herded.

Sure enough, despite including the make, model (Honda) and year of one of our cars, this mailing had nothing to do with Honda, and probably not with any other manufacturer. In fine print at the bottom, “Vehicle Protection Center is an independent nationwide company marketing vehicle service contract on behalf of leading third party administrators.” Which means nothing. Third sentence of that paragraph: “Vehicle Protection Center is not affiliated with any auto dealer or manufacturer.”

Here’s the thing: I never had any intention of purchasing an extended warranty. I turned it down when we bought the vehicle. Our history is of driving cars for years—decades, now—beyond their warrantees, and if they break, we pay for it. (Revolutionary, I know.) So I looked these folks up online. Sure enough, I don’t have to scroll too far down in the search results to find a page titled “Don’t be fooled by this vehicle extended warranty mailer from Vehicle Protection Center”.

This mailer is sleazy, and I’m posting this not because I think my regular readers would be fooled, but because I want that link above to come up closer to the top of search results.

Posted by pjm at 8:14 PM | Comments (0)

December 8, 2012

The webmaster's guide to passwords

Here’s the short summary: if you’re storing user passwords unencrypted anywhere, you’re doing it wrong. If you don’t understand why, you should stick to using free open-source packages like Drupal and not roll your own login system. Also, if you’re not a webmaster, and you ever get an email from a website which provides your unencrypted password, you should know that this site is probably not doing a good job storing your password securely.

The problem is this: sites get hacked, and databases get compromised. Encrypting the connection (your SSL certificate, the https in the address bar, and all that) just protects the customer’s communication with your server. It’s nice that they’ve stopped crackers from harvesting passwords one by one as their users provide them, but what’s the point if a successful compromise of the server means everyone’s passwords are available to the cracker?

The first thing you need to know (if not understand) is that there are certain functions which are one-way; that is, the input cannot be determined by the output. Some of these are called hash functions. If you run a sufficiently strong hash function on a password, it is not possible to determine the password from the hash. (The output of a hash function is sometimes called a hash.) (Hash functions are like padlocks: some are stronger than others. But even a weak lock is better than none at all.)

“But wait,” the inexperienced webmaster says, “how can I tell if my user is providing the correct password when they return to the site?”

Well, think about it. They’ve stored a hash produced by running a hash function on their password. Why not run the same hash function on the password provided at login time and see if the resulting hash is the same as the one in the database? Problem solved.

(N.B. You might also want to read up on “salt.”)

Posted by pjm at 9:22 PM | Comments (0)

November 19, 2012

Tally another rodent

Most of my public internet trail recently has been about little girls, and Izzy has not been getting his proper attention.

Therefore, I should announce that this morning he presented for tagging his first mouse of the season. (Mouse hunting season in most of the states he’s lived in runs from September 1 to August 31.) This is his first mouse of his second decade of hunting.

I was thinking about his record today, and unless I’m forgetting some, of the six places we’ve lived with him, he’s caught mice in three, and in a fourth he caught three bats(!) which I count as mice with wings. He also caught a mouse once while visiting A’s parents, so I make his total somewhere around eight non-flying mice and three flying mice.

I have a hunch he’s not done in this house, either.

Posted by pjm at 9:37 PM | Comments (0)

November 12, 2012

What if?

I don’t remember when I started reading XKCD regularly, but their new “What If?” feature has me stifling inappropriate laughter on a regular basis.

An example: a recent piece on the probability of electoral ties compares the odds of nine swing states all producing equal vote totals for the top two candidates with the odds of some fairly unlikely events, including being struck by a bale of cocaine dropped from an airplane, a tornado, and a meteorite strike. (Along the way we learn that a typical location in Florida “…experiences an average 1.4 picotornados per second … a Florida resident suffers an average of 0.64 femtodeaths per second from meteorite impacts … the average person in Florida is struck by an average of 29 zeptobales of cocaine per second” and the average income of a typical acre of Florida land derived from falling bales of cocaine.)

So if you like the absurdum part of reductio ad absurdum, you’ll like What If?

Posted by pjm at 9:21 AM | Comments (0)

October 25, 2012

Now I know a little more about rake-pipeline

I’ve been doing a lot of work recently with a Javascript framework called Ember.js. In production, it asks the user to load a single Javascript file up front, and then runs the whole application in the browser. With a medium-sized or bigger project, you need some kind of build toolchain to take the many smallish code files you’re working on and bundle them up, both for production and also on an ad-hoc basis as you’re working. The toolchain I’m using is called rake-pipeline (rakep for short) which is just some sugar layered over rake which is really just ruby scripting.

If you haven’t glazed over yourself by now, bear with me.

(Aside: All of this stuff has been generated by a culture of companies, mostly but not exclusively on the West Coast, building tools for their own use and then publishing the good stuff—whatever’s not central to their real business—free, open-source, for everyone else’s benefit. It’s pretty awesome and I try to contribute my own tweaks back when I can.)

If you haven’t used Ruby but are familiar with software, Rake is just make in Ruby. rakep reads an Assetfile which is the equivalent of Rakefile in Rake or Makefile in make. I hadn’t seen the syntax before but I could sort of suss out what was going on.

I’ve been using git post-commit hooks to generate a one-line Javascript file which contains a “version string” that’s just the hash of the most-recent git commit. Displaying this string in the application helps me tell if I’m looking at the most-recent version of the code, or an older build. However, if someone else doesn’t have my hooks installed, that file isn’t generated, and their application won’t load. I needed a better way.

First I looked at Flame.js, a widget library for Ember which I’ve contributed to several times over the last few months. Flame generates a version constant by generating a temporary version.js file in ERb, Ruby’s built-in template language, using Ruby to send git describe --always --dirty --tags to the shell and planting that in a temporary .js file. Flame, however, uses its own Rake tasks to build its distribution versions, and runs Sprockets over all the input files to handle Sass, and rakep uses neither Sprockets nor Sass, (at least not explicitly). I couldn’t just borrow stuff from their Rakefile, nor could I drop an .erb file into my code directory and expect it to Just Work.

I looked at the filters that were included, and discovered that Yehuda Katz’s rake-pipeline-web-filters library (which was already in use - Katz is a core team coder for Ember) includes a Tilt filter. Tilt is a sort of “send me anything and I’ll decode it” filter, and it will handle ERb. So I explicitly required Tilt in my Assetfile, and added this block before encoding of Javascript began:

  match 'lib/version.js.erb' do
    filter WebFilters::TiltFilter do |input|
      input.sub(/.js.erb/, '.js')
    end
  end

What that wound up doing was taking my version.js.erb file and generating a temporary version.js file which was then included along with the rest of the files as though it had been there all along. It’s not in with my regular code, so it doesn’t get committed to git itself, but it’s included in all the build files. And because the Assetfile is part of the project itself, anyone who builds the project (and has included all the requisite gems, has the right versions of Ruby, etc. etc. which they probably do if they’re building this) will get the appropriate version string in the application.

It’s a little thing, but I’m sort of proud of it. I could probably make that first line match 'lib/*.js.erb' and have it work on any .erb file in the directory, but it’s not needed so I won’t bother.

Posted by pjm at 8:42 PM | Comments (0)

September 15, 2012

Which do you believe, the map or the GPS?

If you read my last grumpiness regarding Nike+, you probably know that the answer to the above question is, “It depends.”

It turns out Strava has the same problem as Nike+ when it comes to using the GPS in the iPhone to track runs. Simply put, both apps trust that the GPS track from the phone is 100% reliable; once a run has been tracked, there is no option to correct the track or replace it with something generated from a map.

This would be wonderful if the GPS track was, in fact, 100% reliable. But for some reason in the last few weeks, my GPS tracks have been consistently bad. I’ve had seven-mile runs marked as two and a half, two-and-a-half mile runs marked as three… it goes on and on. I don’t know if the problem is the phone hardware, the apps, local topography, local weather, solar weather, or some combination, but it’s pretty consistently bad.

And it highlights the problem with using GPS tracks to get run distance (or much other run data): GPS as a technology is much more precise than it is accurate. Put another way, like email, GPS is a “best effort” technology (much like email). It can be wrong, and if it’s wrong it will not apologize nor necessarily admit the error.

So why don’t either of these logging systems accept an alternative? All they need is an option—it can be on the website, it doesn’t need to be right in the phone app—to indicate for a given run if the GPS track is actually correct. The user could have the option to upload a .gpx file with a better map track if they want to generate one with another app. (It’s hypothetically possible to use the Gmap-pedometer to create a gpx file, and use that to record a new run with Strava, but so far the gpx files I’ve tried uploading to Strava have failed.)

Introducing this option of human oversight is a simple way of accounting for GPS’s lack of accuracy. I’m sure most of the app developers want to avoid that degree of complication, but in doing so, they’re placing more trust in a fallible technology than it really deserves.

ETA: So the issue with my GPS inaccuracy turned out to be the iPhone and not the apps. Still, how do I correct the logs?

Posted by pjm at 1:40 PM | Comments (0)