Archive for October, 2009

Book Review: Net, Blogs and Rock’n'Roll

Friday, October 16th, 2009


Net, Blogs and Rock'n'Roll Cover
One species that has flourished in the world of Web 2.0 is the pundit. Change happens quickly and hard evidence has trouble catching up, leaving a certainty vacuum that can readily be filled by anyone with an air of authority.

While Net, Blogs and Rock’n'Roll is aimed squarely at the Web 2.0-prognostication market it’s far from being the worst example of this: David Jennings draws on plenty of personal experience as well as interviews and systematic research to paint a picture of the way music will be changed as a result of social changes brought about by web technology. Even so, this is fundamentally an attempt to gaze into a very hazy future, and while I found in it some good inspiration, nothing in it felt especially certain.

A particular problem with this book is that it goes on too long, without enough structure to make the purpose of much of the text clear. The last third of the book didn’t seem to add much value and felt more like an overly-extended summary than anything else, and was very hard work to get through.

If you’re in the music industry or a part of the web industry that overlaps with music, then this book is certainly worth reading as part of gathering a wide variety of opinions. There are plenty of insights to be had, if you approach them critically. If your interest in the future of music is more casual then you’re probably better served by tracking events as they happen on blogs rather than spending effort trying to divine the future.

Closures in the real world: Part 2

Sunday, October 11th, 2009

My last post about closures left some details unexplored: I mentioned that I was caught out by the lifetime of variables that are bound into the closure, but I didn’t have time to go into detail.

I’ll try a different example which hopefully illustrates the problem without needing too much background. Suppose we are running a web site with various age-restricted products, and we want to be able to filter out users whose age is over the required limit. We’ll need a predicate that we can pass into filter methods to select the right people.

Furthermore, assume that for some reason we’ve decided that we want to pre-calculate these predicates and store them in an array, rather than constructing them on the fly (yes, the “in the real world” idea is rather failing me here). That is, we want to be able to do something like:

IEnumerable<User> allowedUsers = users.Where(ageGreaterThan[18]);

We need to populate the array of predicates, and the obvious way is with a for loop:

for (int limit = 0; limit < 22; limit++)
{
   ageGreaterThan[limit] =
      delegate(User user)
      {
         return user.Age > limit;
      };
}

We can then test our predicates:

User bob = new User() { Age = 16 };
Console.WriteLine("{0}", ageGreaterThan[6](bob));

This prints “False”, which is not what we expected. The reason for this is that when we construct the predicate, the variable bound in is the same variable in each case. As we run through the loop the variable is incremented, and this affects the values bound into the already-constructed closures. This might not be so surprising with a reference type variable, but we have a plain unboxed int here (and no auto-boxing is going on).

The semantics of closures vary between languages in a way I haven’t been able to pin down, but given that the very concept of a variable changes from one language to another it’s probably not surprising. The way C# binds variables into a closure is to identify the variables inside and outside the closure as being the exact same variable, and it follows that changing the variable’s value via one location affects it’s value in the other.

This was unexpected to me, coming from languages where variables are all immutable. Arguably, it allows extra flexibility, since you can bind a local copy of the variable if you want and then it won’t be affected by changes to the outer variable:

for (int limit = 0; limit < 22; limit++)
{
   int localLimit = limit;

   ageGreaterThan[limit] =
      delegate(User user)
      {
         return user.Age > localLimit;
      };
}

This is what I ended up doing in the Psonar code, but personally I don’t like it. Not only does it clutter up an otherwise quite neat algorithm, it’s not at all clear to the untrained eye what the copy of the variable is doing there. An inexperienced programmer might quite reasonably think that since int is a value type, it would be OK to elide the copy.

The issue of value types having this behaviour was a particular problem for me. One thing I usually assume about value types is that they are safe from action at a distance. This gets even worse when you realise that the closure can have a different lifetime to the stack frame in which it was created – in fact each of the closures we’ve created can have a different lifetime. If the integer variable isn’t boxed (it isn’t), how can the runtime possibly ensure that it survives past the end of the stack frame, and yet gets cleaned up when necessary?

