Musings
muse: to turn something over in the mind meditatively and often inconclusively
So long and thanks for all the fish

mosaic_drinks_small.jpg End of an era today. My last day at Mosaic after just over 5 and a half years. It's hard to say goodbye to anything you've been involved with for that long.

People have been asking me all week what I'll miss the most and I haven't really had a good answer. Everything I suppose. Weird little things like the chair that I've had for the entire time I've been there. I know it's the same chair because it has characteristic scratch marks on the arm obtained during a particularly exuberant debugging session with our first "big iron" (the Brig). It's the last time anyone will use my extension number (6106) which will no doubt be recycled into the pool of numbers available.

It's the familiar faces: people I've worked with every day for years, tools I've fought with too many times to count, and code that I can recite in my sleep. It's the morning coffee routine and the lunch walks. It's all those plans for the future that I now have to walk away from.

I think the hardest part for me is that I've always been one to give my all to something. Part of that has been staying in one place long enough to really make a difference. To get involved on a long term basis rather than just being there for the short haul. So a change like this runs counter to that basic drive to see things through to the end.

That doesn't mean I regret moving. It really is time and I'm looking forward to whatever Life has in store for me. But at the same time it's hard to let these things go.

Adios amigos. Until we meet again.

Posted at 07:44 PM

JDB I didn't C that

Hmmm. Seems I wasn't quite correct in suggesting that the aforementioned scenario isn't covered in the JDBC specification. It's covered from at least version 3.0 on (I didn't have ready access to 2.0 but I couldn't find anything in the 1.0 spec when I checked).

And it seems DataDirect are compliant. The spec expects an exception to be raised when calling any of the execute methods that take a String parameter on a PreparedStatement

I do feel though, that this spec clarification vindicates my comments on the design.

Posted at 10:39 PM

Exploring an API from the other side

Bored and idle, and with a small itch called ANTLR to scratch I started playing with a parser for a very simple subset of the ANSI SQL grammar, with the intention to flesh it out into a poor man's database complete with a JDBC driver. My aims were first, to play around with a simple parser so I could suss out ANTLR's capabilities, and, second, to explore the JDBC API a little more. The backing persistent store was never intended to make up a significant part of the playing. I figured I'd just write up a Serializable class representing a table's metadata and row data and persist each table in a separate file. I didn't want to get bogged down in locking or atomicity requirements. Not yet anyway, although my interest has been aroused and I'm starting to think about how I'd handle locking, indexing and how I'd implement write-ahead-logging.

Okay, so I may have bitten off more than I can comfortably chew in a weekend.

It's always interesting what you learn about an API when you start looking at it from the other side of the fence. It's one thing to use an API. It's quite another to produce an implementation of that API. I haven't implemented much in the way of the JDBC API so far but already I've run into an interesting question which neither the specification nor the API docs clarify (as I read them). If you're using PreparedStatement to query a table then you're probably writing code something like this (assuming ds is an appropriate instance of DataSource and forgiving me for not diligently cleaning up all resources):

   public static void main(String[] args) throws SQLException
   {
      Connection cn = null;
      PreparedStatement stmt = null;
      ResultSet rs = null;
      try
      {
         cn = ds.getConnection();
         stmt = cn.prepareStatement("select strcol from mytable");

         rs = stmt.executeQuery();
         while(rs.next())
         {
            System.out.println("mytable ["+rs.getString(1)+"]");
         }

         cn.commit();
         cn.close();
      }
      finally
      {
         if (!cn.isClosed())
         {
            cn.rollback();
            cn.close();
         }
      }
   }

All very good and well. But, if you look more closely at the API you'll notice that, because PreparedStatement extends Statement the following is possible (albeit it a bit odd):

   public static void main(String[] args) throws SQLException
   {
      Connection cn = null;
      PreparedStatement stmt = null;
      ResultSet rs = null;
      try
      {
         cn = ds.getConnection();
         stmt = cn.prepareStatement("select strcol from mytable");
         rs = stmt.executeQuery("select strcol from othertable");
         while(rs.next())
         {
            System.out.println("mytable ["+rs.getString(1)+"]");
         }

         rs = stmt.executeQuery();
         while(rs.next())
         {
            System.out.println("othertable ["+rs.getString(1)+"]");
         }
         
         cn.commit();
         cn.close();
      }
      finally
      {
         if (!cn.isClosed())
         {
            cn.rollback();
            cn.close();
         }
      }
   }

