Can I get a witness? 5

Posted by Piers Cawley Mon, 19 Nov 2007 19:17:21 GMT

Worrying about test coverage when you’re doing Test- or Behaviour-driven development is like worrying about the price of fish in Zimbabwe when you’re flying a kite.

Your tests are there to help you discover your interface and to provide you with an ongoing stream of small bugs to fix. If you write them cleanly, and keep them well factored (you are refactoring your tests, aren’t you?) they will help to document your intent too. Ensuring that every code path is exercised might be intellectually satisfying but that satisfaction costs time, and time is money. And that’s before you start worrying about your code’s malleability. Cover the happy path and the edge cases you know how to deal with and move on. If you’ve screwed something up, it will get found during acceptance testing (or out in the wild) and you can write a few more tests to isolate the problem, fix it, and move on.

If you deliberately add a test that passes without requiring you to write another line of code, ask yourself why you bothered with it. The test isn’t isolating a bug or specifying new behaviour. If you’re lucky, it merely confirms something you already know, and if you’re unlucky, you just introduced a bug in your test suite. Better to move on and either pull a new bug off the queue, or turn a feature request into a new bug – “Feature X doesn’t work!” – fix it, refactor and move on to the next. Further down the road, you may discover that the feature you were about to exhaustively test doesn’t even need to be there, or maybe it works differently than you expected. Aren’t you glad you didn’t worry about 100% coverage then? Maybe you will need to revisit the tests and cover more cases in the future. But future you knows more about the problem domain and can do a better job of working out what the behaviour needs to be. And if future you is likely to do a worse job than you right now, you may have bigger problems than the code to worry about.

So... I was wondering 3

Posted by Piers Cawley Sat, 17 Nov 2007 18:54:23 GMT

Has anyone written an Atompub client in JavaScript yet?

An announcement 2

Posted by Piers Cawley Sun, 04 Nov 2007 11:59:43 GMT

Do you have a PC, Xbox 360 or anything else that will run the Valve Orange Box? If so, get hold of a copy and fire up the Portal subgame.

That is all.

Things that make a developer cry 6

Posted by Piers Cawley Fri, 02 Nov 2007 14:49:00 GMT

So, we’re doing a cobranding exercise at work. The idea being we serve up a branded version of amazing tunes in a subdomain of our partner, their users get a skinned version of the site that feels like part of the partner’s site, we get an influx of new users and everybody is happy. One aspect of this is we’re using the partner’s site to handle authentication.

Today, we got all our ducks in a row and started authenticating against the partner’s SOAP service as part of our user testing. So off I went to the partner site and set up an account…

At amazing tunes, we’re pretty scrupulous about password security, we never store plaintext passwords, any request that involves a password being sent is done over an https connection. It’s just the right thing to do.

After I’d finished setting up my account on the partner’s website I was presented with a screen that looked something like:

Your username is: pdcawley

Your password is: fucknuckle

At least it was an https connection, but it doesn’t exactly fill me with delight.

Leopard Polish

Posted by Piers Cawley Tue, 30 Oct 2007 14:27:25 GMT

Yes, I’ve upgraded to Leopard. Yes, it’s spiffy.

The headline features like Time Machine are great, but I’m loving the little details more.

For instance, the first time you go to run an application that’s been downloaded from the net, a dialogue pops up reminding you that the file has been downloaded and asking if you want to trust it. It’s a nice bit of security, and it asks you the question at the right time.

Tiger asks a similar question, but it does it at entirely the wrong moment. What happens is that Safari stops and shows you a dialogue that says something like “The file you downloaded may contain an application, do you want to continue?”. Well, of course I want to continue, I’m surfing the web, not trying to run this new app. My reaction to this sort of dialogue is to think “I just don’t care about that right now, go away and stop annoying me!”.

The way it works under the covers is pretty neat too. With any luck the OS X Finder team will take a leaf out of its book and think about replacing those annoying .DS_Store files with directory metadata along the same lines. But I’m not holding my breath.

Time flies when you're enjoying yourself 2

