I spent the weekend at the UK Sacred Harp Convention, singing blood curdling hymns to the glory of god, very loudly with a hundred or so others. Great fun so it was. There’s something joyous about hollering out a hymn that opens with the line “And am I born to die?” and ends with the stanza
Waked by the trumpet’s sound
I from my grave shall rise
And see the Judge in glory crowned
And see the flaming skies
Jay Fields responds to on Ola Bini’s Evil Hook Methods? about the common ruby idiom that lets us write:
class Fruit
include DataMapper::Resource
property :id, Integer, :serial => true
property :name, String
property :notes, Text, :lazy => false
end
What Ola and Jay don’t like about that is the way that a single include DataMapper::Resource
actually adds class methods to Fruit because the implementation of DataMapper::Resource.included
looks like:
module DataMapper::Resource
def included(module)
module.send :include, InstanceMethods
module.send :extend, ClassMethods
end
end
Which is a perfectly common idiom nowadays, but which breaks include
’s contract in annoying ways. Jay proposes fixing this by adding a become
method to Object which would wrap the include
and extend
in such away that they’d be called by the including class. Huzzah. And it makes sense… sort of. But it really doesn’t go far enough.
If you asked me to name my favourite radio and TV comedy, the odds are very good that Geoffrey Perkins had a hand in most of them. When I found his obituary in this morning’s Guardian I felt almost physically winded. I never met him, I don’t know anyone who did, but he was someone who helped to make the world a pleasanter place to be in. My thoughts are with his family and friends, who are no doubt even more gutted than I am.
Ruby’s primitives (Strings, Hashes, Arrays, Numbers - anything that has a literal syntax) are fine things. But that doesn’t mean you should use them everywhere. You’re often much better off wrapping them up in your own Value Objects.
Something I was working on at Railscamp this weekend threw up a great example of why it makes sense to replace primitives with more specific objects as soon as possible. Tom Morris asked me to take a look at Rena, an RDF/Semantic Web thingy.
If the last post about our Javascript issues didn’t put you off, then you might be interested to know that we’re hiring. If you’re an experienced, test infected Ruby on Rails programmer with some Javascript and a real world consumer website or two under your belt, and you’re happy to work in Newcastle upon Tyne, then we definitely want to hear from you. I’d probably be interested in at least hearing from you if you’re an experienced dynamic language programmer who has only recently made (or is considering making) the switch to Ruby and Rails. It’s only syntax after all.
Usability testing is wonderful. But wow, its humiliating.
I’ve spent the last few weeks working on the Amazingtunes in page player. Amazingtunes is a music site, so we need to play music. However, we don’t like the way that most music sites work; either the music stops as you go from one page to another, or the player is a huge Flash app running in its own window. There has to be a better way. There needs to be a popup window if you want to eliminate stop/start behaviour, but there’s surely no reason not to keep the controls on the main page.
I’ve just pushed a just about usable (but horribly untested) port of Vassili Bykov’s very lovely Smalltalk Announcements framework onto github. It’s a very raw port at the moment (the interface isn’t what you’d call idiomatic ruby yet), but I shall be working on that soon. Documentation (beyond a synopsis in the readme file) is nonexistent, but I reckon that there’s the core of something useful there (I’ve got plans for using it in Typo as the basis of a Wordpressesque plugin architecture and I need it for my Sooper Sekrit Project too…).
When, in the course of learning about Haskell, I reached the point where I thought I understood what Monads were for, I wrote about it. In the comments, Seth Gordon observed that:
There are two kinds of people who try to learn Haskell: the people who give up because they can’t figure out monads, and the people who go on to write tutorials on how to understand monads.
I remembered this today as yet another git tutorial rolled by in my newsreader. Maybe git is the monads of version control.
Sometimes, for one embarrassing reason or another (usually involving chaotic branch merges…) a database migration can get leapfrogged. When this happens, it’s tempting to renumber the leapfrogged migration, but that breaks any servers where the migration didn’t get renumbered. Here’s how I dealt with it recently:
class MaybeOldMigration < ActiveRecord::Migration
def self.up
unless old_migration_applied?
OldMigration.up
end
end
def old_migration_applied?
# Checks that the schema looks as it should
# if the old migration got applied
end
end
Yeah, it's a hack, but it's a fairly robust hack.IE’s a pain. The particular pain I want to write about is its pickiness about Javascript object literals. Consider the following Javascript object:
{ success: function () {...},
failure: function () {...},
}
If you're used to programming in Perl or Ruby, that trailing comma's perfectly fine, in fact leaving it there is sometimes considered good practice because it makes it easy to extend the hash, just add a new row and leave another trailing comma.The trouble is, it’s not strictly legal to do that in Javascript. Pretty much every implementation out there will allow it though.
Back when I was writing the occasional “How do you find me?” article, I would get some weird ads showing up. On one occasion, I commented that the searcher had obviously just typed a homework question into google and expected an answer. All the ads on that page ended up being for sites that would write your essays for you.
“Hmm…” I thought, “That’s not good.”, and set about adding those advertisers to the block list.
Terry Pratchett once observed that a character of his was anorexic because every time they looked in a mirror, they saw a fat person. By that measure, I’m anorexic, though I tend to avoid mirrors. By more objective measures, I’m morbidly obese - 6’ tall, 346 pounds; the Body Mass Index calculation is never going to give a good number.
To listen to some sections of the press, I might as well be public enemy number one. A drain on the public purse, a morally bankrupt insult to the eye of the right thinking, Daily Mail reading healthy public. Apparently, I have the self control of an incontinent puppy and spend my time sat on my arse in front of the TV or looking at child porn on the internet, constantly stuffing my face with lard and chocolate.
When they tell you to stop because you’re reinventing the wheel, ignore them and carry on building a better mousetrap.
I’m just back from the first Scotland on Rails conference, and a jolly fine conference it was too. Much kudos is due to Alan, Graeme, Abdel and Paul. It was hard to believe that this was the first conference these guys have run and I think all my fellow delegates hope it won’t be the last. As I said in the Pub on Saturday night, I’d had a talk proposal knocked back and, in that situation, it’s terribly easy to find yourself sitting in a session thinking “Bloody hell, my talk would have been better than this!”, but not at this conference.
There’s always a moment, in a perfect tragedy, where you dare to hope that maybe the heroes are going to break the surface tension of the plot and escape. That perfect moment in Romeo and Juliet where, no matter how often you’ve seen it, you hope that this time, Juliet’s message will reach Romeo. Or, when watching Cruel Intentions, you find yourself hoping that the writers have managed to wangle a happy ending.
Who came up with the javascript scoping rules? What were they smoking. Here’s some Noddy Perl that demonstrates what I’m on about:
my @subs;
for my $i (0..4) {
push @subs, sub { $i }
}
print $subs[0]->(); # => 0;
Here's the equivalent (or what I thought should be the equivalent) in Javscript:
var subs = [];
for (var i in [0,1,2,3,4]) {
subs[i] = function () {
return i;
}
}
alert subs[0]() // => 4
What's going on? In Perl, $i
is scoped to the `for` block. Essentially, each time through the loop, a new variable is created, so the generated closures all refer to different $i
s. In Javascript, `i` is scoped to the `for` loop's containing function. Each of the generated closures refer to the same `i`. Which means that, to get the same effect as the perl code, you must write:
var subs = [];
for (var shared_i in [0,1,2,3,4]) {
(function (i) {
subs[i] = function () {
return i;
};
})(shared_i);
}
subs[0]() // => 0
h3. Dodgy Ruby scopingI had initially planned to write the example “How it should work” code in Ruby, but it turns out that Ruby’s for
has the same problem:
If you follow the Ruby blogs, you will probably have seen a bunch of programmers attempting to do something akin to Haskell’s maybe
, or the ObjectiveC style, message eating null.
Generally, by about the 3rd time you’ve written
if foo.nil? ? nil : foo.bar
...
end
you're getting pretty tired of it. Especially when `foo` is a variable you've had to introduce solely to hold a value while you check that it's not nil. The pain really kicks in when you really want to call `foo.bar.baz`. You can end up writing monstrosities like (tmp = foo.nil? ? nil : foo.bar).nil? ? nil : tmp.baz
(actually, if you were to write that in production code, you probably have bigger problems). One option is to just define `NilClass#method_missing` to behave like its Objective C equivalent, but I've never quite had the nerve to find out how that might work. I wanted to write
if maybe { foo.bar.baz }
...
end
and have nil behave like an Objective C nil for the duration of the block, but no longer. So I wrote it. Then I thought about how to present it. I wrote the thing test first using rspec and the whole thing just flowed, but writing up a test first development process for a blog entry is painful, so I've made a very rough (but blessedly short) screencast of the process instead.
:http://www.archive.org/download/RubyMaybeRoughcut/Monad2.mov
That's a slightly reduced thumbnail, the movie is substantially more readable. The bottom pane of the window is the output of autotest rerunning the spec every time either the spec or the implementation changes. The top pane alternates between the specs and the implementation. Generally, every time I edit the specs, a test starts failing and every time I edit the implementation it starts passing again. In the (any) real coding run, there were of course false starts, but generally the specs kept me pretty straight.
A word or two of warning: This is a completely unedited, silent, screen cast, there are typos, backtrackings and other embarrassments. I stopped recording once I'd got 4 tests passing, but this is far from release quality (it's perfectly usable if you know its limitations, but it's not entirely robust).
Please let me know what you think of this. I'm aiming to make a more polished version, complete with voice over and it would be good to know which bits are confusing and need addressing in more detail in the voice over.
I am not a rock star. I am a computer programmer. I think I’m quite a good one.
You are not a rock star either.
387,000 matches to that query. Can we all just… I don’t know… grow up please?
Mutter… grumble… chunter… I’m 40 you know!
Updates
#
I have it on reliable authority that James O’Kelly is a Ruby on Rails Rockstar that would make a great addition to any team!
Remember the good old days? The days before Google? The days before Altavista? The days when a 14k4bps modem was fast? Did I say good old days?
In those days, the web had to be discoverable ‘cos it sure as hell wasn’t searchable. The big, big enabling technology of the web was the humble Go somewhere else
. Placing the links right there in the body of the document turned out to be exactly the right thing to do.
Recently I’ve been thinking about the way that patterns on different scales interact with each other. If you read Christopher Alexander’s A Pattern Language, the first pattern in the book is Independent Regions, which are talked about within the context of a World Government, so it seems like a huge pattern. And it is, sort of, but it’s scale invariant - it applies at the level of countries, but it also applies to states, cities, neighbourhoods, streets, houses and arguably even rooms within those houses.