23 May 2008

Programming for the Stone Age

Warning: Rant Ahead. I just need to get this out of my system. You don't have to read it. It might look like I'm beating a dead horse, but recently I found this particular horse alive and kicking.

We have to do it this way because otherwise it will be a maintenance nightmare

So, here are some ways to make your code maintainable:

How to Write Maintainable Code

  1. Write helpful, detailed comments
  2. Always code to interfaces: you never know when we will need to substitute a different implementation
  3. Your Controllers delegate to Façades, your Façades to Services, and your Services to DAOs: this allows us create modular and re-usable components for greater flexibility
  4. Extract a maximum of configuration information to properties or xml configuration files. That way, the future maintainers will be able to modify the program's behaviour without even needing to recompile!
  5. Actually, if you can put some if this information in the database, even better, you can tweak the application while it is running!

Oops! Sorry, actually, I meant to publish that in a different universe. Here's the corrected version.

How to Write Maintainable Code

  1. The code is the documentation. Comments get in the way and are often wrong
  2. A smaller codebase requires less effort to understand it, hence will be more easily assimilated by future maintainers. This means don't create interfaces until you actually have varying implementations
  3. The simplest possible code is also the hardest to break accidentally, and also the easiest to introduce new features to. Don't add layers until the need for them is manifest
  4. Extract only the minimum possible configuration information. If later you find something needs to be configurable, extract it then. Each configurable item is another piece of indirection, adding size and complexity to the system.
  5. If something needs to be configurable, put it in the database only as a last resort, and only if there is a proven requirement from real users that this needs to be configured, and then only if they are willing to pay not only for the initial development cost of this configurability but for the future maintenance costs arising from the much-increased size and complexity of the system as already described.

Two worlds, opposite extremes, both seeking the same outcome: to protect future maintainability. The other-universe of the first approach isn't a weird quantum thing, it was just twenty years ago.

Comments

There was, indeed, a time when languages imposed a (small) upper limit on the length of names. So you had this

sndClsAppMl(char* addr, char** tmpl, int cntyCd, int clsCd)

And now you have

sendClassificationApprovalEmail(EmailAddress address, 
    MessageTemplate template, 
    Locale locale, 
    Classification newClassification)

What clarity could be achieved by commenting this that could not be gained by altering the name of the method or its arguments?