Pretty odd, but nothing I can see in the specification or API prevents it. And, more worrying, it's not clear what the driver is expected to do in this case. Years working with JDBC and I've never bumped into this oddity. A few hours implementing a simple JDBC driver and this was pretty much the first head-scratcher I ran into.

It's interesting that for a long time I've viewed the JDBC API as reasonably well designed. But this simple exercise has made me rethink my feelings on the whole statement interface hierarchy. I think the designers fell into the trap of not wanting to repeat common methods on all three of the statement interfaces. In particular, the idea of repeating large groups of methods like those for binding input parameters on PreparedStatement and CallableStatement was probably pretty unpleasant. Since at first glance it seems like a statement with parameter bindings is just a specialisation of a statement with none, the current hierarchy probably looked pretty obvious.

In hindsight, and looking at some of the rough edges like that flushed out in the example above, I think I may have gone a different route. I'd probably have started with a much simpler Statement interface with no execution methods. Things like query execution and parameter binding (for both input and output parameters) could be provided as collections of methods grouped into standalone interfaces. So we'd end up with something like this (perhaps with some more thought given to interface names):

public interface Statement
{
   // Methods common to all statements
   void close();
}

public interface ParameterizableInputs
{
   // Methods for managing input parameters
   void setInt(int index, int value);
   void setString(int index, String value);
}

public interface ParameterizableOutputs
{
   // Methods for managing output parameters
   void registerOutParameter(int index, int type);
}

public interface RetrievableOutputs
{
   // Methods for retrieving input values
   int getInt(int index);
   String getString(int index);
}

public interface PreparedExecutable
{
   // Methods for executing previously
   // prepared statements
   boolean execute();
   ResultSet executeQuery();
   int executeUpdate();
}

