Real Developers and Kernel Source

June 23rd, 2006

Jeremiah Foster writes about Apple closing the source to the OS X kernel on Intel. I the statement:

Without the ability to modify kernel source serious developers will not touch the Apple platform, maybe that is why the OS X server is not making significant inroads into the server community.

Firstly, serious developers don't really care about kernel source unless they happen to develop kernels or kernel modules. Most developers, both fun loving and serious, develop well above the kernel level and don't need access to its source code. Even the link between serious developers and those that are so passionate about open source kernels, that they refuse to use an OS whose kernel isn't open source is tenuous at best. The kernel is one very small, albeit central, part of OS X and the vast majority of the OS is and has always been closed source.

The connection between the number of developers and the adoption of Apple's server platform specifically is also strange. There's a great range of server software available for OS X, including the Linux staples, Apache, MySQL, PHP, Perl, Python and Ruby on Rails so it is hard to imagine that the lack of adoption of OS X server is particularly because of a lack of software. The fact is that Mac OS has and still is viewed as a consumer OS is significantly hurting OS X's adoption, as is the lack of a clear, long term roadmap from Apple. The truth is that there's a great number of reasons that OS X server isn't taking off, but the least significant of them is the fact that the kernel isn't open source.

Perhaps the question is‚ will Apple have enough innovation to maintain a pipeline of consumer products to remain vital?

Current trends point to yes. If and when being open source becomes important for Apple they are well placed to be able to do that, having gained experience and a lot of tough lessons in building open source communities. Right now, being open source is not a key selling point for Apple's key markets and so they won't hesitate to close source when it suits them.

Keyboard vs Mouse

June 23rd, 2006

Someone, I forget who, pointed to an old article on Ask TogKeyboard vs. The Mouse, pt 1. I found it particularly interesting to read that:

  • Test subjects consistently report that keyboarding is faster than mousing.
  • The stopwatch consistently proves mousing is faster than keyboarding.

I've always been of the mind that GUIs are faster than command lines for any task which you don't do often enough to know off by heart. I imagine the same applies in this case - any task you perform often enough to learn the keyboard shortcut off by heart is faster by keyboard shortcut, otherwise using the mouse is faster. Unfortunately, this means that when you begin using a new command frequently, you have to go through a period of slower use in order to learn the keyboard shortcut, after which you should be faster.

However, the article suggests, but doesn't outright state, that keyboard shortcuts are always slower which I find really quite odd. Perhaps that's not what's meant by the article, or perhaps I'm suffering from the two second amnesia and keyboard shortcuts really are always slower. I'm particularly intrigued to see if anyone has actual user data that shows that keyboard shortcuts are faster, and when they are.

Velocity and Estimate Accuracy

June 21st, 2006

In my previous post on tracking estimate accuracy, Stephen Thorne commented:

I thought the entire idea about estimates is that they should be self correcting? Estimates made in some arbitary numbering system, you sum up the estimates, divide by the time actually taken, then you have an accurate picture of how one developers estimates map to reality…

The ability to map arbitrary estimates to actual time that Stephen refers to is velocity. Essentially, how many points per time period can the team complete? This is a really effective technique if your estimates are consistent. That is, you may find that 3 points takes on average, a day to complete. So your velocity is 3 points per day1. However, if your estimates aren't accurate, you may have some 3 point stories take 15 minutes, and some take a week.

Clearly, estimates that vary by that much make scheduling and planning extremely difficult and reduce the confidence you have in your measure of velocity - what if one week you happen to pick 5 week-long 3s? To avoid this, it's important to try to make your estimates consistent. It doesn't really matter if a 3 is half a day or two days, as long as it is a consistent measure of work.

One of the most common ways that this happens is that the original estimate didn't take into account some prerequisite work that needed to be done. Addressing this problem is why we plan to start brainstorming tasks required when we estimate - hopefully by spending some more time thinking about what's required, we'll find less unexpected surprises.

Another common way that estimates turn out to be wrong is that the team has to pay back code debt as part of the story. This is significant refactoring that will pay itself back over time, but makes the task at hand involve more work than expected.

A less common, but particularly painful case is when unexpected or unplanned dependencies occur between stories. In an ideal world, all stories are independent of each other, however sometimes it doesn't work out that way and it turns out that another story needs to be completed before this one can be. This case doesn't really make for a bad estimate, as much as it throws out the planning for what can be completed. The estimates for each of the stories are probably right, but in the planning game, both stories should have been played in the same iteration instead of just one. As a result, the team needs to drop stories unless they get lucky and have a higher than expected velocity.

