Table of Contents
- What LSD-Meth Is
- When to Drop LSD-Meth
- Profile of an LSD-Meth User
- Panicking All the Time
- Procrastinating All the Time
- Throwing Everything Together All the Time
- Screwing Everything Up All the Time
- Rewriting Everything All the Time
- One Thing at a Time, All the Time
- A Simple Question
- Software Engineering Methodology as Speculation
-
A
Better
Question - Software Engineering Practice as Housekeeping
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:
- you can choose what feature to work on next and how to write it,
- you aren't sure what the guts of the finished program will look like, and
- you don't have to waste your time arguing about your decisions.
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
- panicking all the time,
- procrastinating all the time,
- throwing everything together all the time,
- screwing everything up all the time,
- rewriting everything all the time, and
- managing to do just one thing at a time.
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