Posted by Piers Cawley Sat, 27 Oct 2007 10:37:42 GMT

It’s been a while since I wrote anything here, mostly because I’ve been indecently busy. Well, up until last Sunday when I managed to trip over a low wall in our garden and, in the process take off a large amount of the skin on my left shin. A mere flesh wound, but painful, embarrassing and it’s left me sporting what looks like a foot long, white, elastoplast. The worrying bit is that, when I went to get my wounds dressed, the nurse took one look at my bulk and demanded a urine sample. Which tested positive for glucose. For the second time in a year. So, interspersed with getting my dressings changed at the GP’s, I got a blood test and it looks like I’m diabetic.

Given my weight and what I understand about the workings of late onset diabetes, it’s not really surprising. I’m sure it’s better to get an early diagnosis than a late one, but it does rather give one pause for thought. Somehow I doubt I’m going to find it easy to change my diet and lifestyle; if it were easy, I would have done it already. I like food. I don’t like exercise – it’s a pain in the arse, time consuming and boring. About the only form of outdoor exercise I ever enjoyed was sailing, but the old adage that you can recreate the sensation of sailing by standing in a cold shower tearing up 50 pound notes is depressingly accurate and I simply don’t have the 50 pound notes to spare.

Crap.

Anyway, normal blogging service should be resuming shortly; I’ve got a couple more nouns to write up as essays, and a long, half written, tutorial on writing pidgins in Ruby. Watch this space.

Rails tip: Side effect filters

Posted by Piers Cawley Mon, 08 Oct 2007 12:13:00 GMT

Some bugs are easy to overlook. One that has a habit of catching me out is a Rails filter that returns false occasionally when it’s being evaluated purely for its side effects. Here’s how I’ve started working round the issue:

def side_effect_filter
  return if some_conditions_not_met?
  ...
ensure
  return true
end

What happens here is that the ensure catches any return and returns true instead. The catch is that if something throws an uncaught exception anywhere, it too gets caught by the ensure and true is returned. Which may not be what you were looking for. Here’s how to fix that issue:

def side_effect_filter
  error = nil

  return if some_conditions_not_met?
  ...
rescue Exception => error
ensure
  raise error if error
  return true
end

This catches the exception in a rescue and stashes it in the error variable, then the ensure checks to see if an exception was thrown and rethrows it, otherwise, it just returns true. Which is bulletproof, but ugly. Let’s wrap the ugliness up in a method:

def self.side_effect(method, &block)
  def_method(method) do
    error = nil
    begin
       instance_eval(&block)
    rescue LocalJumpError # catches an explicit return
    rescue Exception => error
    ensure
      raise error if error
      return true
    end 
  end
end

side_effect :side_effect_filter do
  return if some_conditions_not_met?
  ...
end

Again, not pretty inside, but all we actually care about anywhere else is that the interface is good and does what it’s supposed to do. Encapsulated ugliness has its own beauty. Especially if you get the interface right.

Homework

This should pluginize quite nicely, just install the method in ActionController::Base and ActiveRecord::Base and you have a very useful tool, but I’m still not sure that the method name is right, so I’m holding off on it. If someone were to come up with a bulletproof name and release a plugin, that would be wonderful though.

Updates

Fixed a scoping issue in the encapsulated version of the code. Replaced yield with instance_eval(&block)

Typo on Rails 2 1

Posted by Piers Cawley Fri, 05 Oct 2007 20:09:04 GMT

Whee! Sat in my home directory is a version of typo that appears to work with Rails 2.0. I ended up giving up on the themer approach which proved to be very hard to get up and running transparently – things kept disappearing off around infinite loops, which is no fun at all, let me tell you.

So, ended up cheating and ended up monkeying with @@view_paths directly, which is almost certainly against the rules, but has the cardinal virtue of working.

I’m sanguine about it because the way themes worked on rails 1.2.x also involved fiddling with undocumented methods which aren’t there in edge rails.

So, it now remains to walk around the thing, kick the tyres, write a few more tests and generally get myself to the point where I’m happy that it all works, and merge my local branch with the main line. I’m going to wait until 2.0.0 proper has been released, but now that I’ve done the work I expect to be merging it sharpish.