1 - Typically, velocity is tracked per iteration and is reported as just a single number rather than "per" some timeframe.

One Reason Unused Classes May Get Loaded

June 20th, 2006

In general, Java classes are lazily loaded into the system, so if you have something like1:

if (System.getProperty("java.version").equals("1.4")) {
    Java14OnlyClass.doStuff();
} else {
    AlwaysAvailableAlternative.doStuff();
}

The code will have to be compiled on Java 1.4, but will actually run on Java 1.3 without throwing a ClassNotFoundException. This trick however can be dangerous, there isn't any guarantee that class loaders will always use lazy loading and even with current class loaders, there are occasionally some surprises.

For instance, if we take that same code and add a try catch statement:

if (System.getProperty("java.version").equals("1.4")) {
    try {
        Java14OnlyClass.doStuff();
    } catch (Exception e) { e.printStackTrace(); }
} else {
    AlwaysAvailableAlternative.doStuff();
}

whenever the enclosing class is loaded on Java 1.3, it will throw a ClassNotFoundException claiming that Java14OnlyClass could not be found, even though that code is never run. The reason is that the class loader will automatically load any classes referenced in a try/catch block instead of using lazy loading.

Somewhat surprisingly though, this search for references doesn't descend into method calls. So to make it work with the exception handling, we could use something like:

private void doStuff() {
    if (System.getProperty("java.version").equals("1.4")) {
        try {
            doJava14Stuff();
        } catch (Exception e) { e.printStackTrace(); }
    } else {
        AlwaysAvailableAlternative.doStuff();
    }
}
private void doJava14Stuff() throws Exception {
    Java14OnlyClass.doStuff();
}

Useful to know if you suddenly start seeing ClassNotFoundExceptions for class references that are surrounded by a specific version check like this. My best guess is that the VM optimizes the exception handling code somehow which makes the class get loaded immediately. Why it would do so or exactly what it's doing goes beyond my understanding of the VM's internals.

One other surprising case I've run into, calling setPreferredSize on a component caused unused classes to be loaded which triggered a ClassCastException. I ran into that a number of years ago so my memory of the exact details are somewhat sketchy, but I'm quite confident that it was a call to setPreferredSize that triggered all the classes referenced by the current class to be loaded immediately. It couldn't have been because setPreferredSize triggered a layout and the knock-on method calls triggered a reference to the class because there's no way I could have created an instance of it and added it to the layout.

In general, a much better approach is to define an interface that is always available and load the required implementation via Class.forName, that way there is no reference to the class in bytecode at all and nothing the classloader can do will cause it to be loaded ahead of time, saving an awful lot of hassle.

1 - Ignoring the fact that this is a really brittle check for Java 1.4.

Tracking Estimate Accuracy

June 19th, 2006

Over the past few weeks we've been working on tracking our velocity and trying to get a grip on how many points a week we can do. We haven't really rolled out proper iterations yet, but we pick a set of stories to work on for the week and then set about doing them. At the end of the week we add up how many points we completed. This has been working quite well except that we are regularly doing more points than we expected but not nessecarily completing any extra stories.

The problem is that our estimates aren't accurate enough. Sometimes this is because we estimate a story at a 1 or a 2 and it turns out to be a 3. Sometimes it's because we estimate a story as a 3 when we should have broken it down into multiple stories. Often though, we're seeing our estimates are out because there is a dependent story that we didn't know about at the start of the week.

So over the next few weeks we're going to try to get a handle on our estimates, see how accurate they are and try and improve on that accuracy. So far I see a three pronged approach:

  1. Any story that is taking longer than expected should be brought up at the morning stand-up meeting so that any required help is made available. This also means we'll know about potential problems early.
  2. Track and graph the difference between our estimates from the start of the week and the final number of points we thought the story was worth. This will let us look back at things that seriously blow out but also to pick up if we're just consistently underestimating things.
  3. Add a bit more into our planning game so that the engineers actually go through the process of brainstorming required tasks for each story and then estimating them instead of just going on gut feel.

The last item is likely to be the most beneficial but it will take a while to ramp up and we only get a shot at it each week so it will take another week before we even get started on it. We haven't done this previously because we've kind of snuck up on iterations and the planning game. Our whole approach to adopting XP has been like this - find the most pressing need and implement the part of XP that best solves it, then move on to the next need.

At first we just threw a huge number of stories up on the wall and started work on them, but that gave us no indication of our velocity. So we started planning what we'd do each week and tracking how much we got done - the first step towards doing proper planning games. Now we're seeing a need to get more accurate estimates so we'll start rolling out tools and techniques that help us estimate.