The three common interfaces developers would then interact with would be something like RawStatement (since we've already used Statement), PreparedStatement and CallableStatement. These would all inherit from Statement and then mix in any other relevant interfaces.

So a PreparedStatement would then be a Statement that included a "mixture" of support for execution (without the ability to excute arbitrary SQL statements on the spot) and binding input parameters. And a CallableStatement wouldn't have to inherit from PreparedStatement, since it could just collect together the areas of functionality that apply.

Even the ResultSet interface benefits because one of the services it provides is encapsulated within the RetrievableOutputs interface.

Admittedly, this is after only a few hours of thought, and it may not stand up to closer scrutiny. However, it illustrates the benefits of exploring an API from both sides to flush out the "funnies".

Okay, so having said all that, what happens in the real world? I tried the above on two SQL Server drivers (simply because I had them and a ready database handy): JNetDirect's JSQLConnect and DataDirect's JDBC driver. The results were interesting. JSQLConnect produced the same resultset twice: rows from the second table queries. So executeQuery(String sql) obviously updates the internal state of the prepared statement. DataDirect (always interesting because I know they're closely involved with the JDBC specification, and I think have two members on the working group) throw an exception indicating that calling the executeyQuery(String sql) method is a Statement method and that calling it is invalid (this is how I read the exception message anyway).

The latter fits my worldview more comfortably. The problem is, it's not clear from the spec whether or not PreparedStatement implementations should execute the second query without disturbing their internal state, or update their internal state with the new query string. DataDirect have taken the position that the method doesn't make sense for a prepared statement. This is the same position I'd be inclined to take and is a driver behind the interface decomposition I've discussed above.

I think having PreparedStatement inherit from Statement was a mistake. Fundamentally they're actually pretty different ideas. CallableStatement and PreparedStatement have much more in common and this relationship probably makes more sense. But the former is harder to swallow.

Posted at 04:33 PM

Balancing stability and progress

Software development, as with so many other things, usually comes down to finding a balance between extremes.

Programmers love writing code. Most programmers anyway. Those that don't can probably be discounted in this discussion. This isn't a problem in itself, but it can become one when you're tasked with maintaining the stability of a project. Stability comes in many forms. The most obvious is stability in the sense of raw uptime of mission-critical software. If a hospital's life support systems need a manual reboot every now and then you're probably going to have more bed space than you know what to do with.

But stability comes in other forms too. Unstable code is code that sees a little bit too much activity. This could be for any number of reasons. The code may be host to a large number of subtle bugs. The code may perform inadequately. The code may be written in such a way that it tends to foster new bugs whenever someone so much as looks in its general direction. In a nutshell, unstable code is the subset of any codebase that people would rather not have to touch because, well, everyone knows that life is miserable for a few months after doing so.

But what progress without change? The very definition of progress involves movement, which is essentially a change in your position. But change (and so too progress) brings with it risk. You change a line of code, you risk breaking something. You add a line of code, you risk breaking something. Even adding something as innocuous as a comment introduces a modicum of risk (unless you have complete and utter faith in the compiler, something I lack).

So, assuming that progress in our software is desirable, and leaving aside any concerns you may have over that statement, how do you balance the need to make progress (and usually relatively quickly at that) with the need to maintain stability? Or, more bluntly, how do you satisfy the need (emphasized to reflect my state of mind) to write code without cocking up what you have?

I hope you aren't expecting an answer. I sure as hell don't have one.

Posted at 08:53 PM

The joys of a monopoly

saixreseller13xz_small.jpg Yes, Telkom (the local telco monopoly) are at it again. Or so it seems. A friend runs a local ISP. We actually use him for our ADSL connection, or at least the part where competition exists (you can't rent your line from anyone but Telkom).

We had breakfast with him on Sunday and he dropped a few tidbits which had my blood boiling and, frankly, ruined the rest of my weekend.

To start with, come the start of November, Telkom are instigating hard caps. ADSL in this country is capped. If you're Telkom are your provider then the best you can do (currently) is a 3Gb cap. As much as I dislike capping I can see how it might be a necessary evil. But until now, capping has meant being shunted over onto a shared (and therefore usually dog slow) line when you exceed your cap. As of November exceeding your cap will mean connectivity ceases for the rest of the month. Ouch.

saixreseller26ux_small.jpg In addition, Telkom are raising their prices substantially. Our current package will double in price. Given how uncompetitive broadband pricing is in this country (we're paying around GBP 110, or $169 a month for a 384kb connection with a 10Gb cap) this is just nuts. As it is our international call rates are the most expensive in the world (almost three times more expensive than the country next in line for this dubious honour). One of the biggest emerging international job markets for relatively low-skilled personnel is call centres. Telkom are probably the single largest hurdle to South Africa cleaning up in this market.

And finally, Telkom have made it extremely difficult for ISPs making use of their ADSL offering to disconnect someone who has exceeded their cap. In a nutshell it comes down to this. Data about line usage is not updated in realtime, so an ISP gets updates only periodically. The delay is long enough so that someone on a reasonably fast line can significantly exceed their cap before the ISP is alerted to this fact. As a result the ISP is out of pocket for the extra bandwidth consumed by that user. This is really going to hurt smaller ISPs who are already operating on razor thin margins. The result is that a lot of smaller ISPs may well decide it's just not worth it anymore and close up shop. Given the focus on job creation in this country at the moment this should set of warning bells all over the place.

Welcome to Africa.

Note, the included images were sourced from here, and were not provided by the friend mentioned, although I'm pretty sure he would have received these letters too.

Posted at 03:07 PM

In sickness and in health

Bah. Laid up at home with something horrible. Yesterday evening was about the worst I've felt in years. The weird thing is it felt like flu but all flu-like symptoms have disappeared today. Still not feeling great, but at least I can breathe properly again.

Posted at 01:01 PM

Cape License Plates

Ever wondered where that CZ car's from? Wonder no more.

If I don't get bored I may keep this updated.

Posted at 05:19 PM

The Antidote

I've been carrying a copy of The Antidote (by Morcheeba) on my flash keyring for, hell, well over two months now. About a week ago I finally dumped it into WinAmp.

I'm sorry it took so long: I'm thoroughly enjoying it. I suspect much to the annoyance of anyone who spends any significant time within earshot of me.

Heartily recommended.

Posted at 11:41 PM

On alpha geeks and penis waving

That got your attention, didn't it?

I met up with Bent, one of my soon to be co-conspirators, for coffee this morning. As the converation progressed it turned, as they tend to, to Intel assembly language. It seems that some penis waving is afoot at the office (I'm assuming it's just penis waving since I don't see a lot of scope for that kind of low level coding, not yet anyway) and having never blackened his soul he had a few questions after perusing some output from gcc.

Frankly, I had to do a little scrambling to provide him with some "answers". It's been well over 10 years since I dabbled in assembler (yes, that long) and the world has moved on from the days of 16 bit registers.

So here I sit. It's 10:30 on a Saturday night and I'm brushing up on Intel assembly language. I don't plan on being lunch for a hungry pack of alpha geeks any time soon.

Posted at 10:37 PM

And he's off

Or more correctly, Andy's off.

Some bastard from Gauteng, trying to shave a few seconds off his journey time no doubt, tried to turn across the line of oncoming traffic just after a light change (to green). Unfortunately he didn't see the little red RF400 pulling away.

The bike seems to have suffered only superficial damage (to my untrained eye anyway) and Andy seems to be in much the same position. We lifted him to Vincent Pallotti for an x-ray and his arm (the point of impact), although a bit numb and quite swollen, is unbroken. However, the swelling was apparently cause for some concern and he's been booked in for an overnighter (bed and breakfast as he calls it) just in case it suddenly turns blue and falls off.

As usual, the local biking community rose the call of one of their own kind in distress. Hats off to Peter for offering to drive out from the Northern Suburbs at 6pm on a (busy) Friday evening to pick the bike up. And news travelled fast enough so that concerns were voice by means of this new fandangled "voice over a distance" (look Ma, no wires) technology.

Posted at 10:31 PM

Complex shopping

I spent the morning as a pro-wrestler (complete with gum guard), dressed in an asbestos fire-retardant suit trying not to be spotted by any of the special effects crew in a nearly vacant movie studio.

Why? Because the rest of the shopping complex wasn't open yet.

Hey, I'm just the execution environment.

Posted at 08:37 AM

Personally?

A real smorgasbord of topics today. Cast your mind back to English language at school. Hopefully someone, at some point, spent some time discussing various types of interesting language constructs (in some case errors is more appropriate) with you. If not, here's Google and a list of terms [tautology, malapropism, spoonerism, transferred epithet], knock yourself out.

An example of a tautology is "Personally, I prefer meatballs." since "personally" and "I" duplicate information in that sentence.

I've been trying to come up with a legitimate use of "personally" that isn't a tautology. The closest I've come is "I've never tried it, not personally."

Dictionary.com proffers the following:

  1. I thanked them personally.
  2. Personally, I don't mind.
  3. I admire his skill but dislike him personally.
  4. Don't take the disparaging remarks personally.

At first I thought the first example was a tautology, but I suppose it's possible to thank someone impersonally: via email, or a written note, or even by mailing them a dead squirrel. Actually, scratch that last one, they may not take it as intended.

Any other suggestions? (I realise you can't answer that here because I haven't enabled comments, consider this the ultimate rhetorical question.)

Posted at 07:24 PM

Pluggable Types

Yes, I thought it was an intriguing title too, especially prefacing an entry on the blog of the only Computational Theologist I know of.

It's an intriguing idea, and his paper introducing the topic is very readable. I recommend it.

I've lost track of the number of heated arguments I've had about whether or not static typing is "better" than dynamic typing. Bracha's point is that this focuses on the wrong distinction. It's not (in his opinion) whether or not you have a static or dynamic type system, but rather whether or not it's optional or mandatory.

I always like to cast abstract concepts in concrete terms. It tends to illuminate them. I'm also in favour of pragmatism over hand-waving. If it can't be cast in practical terms, then it's value is questionable. So what does an optional type system really mean? There's a tendency to suggest practical examples using Lisp or Smalltalk. Without meaning to suggest that either of these are hand waving, I'd suggest that they're hardly the most accessible way of presenting an abstract idea in languages. So what does it mean in terms of Java (this applies just as much to C#)?

Imagine for a moment that you never had to specify the type of a variable in Java. I submit that you'd be able to write a lot of Java code much faster. Yes, a lot of that code would be broken (static typing has some very definite advantages) but you'd have turned Java into a flavour of Python (in some respects anyway) and there are definitely some jobs where it's faster to use Python than Java.

This comes at a price though. Some things are no longer possible. For example, overloading methods isn't possible because there's no way for the compiler to differentiate between the following two methods:

foo(my_map)
foo(my_set)

Written as Java code today these would look like this:

foo(Map my_map)
foo(Set my_set)

and the compiler could use the type information in the parameters to make a decision about which method you intended to invoke. It's debatable how much of a loss this is. Personally, I don't think losing the ability to overload methods is a huge loss and with a slight change in how you structure solutions it's possible you might never miss it.

Perhaps a bigger loss would be IDE support for things like auto-completion (how does the IDE know what methods exist on an object if it doesn't know the type?), or refactoring (how does the IDE make sure every instance of a method name has been changed if it can't check the type of variables in other code?).

A much bigger loss is that of interfaces. Yes, it's possible to tack something like interfaces onto a dynamic language (PEP 245 is proposing an approach for Python) but it tends to be very clunky and requires a fair bit of additional dynamic introspection in your code. Interfaces are essentially a contract between two objects and they tend to work rather well when cast in the form of a type.

So you lose a lot by removing static typing. But you also gain a lot, mostly in terms of flexibility. Bracha also points out that by tying a language to a type system you increase its complexity significantly, usually to a point where formal verification is no longer feasible. Which means you can't prove things about the language which limits the domains in which it is useful. If a language is dependent on its type system for something like security (as Java is) and you can show the type system to be broken, then it's pretty much tickets for the language (from a security perspective).

Optional typing proposes the following. Let's separate the type system from the language. This makes formal verification simpler because you're only dealing with a grammar and we know quite a bit about parsers by now. So your language doesn't depend on a type system at all. We've seen that this requires some thought from the language designers. Certain things (like overloading) are no longer possible. But, we'd prefer not to throw the baby out with the bathwater, so let's allow the type system to be "enabled" optionally. This means that your IDE could apply type checking while you're developing your code, if you wanted it to. So if you like (or feel more comfortable) with squiggly red lines under variables when you cock it up then switch it on. If you're trying to whip out a quick 15 liner to get something done pronto and feel confident in your abilities then switch it off.

But that's perhaps easier said than done. Where is the IDE going to get the type information it needs to play the blame game? With a language like Java (or C#) you could mark things up using meta-data (annotations). This gives tools (like your IDE) the information they need to work with, without forcing it onto the language. Instead of typing


int foo;

you would type something like


@int foo;

The important thing to realise here is that the type information is optional in the second example. It isn't required by the language specification. It features nowhere in the grammar.

So why would we do this? Well, there are a few benefits worth considering. If it turns out your type system is flawed, then you can fix it. The language isn't broken, just your type system. If Java's type system (today) turns out to be broken, then for many applications it would mean back to the drawing board. Applets, for example, rely heavily on bytecode verification to be able to make guarantees about what they can and can't do to your porn collection. This verification depends crucially on Java's type system. If it's broken, so are Applets.

It also becomes possible to plug in diffferent type systems. Why would you want to do this? Well, it's been shown that a range of static analyses can be represented as type systems. Some make guarantees about aliasing (show me a C++ programmer who hasn't been caught by this), others make guarantees about the flow of information through your application (Java relies on this to a degree to catch potential references to uninitialized variables). Throwing all of these into a language would make the language unmanagable, and would also force you to deal with restrictions imposed by one of those type systems which really only make sense in another context (another project, another team, another industry). Essentially you could choose how strict (and exactly what strict means) based on the project you're working on.

It has certain appeal. In many respects it seems to bring a language one step closer to being universal. This alone gives me pause for thought: I firmly believe in choosing the right tool for the job. Languages have strengths and weaknesses and trying to make a language into something it's not usually degrades the language (in my opinion). Another way of saying this is that I don't believe in the idea of a universal language.

Hmmm.

Posted at 05:00 PM

Stellenbosch

stellenbosch_small.jpgThe previous entry has been brewing in my head as a background task for some time now, but I finally pulled all the threads together over the course of a trip out to Franschoek and then back via Stellenbosch with Andy. It's very pretty country and it's very hard not to stop every few hundred meters and take a dozen more photos.

The South Easter was blowing hard today, hard enough to to airbrush Table Mountain out of the skyline on the way back. Wind like that is always pretty unpleasant when you're on a bike.

It helps to have a heavier bike when battling strong wind. I had a 250cc back in Oz that spent most windy rides leaning at a 45 degree angle, just to stay in the lane.

On the way back we stopped off in town and left handprints and drool marks on some of the shop windows. So many bikes, so few paychecks.

While we were doing that what seemed like every emergency vehicle in Cape Town showed up for what I can only assume was a pretty horrific accident. We found an alternative route out of the city and avoided the very human urge to do some rubber-necking.

Posted at 06:31 PM

Curves ahead

curves_ahead.jpgWhen I'm out on my bike this sign means two things to me: the road ahead is probably going to be a lot of fun, and there's a good chance I'm not going to be able to see what's around the next corner. Life, it would seem, mimics art (or rather my photography). Curves ahead indeed.

After a lot of thought, and a fair bit of soul-searching, I've decided to join Amazon. So while I have no doubt that the road ahead is going to be a lot of fun, it's not entirely obvious what's around the next bend.

The decision was actually made a while back. I haven't mentioned anything here because I wanted a chance to break the news to the various people I know and work with personally. Personally because it would give me a chance to explain my reasons. I wanted to make sure people understood why I chose to move on. There's a fair bit of uncertainty around Mosaic's purchase (already almost a year on) and FUD tends to flourish in the presence of uncertainty. I really believe there are great things ahead for Mosaic, and for the people that make Mosaic what it is, and I didn't want to contribute to that FUD.

If I had to give you five reasons for moving, they would be, in descending order of importance:

  1. A chance to work on something completely different. Different tools, different platforms, and different technologies.
  2. A chance to be on the cutting edge of technology.
  3. A focus that's closer to pure Computer Science. This is a really bad way to put it, but I haven't been able to come up with a better way..
  4. A chance to work with people much smarter than me and with much, much more experience. Everyone at Mosaic is like me: we've all had to figure stuff out from first principles. We're basically making it up as we go along. It will be interesting to see how others have done it, and what's worked and what hasn't.
  5. A chance to work in a small team again. This is relatively minor but has a lot of appeal. It's amazing what a small group of skilled people can achieve. It will be nice to be a part of that again.

It's meant giving up a lot. I really do believe great things are ahead for Mosaic, and it will be hard not to be a part of that. It's also hard walking away from something like Realtime 5. Two years is a long time to invest in any single task, and we really are so close. It will mean going back to a lower level of abstraction. This is good, I really am looking forward to it, but the opportunity to work at a higher level of abstraction, to look for patterns across a wide range of products, and to anticipate their needs, is probably not a part of my immediate future. But you can't have it both ways.

So come the end of this month I bid farewell to Postilion, the Realtime Framework, and other friends (some of which don't have a LOC count) and move on to whatever awaits. Someone asked me yesterday if I felt at all like my mind had moved on in anticipation of next month. I do feel a little like I'm in limbo. I'm mentally packed, I've made my decision and now Life is playing catch-up. I do feel a little frustrated because I'm not yet contributing, and my "new team" are racing ahead without me.

That said, it's not like I'm panting to get out of here. I still have a few things to tie up, and I will miss these people. And letting go of half a million lines of code you've been knee deep in for so long is tough.

But I'm looking forward to whatever is around the next bend.

I'd add something soppy like "don't forget me" here but I'm sure I've left behind enough code that will have people cursing my name. At times like that being forgotten may be something to aspire to.

Posted at 05:49 PM

Raising (or lowering) the bar

We had a lengthy discussion today around recruiting. At the moment there's a lot of pressure to hire people. We're overworked and understaffed (who isn't?) and it hasn't helped that another division, one we share an office building with, has recently hired three new people.

So one of the areas of discussion today included questions like "Are we aiming too high?", "Are we perhap being a tad elitist?", and "Are we saying no too easily?"

These are valid questions, and anyone who has to sit through more than a handful of interviews for more than a handful of weeks will very quickly find themselves second guessing their no-hire decisions.

What makes it particularly hard is the subjective nature of interviews. As much as we strive to standardize them, to aim for objectivity, and to remain consistent in our evaluations, at the end of the day it comes down to how I feel about a candidate. And that's not something I can even really explain, let alone pass on to someone else. I have a lot of faith in my ability to suss a developer out. But it's really hard to pin down what my triggers are. Over the years I've slowly pulled together a list of technical questions (and answers) that usually flush out these triggers, but that's about as formal as I can claim to have made the process.

This discussion quickly turned into a discussion about what we should be aiming for within the group. What should we be aiming to achieve in terms of the ratio of "star performers" to "carbohydrates"? Should we be trying for SPs only, or is it acceptable to be saying yes to the occasional C?

I think it depends on the kind of work you're doing. Our division is product focused. That's pretty rare in our industry and almost unheard of in this country. The other division is project focused. This is how much of the industry works. Especially in this country. Programming tends to take the form of projects, often involving a small core team of people surrounded by contractors. This admits a different approach. The focus tends to be more short-termist and there's a ton of pressure to just get it working, and get it working quickly. So the market tends to proffer these kinds of developers far more readily than developers with a product focus.

A product focus tends to be longer term. It's much more important to do it right, even if that means taking a little longer. Finding the kind of people who are suited to this is hard. But because of the long term nature of the things you build it's extremely important (in my opinion anyway) that you find the right people. And I'm tending more and more towards making sure as many of your people as possible (all of them if you can do it) are the right kind of people. Which means we should be aiming for SPs only.

But that's hard. It takes time. And I'm not sure the local market even has that many people to give.

Posted at 10:36 PM

Why people are better than software

This is one of the fundamental challenges facing B2B web services: dealing with the messiness of reality.

I dropped a note to the supplier I'd prefer to put the laptop I'm interested in together, just on the off chance a human would answer it and take a personal interest in poor old me. And what do you know, I lucked out. Although their online billing forms don't allow for international cards, they're prepared to accept them. I just need to provide whatever details won't fit into their form in the general comments box at the end of the process.

When the world first started talking about web services people got a bit ahead of themselves. The envisioned your refrigerator negotiating with the local store to restock before you ran out of frozen TV dinners. B2B picked this up and ran with idea of business software automatically managing internal inventories. Almost out of H4 pencils? Never fear, RePencil 2000TM will automatically step into the breach, negotiate the best price and an optimal delivery date from a selected set of vendors and refill your stapler while it's at it.

This has always bugged me because it assumes the world is more predictable than it actually is. This laptop is a case in point. Credit cards and billing addresses are not uniform the world over. Hell, just the form an address takes differs fairly significantly (from an automated processing point of view), even if you confine yourself to the US, UK and here.

How is software going to cope with that? With difficulty. I'm not suggesting it's insurmountable, but we do ourselves a disservice by assuming this is a trivial thing to accomplish.

For me, what web services give you is a more debuggable (XML is not human friendly, but it is human readable) way of building APIs that allow software built using vastly different tools on vastly different platforms to talk to other like-minded software. Let's get that right first. Baby steps.

The upshot of all this is that, once again, the laptop looks feasible.

Posted at 06:41 PM

The not-so-global village

Gah.

I'm looking for a new laptop at the moment. I'm pretty much sold on the Asus W3V. Problem is, it isn't available in this country.

So a quick look on the trusty interweb brings up a list of suppliers. A bit more digging found someone who will customize it for me (I want more RAM and a bigger, faster drive than ships standard).

As usual, despite much finger crossing, come checkout time everyone wants a US billing address.

So much for the global village. Time to call in some favours...

Posted at 08:57 PM

Lamb soup stew

A battered printout of the recipe below has been stuck to various fridges of mine for the better part of 4 years. The email is titled "lamb soup - the way I made it" and is dated 14 May 2001 (08:51 AM).

I highly recommend it, especially on a Wintery day. I've adapted it into a stew (we'll find out how successfully in about an hour) by using two onions, halving the tomato puree and adding diced baby potatoes. And being a spur of the moment dish we're not entirely kitted out for this recipe so a few odds and ends are missing. My uneducated palate probably won't notice the difference.

INGREDIENTS

  • 300-500g stewing lamb (on the bone)
  • 1 teaspoon coriander seeds
  • 1 teaspoon cumin seeds
  • 1 large onion, peeled and chopped
  • 2 cloves garlic, crushed with 1 teaspoon salt
  • 1 teaspoon allspice
  • 2 teaspoons mild chilli powder
  • 2 teaspoons castor sugar
  • 1 green chilli, deseeded and chopped
  • 140g tin tomato puree
  • 1.3 litres liquid - beef and vegetable stock mixed works well
  • 1 tin chickpeas, drained
  • 100g dry couscous
  • 1 tablespoon chopped mint
  • 1 tablespoon chopped parsley
  • 2 tablespoons of oil (more if required)

METHOD

  1. Heat a pan over medium heat and dry roast the cumin and coriander seeds for 2-3 minutes. Then remove them from the pan and gently cook the onion until it is soft and lightly browned, 5-6 minutes
  2. Heat 1 tablespoon oil in the pan and gently cook the onion until it is soft and lightly browned, 5-6 minutes
  3. Add the crushed garlic and salt, and cook for another 2-3 minutes
  4. Add the crushed spices, the allspice and the chilli powder and stir. Remove all of this from the pan and keep aside while you heat the other tablespoon of oil and brown the lamb, stirring it regularly
  5. Reduce the heat and add the onions and spices, tomato puree, chopped chilli and castor sugar. Stir everything
  6. Add the water/stock and the chickpeas, and stir together. Simmer for at least an hour on medium low heat
  7. Before serving, remove from heat and add the dry couscous, parsley and mint. Wait at least 3 minutes

Posted at 05:42 PM

Is passion a necessary condition?

We met Miss Johnson and Brandi for lunch yesterday. Brandi has been involved in some of the interviewing I've been doing recently and the conversation drifted in that direction. Actually, in truth it was dragged forcibly in that direction when he asked if I though passion was a requirement when evaluating candidates. This prompted an interesting discussion about whether or not passion was important in what we do.

I really believe it is but the discussion left me trying to figure out why I think this, and whether or not I'm reasonable in thinking so.

Wes felt that all we should require is competence. During the discussion it became apparent that he also felt discipline was important, although he never claimed that explicitly. So is discipline and competence enough? Something else that came up in the conversation was a distinction between enjoying your job and being passionate about it. That was the key point that got me thinking about this.

There are a few things that tie in to this conversation. First is that it's critical (in my opinion) that someone enjoy what they do. They're going to do an awful lot of it and, frankly, I don't know how quality can do anything but take a knock if you don't enjoy what you do. Everyone seems to agree here though, so this isn't a point of contention.

Competence is definitely a requirement. I expect my pilot to know what he's doing when I travel. I expect the same thing from people writing our software.

Discipline is pretty important too. Not everything we do is interesting, or challenging, or fun. Discipline is what keeps us going. Discipline and a degree of commitment. I'll take the latter over the former if I have to choose though.

But passion? What do I mean when I say passion? Typically when I call someone passionate what I really mean is that they never stop thinking about what they do. But even that misstates what I mean. What I really mean is that they don't create artificial boundaries in their lives. They don't partition "work" away from everything else. I think about biking while I'm at work. Why shouldn't I think about work while I'm biking?

So why do I think "passion" (as I've described it above) is important? Well, for a start, if you're not spending a lot of time thinking about what you do then I believe you're never going to really understand it. I don't think the really good mathematicians ever stop thinking about maths, and I see no reason why it should be different for programming. You're also probably limiting the rate at which you're likely to improve. The more time you're prepared to give to thinking about what you do (or how you do it), the more likely you are to spot chances to make incremental improvements.

I think the kind of continual focus is particularly important in any creative endeavour. When you're involved in something creative you basically spend most of your time waiting for the next idea to hit you. The more time you're prepared to give to waiting, and the more open you are to those ideas arriving at any time and in any context, the more successful you're likely to be.

Do I believe what I do is creative? Absolutely.

So for me, passion is a necessary condition though not a sufficient condition.

Posted at 06:44 PM

Know your road signs

canola_small.jpgPleasant run this morning out to Napier for lunch. The kind of roads dotted with "sharp bend" signs every few kms. Perfect biking country. Pity the lunatic:levelhead ratio was so high.

This morning started out cold and damp. Rain threatened and spots came down on the way out to the rendezvous point. But the weather on the other end of the ride was superb. Clear skies with almost no clouds to be seen. Amazing what a difference a few hundred kilometers can make. We met up on the N2 so we could grab some petrified tree juice. Werner (lunatic #1) brought a buddy with who rocked up on a new Honda CBX1000 with an aftermarket nitro kit fitted (lunatic #2). Shortly after that Albert rocked up on his new ZX10R (lunatic #3). Lastly we were joined by Riel (veteran biker and voice of reason). I'm going to count myself as levelheaded (feel free to disagree).

Our route took us along the coast road. We stopped in Rooi Els for breakfast at which point we parted company with the CBX. From there it was on to Stanford for more fuel, followed by Napier for lunch. The ride out to Napier included some pleasantly pretty scenery. Large fields of flowering canola (inset) broke green fields with patches of yellow. Combined with generally good road surfaces it's a hard ride to beat. Lunacy aside it was a pretty good ride.

I think fundamentally, the lunatics and I differ in what we get out of biking. For them it's about speed and daring, and perhaps to some degree the "look". Nothing wrong with that but I enjoy a more leisurely ride from time to time, so you get a bit of a chance to look around. What concerns me most is the occasional disregard for the other bikers on the road. I've had Werner pass me on the inside without warning a few times, and both he and Albert have an annoying habit of sitting on your tail (right up your ass). The CBX nearly came off second best doing just this quite early in the ride. They also both seem to pay little mind to their own safety. Albert took a gap at one point that could easily have been the last thing he ever did. If the car had been a few seconds earlier (and there was no way to see this wasn't the case) he would have ended his ride having taken on the form of a fine mist.

Perhaps I'm just overly cautious. Maybe it requires something awful to wake them up. I hope not. Especially since "something awful" on a bike is very often fatal.

We split up on the way back. They took a route back via Franschoek pass. I joined Riel over Sir Lowry's pass, bringing the ratio to zero. I think it was a good decision.

Posted at 06:15 PM

News

It occurs to me that we've long since notified pretty much everyone we wanted to get to before making a general announcement, but in case anyone who reads this doesn't yet know Claire and I are engaged.

Yup, I officially have a master.

Sit Ubu, sit. Good dog.

Posted at 08:05 PM