Railsconf Europe Photos

Posted by Piers Cawley Sun, 30 Sep 2007 07:56:22 GMT

James Duncan Davidson

James Duncan Davidson

I’ve finally started uploading the scans from RailsConf Europe last week. There’s still one more roll to scan and another 9 shots in the camera, but I’m pretty pleased with the results so far. I didn’t really start shooting until about halfway through the last day. The light in the hotel was horrible and I just wasn’t in the mood, then suddenly I’d shot three rolls and was wondering where I could find another roll of Neopan 1600 at 9pm in Berlin. It didn’t hurt that I found some really nice light (at least for a black and white photographer with fast film). The shot of James Duncan Davidson above was shot using one of the large LCD screens that were dotted around the hotel as a softlight. It’s the sort of trick that can cause endless pain when you’re shooting in colour, because the white balance is such a bear, but the magic of fast black and white film means I just didn’t have to care.

Later on, I found an even better lightsource – in the atrium there were columns with 3 or 4 big LCDs displaying conference information, which meant they were mostly white. I spent a chunk of the evening grabbing people and asking if I could take their picture in “The best light in the building”. I just wish I’d spotted it earlier in the day when there was more daylight as well, that really would have been gorgeous light.

Today's Noun is: Reticence 2

Posted by Piers Cawley Thu, 27 Sep 2007 23:30:29 GMT

What does the OED say reticence is?

Reticence: Maintenance of silence; avoidance of saying too much or of speaking freely; disposition to say little.

Pretty straightforward. When I chose reticence as one of my five nouns for programmers it was another reminder that objects are not the same as datastructures. Well designed objects keep their cards (instance variables) close to their chest. Client code tells objects what to do, it doesn’t ask them to kiss and tell. In Smalltalk Best Practice Patterns, (you don’t have a copy yet? Are you mad?) Kent Beck recommends that you put your accessor methods in the private protocol unless you have a very good reason for indicating that the accessors should be used by clients by putting the accessors in, say, the accessing protocol or some other, more suitably named, protocol. (In Smalltalk, all methods are public, but you can and should organize them into protocols/categories, either by choosing some existing protocol, or coming up with a new protocol name). In less flexible OO languages, you should probably at least mark your accessors as protected unless you have the aforementioned very good reason.

What about parameter objects then?

One obvious ‘exception’ to the rule of reticence is the parameter object. Say you have an unwieldy method that takes a bunch of arguments and fills the screen with its implementation. Being a conscientious programmer, you want to apply the ‘composed method’ pattern to the method so you’ll still end up with a screen’s worth of code, possibly more, but the individual methods will be much more focussed in what they achieve. What stops you is that bunch of parameters which are used through out the method. So, you introduce a parameter object. Bundle up the parameters into a single object, replace each parameter variable in the body of the code with an accessor call on the parameter object, and have at it. You can extract methods easily and you’ll only ever have to pass a single object.

It’s tempting not to bother creating a ‘real’ object, it’s very easy to just use an options hash, a la Ruby on Rails. And, because the options hash is a common pattern through your code, you can start adding helper methods like with_options, and you’ll get an awful lot of leverage out of it.

However, what’s often missed in discussions of the parameter object pattern is that it’s a waystation, not a destination. It may be handy, but if you persist in treating it as a datastructure, you’re missing out on the good stuff. Now you have a parameter object, you can start to move behaviour onto the parameter object and before you know it you’ll end up with a real object doing real, testable (mockable?), work.

Homework

Find a method where you’re using an options hash. Try using that hash to build a parameter object and then apply the principle of reticence. What happens to it? Where does the behaviour go? If, like me, you’ve come to OO from procedural coding styles, making your objects reticent is not a natural thing to do, it can feel extremely odd. But the more you practice it, the better you’ll get at thinking in a truly object oriented fashion. Sometimes an options hash really is the way to go, but not as often as you’d think.

Try it, maybe you’ll be converted.

Older posts: 1 2 3 4 5 ... 28