The solution to this conundrum is that something is being held by a reference type, but it’s not the integer variable; it’s the closure. And that int variable isn’t a property of the stack frame that the closure is borrowing a reference to, it’s a property of the closure that the stack frame is borrowing a reference to.

disassembly

The disassembly shows the class that represents the closure, and you can see the public int variable on it. I’ll spare you most of the MSIL code, but here’s an illustrative snippet:

 IL_0039:  ldfld      int32 ClosureTest.Program/'<>c__DisplayClass2'::limit
 IL_003e:  ldc.i4.1
 IL_003f:  add
 IL_0040:  stfld      int32 ClosureTest.Program/'<>c__DisplayClass2'::limit
 IL_0045:  ldloc.2
 IL_0046:  ldfld      int32 ClosureTest.Program/'<>c__DisplayClass2'::limit
 IL_004b:  ldc.i4.s   22
 IL_004d:  clt
 IL_004f:  stloc.3
 IL_0050:  ldloc.3
 IL_0051:  brtrue.s   IL_001a

This represents the end of the for loop. We load the field from the closure, add the literal value 1 to it, then store it back on the closure. Then we load it again, compare with 22 and branch back to the beginning of the loop if it’s less. Note that this is the logic for the for loop variable, which only looks like an ordinary local variable, in fact it’s operating on the member of the class representing the closure.

Workarounds are not good enough

Friday, October 9th, 2009

As part of my ongoing quest to introduce my girlfriend to the world of video games, last week I purchased the first episode in the series of Wallace and Gromit games, released by the studio Telltale Games. Précis: A harmless piece of “use wombat with lawnmower”-style point and click adventuring, that stays admirably true to the original source in tone and character animation, but with a fairly weak narrative drive.

I have just one problem with this game: It doesn’t run if you are connected to the internet. Not even slightly. It crashes hard. It’s 2009 and Telltale Games are apparently not testing their games on computers connected to the internet.

I don’t wish to be too hard on Telltale Games. Clearly it doesn’t have this problem on every computer; it’s probably down to the OS, or the video card, or the virus scanner, or one of many other similar variables. Testing on every combination is combinatorially impossible, so these problems are going to slip through QA and appear in production. The standards are low in computer games that retail below £10, and rightly so.

What bothers me is that once this bug was discovered in production, frequently enough to be discussed in their forums, their response has been nothing further than to suggest a workaround: disconnecting from the internet while you boot the game. Apparently in the months since the problem was discovered they’ve made no attempt to fix it, even in copies downloaded by new customers.

Again, I don’t wish to single them out. These problems are endemic to the industry, but I’d like to know why. We wouldn’t accept a kettle that emitted smoke or a watch that didn’t work on thursdays. Surely the bug must be simple to fix, and surely it will help to reassure customers who might be considering a follow-on purchase that they can expect a quality product?

I’m sure some will argue that this is a free market, and that the market is merely reflecting consumer preference. This is certainly true, and if the only way to change it were some form of coercion, I’d be happy to leave things as they are. But it seems to me that a world of poor expectations and shoddy code is just one stable solution to the differential equation that governs the software industry. I don’t believe that quality products and satisfied customers are an impossible goal, but the question is how to get from here to there.

I don’t have any answers as to what is holding us back, but one idea does occur to me. It’s worth noting that workarounds are much more prevalent in software than other industries, for purely technical reasons. I struggled even to come up with a hypothetical example where an engineering fault in an electrical appliance could be righted by an untrained user’s actions, but this is commonplace in software.

Maybe the presence of workarounds is part of the problem. Consider the classic 4-quadrant task planning diagram:

Workaround quadrants

The workaround doesn’t make the bug much less important: it still reflects badly on your company. However, it becomes much less urgent, and moves from quadrant 1 to 2. It’s well known that companies tend to spend too much time in quadrant 3 to the detriment of quadrant 2.

Even worse, it’s hard to tell when something is really important to your company, and I suspect a lot of time is wasted in quadrant 4 as well. Maybe thousands of these tiny misallocations of time are having a profoundly deleterious effect on the industry.