Around this time, twenty years ago, development environments didn't have the same kind of instant code navigation that we do today. Nowadays, if I stumble by some misfortune on a cryptically-named and mal-commented method call, I hit Control-B (yeah, intellij), and I'm instantly in the target method which I can read, understand, and (unless it's lunchtime), rename.

The comments, if there are any beyond those auto-generated by the IDE, usually reflect what the author had in mind, sort of, when he was wondering (pondering, maybe?) what it might be useful (or appropriate) for a method to do - or not do - under a particular set of circumstances (not excluding the most recent version of the spec, while taking into account what one of the users said at the last demo, although the analysts didn't agree) that may or may not bear some relation to the current situation of the project.

Steve Yegge discusses commenting more brilliantly than I could ever hope to, going so far as to declare that static typing is commenting taken to an extreme.

But I digress. The point was that without the instant code navigation we have nowadays, comments may in fact have been useful.

Configuration

Continuing our peek at pre-history, a feature of large systems in the Bad Old Days was that they took ages to compile. Ask anyone who was around. So of course you would want to pluck stuff out of the code and pop it into a config file of some sort, just to cut down on compilations.

Once you had your thing compiled, and especially if it was a native application for a popular desktop OS from a Seattle-based company, it was probably a curse to deploy. The kind of thing everybody wants to delay for as long as possible, whatever the deadline says.

So, naturally, whatever you can configure, you'll want in the database, 'cos you're not doing a redeploy just because your sponsor realised a moment too late that in fact the colour for the "to be chased" status ought to be pink, not red. Just update a row in the database, and it's done for everyone, yay!

The fact that it might cost a team-month to develop the configuration management subsystem for options that are changed, perhaps, only once a year, doesn't seem to trouble the team's goal donors however. The need for user-accessible system configuration control sometimes reflects the unhappy relationship between development teams and user teams. It says "we don't want to have to call you to make this change, you're too slow".

Nowadays the distinction between config and code is blurring. A Spring configuration file is really executable code, just written in XML. In Ruby, the distinction disappears altogether. Ultimately, there is no fundamental difference anyway - java code is just a configuration of the jvm; the OS is just configuration for the hardware. A dynamic language is what you end up with when you make your software totally configurable.

Design Patterns Considered Harmful

As for coding to interfaces and the whole Façade/Service/DAO thing, I can't fit it into the Dinosaur Theory of software development. "Teach Yourself Design Patterns in 12 Days", might be responsible, or perhaps a corporately-misunderstood two-day crash course on the topic. One important use of the Façade pattern is to hide a horrible, complex and difficult subsystem behind a single, simple, interface. The thing is, if you're writing the subsystem yourself, it's not going to be horrible, complex and difficult, right? Façade is just another way of telling your legacy colleagues, "your API sucks but I can work around that". You would just never use it on your own code!

While the goal of writing reusable code is noble and all that, the sad truth is that un-reusable code, i.e. code that solves the specific problem you have right now in this specific project, is much simpler to write and maintain. In fact, it might even be simpler to write your own thing from scratch than to use someone else's "re-usable" component. As your code grows, and as you tend your code and listen to where it's hurting, it will split naturally along implicit fault lines, and where you break a class into smaller pieces, each of these pieces will be naturally re-usable because you are already re-using them in real-world cases inside your real-world project. Designing explicitly for re-usability rarely pays off.

When I was at university, Interfaces were the thing. I got points in exams for Interfaces. But an interface covering every method for each of your business objects? Meaningless! Pointless! Clutter! Writing to an interface doesn't make your code re-usable, if the interface itself isn't re-usable.

If you have read this far, my commiserations. I'll try not do this again. Please be assured that any resemblance to any real persons or situations, living or dead, past, present, or future, is entirely accidental and co-incidental. It's not you. Leave me alone. End of rant.

21 May 2008

Respect The Machine

In a survey conducted recently (using the acclaimed dalton fast-answersTM survey technique*), most respondents claimed that respect for another human being motivates their behaviour more strongly than respect for rules imposed by a machine. More simply, people are more willing to break rules imposed by an abstract authority, than to break rules that might directly hurt another human being.

So, in Paris there are two official ways to cross the street - at painted zebra crossings without lights, and at painted zebra crossings with lights. In the presence of lights, all users are obliged by the law to respect the lights. In their absence, the pedestrian has priority.

Curiously, real-world observations reveal that pedestrians, despite having the right-of-way on bare crossings, congregate at the edge of the road waiting for a gap in the traffic to cross. The drivers appear strangely willing to co-operate with the docility of the wheelless, in what amounts to a blatant violation of pedestrian rights, in which the pedestrians themselves are complicit.

Conversely, I could spend all day pushing the button at a dedicated light-protected pedestrian crossing, and snicker as drivers patiently stop for the ensuing red light and gaze upon footless black and white road stripes until the light goes green again.

What mystery underlies this paradox? What unfathomable fountain of generosity inspires these empowered pedestrians to cede their hard-won road-crossing rights to the mobile metal capsules of our oil-addicted era? And what inexplicable well-spring of patience seizes the hearts and minds of those normally stressed and terribly late and I-don't-have-time-for-pedestrians wheel-turners so that they idle precious seconds before the useless red light of an empty crossing?

Some have suggested that the truth may be more prosaic. From the perspective of the pedestrian, apparently, it is better to be alive than to be right. Fear of a gruesome death, and not noble generosity, inspires the humble pedestrian to stand and wait while those mindless nuts behind the wheel careen past. But how, in this case, are our drivers different from terrorists? How can we say we are civilised when every minute a pedestrian's right to cross the road is crushed by a ruthless driver brutally, savagely wielding the threat of mangling your corpse under his shining wheel rims? This is not the jungle!

I think it's all a big misunderstanding, really. In fact, pedestrians shouldn't worry themselves at all. On several occasions in my personal experience cars have stopped with great suddenness so that I could continue to cross the road safely and legally. Drivers, regardless of any penalties applicable to the situation in question, will never, I have learned, never risk getting blood on their bonnets, or bits of skull in their headlights, or perhaps the paintwork scratched by a protruding fragment of fractured bone. Think of the washing-up! Peeling off patches of skin and torn flesh! The headache of insurance and other administrative formalities! No, they will screech to a halt sooner than face that. And remember, to paraphrase someone wiser than I, it is only a small 95% of bad drivers that make all the rest look bad ...**

* The dalton fast-answersTM survey technique involves me imagining what people would say if I asked them, and compiling the results in my head. The approach is wildly popular for its speed in gathering information; however, some doubts have been raised concerning its accuracy (according to another survey using the same technique)

** Always excercise utmost caution in crossing the road. Never take legal, medical, financial, or road-crossing advice from a blog. Seek professional help from qualified practitioners before making any decisions.

12 May 2008

Listening to the Customer

So one evening my son decided he wanted to program, too. This comes up occasionally, but today he was more insistent than usual. I had heard about StarLogo and that it was a language used for learning programming, so I installed it, fired it up, and stared blankly at the various panels that were waiting patiently for my input.

- but I want to program, I want to program now!!

- hold on, I'm just figuring this out

- but I want to program, why don't you let me program

- I haven't a clue how this works, will you give me a minute

And so on, until I had a wonderful insight. I fired up a text editor, maxed the font, and handed him the computer. Whereupon he merrily whacked the keyboard randomly for the next ten minutes or so.

And the moral of the story: never forget to find out what your customer wants before starting work on the solution ...