Table of Contents

What LSD-Meth Is

Most people claim that there is a method to their madness; I, on the other hand, prefer madness to method. Accordingly, The Lone Software Developer's Methodology (LSD-Meth) is not really a methodology, but rather – at least when you read between the lines – a rant about embracing madness. No, really — madness is the modus operandum in software development, so you'd better love it or leave it.

When to Drop LSD-Meth

This doesn't mean that you yourself have to be mad to try LSD-Meth, though; it's probably enough that the following short list describe your predicament:

In other words, if you aren't working for or by yourself, you should drop LSD-Meth like a hot potato. Not that I've ever seen a hot potato dropping LSD-Meth. I just think that, if you have no say-so regarding your code, you're in a bad spot and probably feel like you need to drop something. Your job, for example. But I digress.

Profile of an LSD-Meth User

LSD-Meth is a good choice for people who don't mind

If this sounds like you, LSD-Meth is just what you need. Read on to drink my Kool-Aid.

Panicking All the Time

Some time ago, I started thinking about how to avoid bungling yet another hack. The first thing I chose to take into account was The Sacrosanct Deadline — the date on which a final product must be delivered. Now, deadlines are a funny thing because, for all intents and purposes, any deadline is reducible to next week, tomorrow, or even now. (I have found an excellent proof for this theorem that this web page's margin is too small to contain.) Therefore, being the sort to panic when facing deadlines, I figured I might as well get in that frame of mind ASAP and learn to live with it.

Procrastinating All the Time

A corollary of the Truth of the Sacrosanct Deadline is that one shouldn't plan too far ahead. This was a welcome realization because I think planning sucks; a lot of the time, it only leads to disappointment and wasted effort. Seriously, given that you have no time and when you're already screwed, why bother? Anyway, the only plan I was interested in was the plan to plan tomorrow. Or the day after. Maybe. So, in this frame of mind, I decided that, instead of planning really well so as to make the best use of my time before the deadline, I would instead avoid as much of the planning as possible and set my aims on the earliest attainable, improved, working system and then do it again… and again… and again… Each time, I thought, I would plan just a little (no more than was absolutely necessary) and get that little bit done, telling myself how I could add the other stuff later if I wanted to or had to; that way, when the real deadline came up, I wouldn't have to lament how I wasn't able to get this or that wonderful idea implemented, and (for once) I could feel good about having put things off.

Throwing Everything Together All the Time

So, having accepted immediate deadlines as a fundamental reality, and needing to harness my panic without a thought-through plan, it seemed consequent to pretend that any given coding session was going to be the last. This meant that every little bit of code would have to be integrated immediately after being written. After all, if I was going to have to submit a working product any moment now, I wanted my product to incorporate as much of the work I had actually done as possible because I don't want to look lazier than I am.

Screwing Everything Up All the Time

Now, such an approach precludes things like multiple release candidates, which are embarrassing, and final testing, which I didn't want to do. Actually, that's a lie: when each build might well be the last, each build is a release candidate, and all testing is final testing. But how might one achieve a final-tested release candidate for each build? With no show-stopping bugs, please? Answer: by writing unit tests that try hard to trip up any and all new code when it is written and running these tests automatically for every build cycle. I don't mind telling you that writing thorough tests all the time seemed like a lot of up-front toil, but I managed to convince myself that it was the sort of up-front work that, in the long run, would save me time: after all, in the context of the project, all new code would be just a patch against an existing code base, so… as I would already have automated unit tests for most of it, I would only ever have to worry (and write tests for) the very latest code. [Yes, I am a great rationalizer.]

Rewriting Everything All the Time

Actually, automated unit tests did more than take the worry out of adding code to the project: they also took the worry out of changing existing code. That's good because, whenever I write any code – whether it be for a new feature or an old bug – ugliness happens, mistakes happen, and madness ensues. Fortunately, though, not all code is born equal; that is, there is no silver bullet, but there is a silver spoon: once you embrace comprehensive unit testing, any code you rewrite is born to a well-designed interface with associated tests. This was great news: I mean, here was a way of going about business that leveraged my weakness for tackling the easy things first to improve the quality of my code!

One Thing at a Time, All the Time

So, now I had an unexpected problem: how to make adding new functionality more attractive. For me, this meant that changes to the code base would have to look a lot like finishing touches – anything else would seem like too much work – while accomplishing more than just a face-lift. As it happened, the agile development crowd had already found the answer for me: during each release cycle, I would add that single feature which, amongst the immediately attainable, added the most value to the program. Thus, the most important things would be sure to get coded, and each release cycle would be as quick and painless as possible.

A Simple Question

And, so, I came at last to the issue of how to go about implementing a feature. I wondered how one might choose an implementation strategy for a feature; specifically, I asked myself whether, for a given interface specification, any two fully-compliant implementations would contribute the same added value to the system. If the answer were yes, then the cheapest implementation would be the best. But I had trouble believing that.

Software Engineering Methodology as Speculation

I reasoned that, if I only cared about increases in the net worth of the production system achieved during the current and immediate release cycles, the answer could in principle be yes, but that if the choice of an implementation strategy for the current cycle were to bear on the cost of future development, the answer would be no; therefore, I concluded, if one wanted to achieve a high net worth for the finished product, one would have to take into account the cost of all of the release cycles and choose the implementation strategy accordingly. But how could I reconcile that with iterative project scheduling, continuous production, and aggressive scope management?

A Better Question

At this point, I admitted to myself that I could not know enough about the future of the project to choose between two implementations on that basis, and I did not want to engage in sheer speculation; all I had to go on was the code itself. So I asked myself another question: given two pieces of code, each implementing the same interface specification, could I say that one was somehow intrinsically better? Because, if I could say something like this code is, in and of itself, more valuable to me than that code, then all I'd have to do is figure out what makes a piece of code better and just do that all the time.

Software Engineering Practice as Housekeeping

Mind you, I am not talking about the kind of better that means runs faster or consumes fewer resources or anticipates such and such a case or conforms to such and such standard or indeed most aspects of quality discussed in software engineering texts. I mean the kind of better that implies more valuable in the context of my approach. So what would make code more valuable to a fellow in my predicament? The answer is simple: that which makes code the most maintainable. I figured that, when a development methodology includes continuous refactoring, continuous testing, and continuous production as mandatory techniques, it is fair to say that the program is under a sort of continuous maintenance. That's why the patron saints of software engineering are Tim Allen and Lucille Ball.

=:-.

OK, that was pretty lame — and a clear sign that we have reached the end of this retrospective… at least for now.


Comments


. .