Saturday 2 January 2016

The Irresolution: on software, quality, and why one works

Meters, object oriented, with proper multiple inheritance.
Doesn't look very impressive? Well, this is Interlisp-D. In 1983.
I don't make new year resolutions; I never have. This year I almost did...

Some weeks ago, working on a project which has gone horribly badly wrong, I tripped on one of those nasty ugly non-orthogonalities which litter Microsoft software. In frustration, I wrote a very sarcastic comment in my code. In code review, a colleague whom I very much respect chided me: a bad workman blames his tools.

Yes, I thought but did not say, but a good craftsman chooses his tools. And I decided then that by the end of 2016 I would be working only in pure functional languages and only on competently-written platforms. That was going to be my first ever new years resolution.

I'm sixty, dammit. People are not going to pay me to cut code for very many more years. I started my career, thirty years ago, working on Interlisp-D, a development environment technically streets ahead of anything commercially available now. A thing of real beauty and a joy to work with.

The general idea of 'progress' is that things get better over time, not worse. I'm damned if I'm going to end my career writing on Microsoft's fit-of-pique clone of an ALGOL-derived language which Sun consciously and deliberately crippled because it was intended as a special purpose tool to develop programs for small-footprint embedded systems with very limited memory.

A meter I wrote this year, in SVG and Angular. No multiple
inheritance, so much less reusable code.
It's crap. Writing software is about solving problems, about finding elegant ways to solve problems. But it isn't and shouldn't be about finding elegant ways to solve the problems caused by the shoddy workmanship and poor technical design of platform you're working on. If the platform you're working on is shoddy, don't bloody work on it.

That was a good resolution. A wise resolution. A resolution it would have been sensible to adopt.

Just after Christmas it was tested: my attention was drawn to a job advert a friend of mine has posted: Clojure, my preferred language, on UNIX, my preferred platform, in Glasgow. I know the office, I've done coding dojos there. It's very slick, very comfortable, with standing desks I much admire; I know several of the team, and I like them. It should be a dream job.

And I'm not going to apply.

Why not?

Cowardice? Possibly.

An old man's reluctance to move? Well, certainly that. I find settling into new places and building new networks of relationships stressful and difficult, so that is a real consideration.

Engagement in the work I'm doing? Well, I do believe in what we're doing. I do believe that what we do, as a company, makes the world a better place. And I do suspect that the company is quite likely to make it very big indeed, and I'd be quite interested to watch that happen - even if this time I'm just an employee.

But what it really boils down to is loyalty. Loyalty to a key group of the people I'm working with; a desire not to let them down. Not that I imagine I'm irreplaceable; I'm nothing like as good as I used to be, and I'm much less good working with tools I dislike than I could be.

I know this is a bad decision. I know that some months down the track I'm going to find myself falling into another sinkhole of Microsoft shite and I'm going to regret this decision bitterly.

But this is my decision, and I've made it.

Afterword: on why tools and their quality matter

Yes, I know all computer systems of any significant size contain elements which seemed like a good idea at the time and which later turned out not to be. Interlisp is a LISP-2 - it has separate value and function pointers on every symbol. It also has subtly different binding mechanisms between interpreted and compiled code, which means that the scope of variables is different leading to semantic difference - which was an uncommon but horrible pitfall when your code worked when interpreted but broke when compiled. It has an awkward inorthogonality between older functions which have abbreviated names in ALL UPPER CASE and newer ones which have LongerNamesInCamelCase. Oh, and there was the curious CLISP feature which you could either see as magical or a well of despair, depending on how you used it (I didn't). 

Finally, in Medley, it had Common Lisp bodged onto the side. Common Lisp is a bit of a mess anyway, but the attempt to make one system interoperate functions written in two different syntaxes must have made for interesting debugging. But I had moved onto Prolog before Medley was released, so I never really had to deal with that.

Similarly, Clojure is partially crippled by the JVM's limited, fixed size stack (back to that notional 32 bit minimal-memory set-top box Java was designed for). And there have been some bizarre decisions in the language design:
  • the default arithmetic operators do not gracefully switch to bignums on arithmetic overflow (although there are alternative operators which sensibly do, if you know about them);
  • nil is not the empty list (both (nil? '()) and (empty? nil) return false) and is also not false ((false? nil) returns false); also, bizarrely, the car of the empty list is nil ((first '()) returns nil) but the cdr is the empty list ((rest '()) returns ());
  • the decision to remove a layer of brackets from cond and case  means that pretty-printing does not give a rational code layout (and also makes translation of code from other Lisps that bit harder);
  • the decision to notate arg-lists and let binding lists as vectors is also bizarre and again introduces needless inorthogonality (yes, I know that as compiled for the JVM they're implemented as vectors, but that's an implementation detail)...
And so on. There is no perfect computer language.

But anyone who has looked at a fern-moss, or a frond of bracken, or a waterfall, or a birch tree, or a cloud, or a prawn, or the development of a human embryo, has to acknowledge that if God does not write Lisp, God writes some language so similar to Lisp as to make no difference. The physical world is built in all its aspects and at all scales of simple functions recursively applied. It physically hurts me to work on systems whose underlying architecture is a bag of hacks kluged together.

A good workman chooses his tools.


No comments:

Post a Comment