The third proposal

Defending six years of undocumented fixes that look exactly like cruft to a first-time reader is hard to do without becoming the person who says no to everything.

#culture #agency

A proposal landed in August to rebuild a client platform from scratch. It’s a good document, written by somebody sharp who has been inside that codebase for five months and isn’t enjoying it. Every criticism in it is accurate.

Then I went digging in the shared drive for what the platform had originally cost to build and found two more of them.

shared drive, oldest first
Rebuild recommendation.docx        five years ago
Platform rebuild options.docx      two years ago
platform-rewrite-proposal.md       last month
Text

Same client, same system, same conclusion, three different authors. Not one of the three documents mentions the others. The oldest predates me working here. It’s dated about a year after the platform went live, which is its own small comedy.

I keep turning that pattern over. When capable people independently arrive at the same conclusion, either the conclusion is correct or something is manufacturing it. I think it’s mostly the second.

Joel wrote the canonical version of this in 2000 and it hasn’t stopped happening once in the 23 years since. So being told evidently doesn’t help much. Understanding the mechanism well enough to talk about it without becoming tedious helps a little.

Write-only memory

Reading code is harder than writing it, and honestly that’s most of it.

When you read somebody else’s system you’re reconstructing intent out of artifacts. Every decision arrives with its reasoning stripped off. When you write, the reasoning comes for free because it’s yours and it’s happening right now.

I wrote up the order I read an unfamiliar codebase in years ago and went back to it later for the part I’d left out, which is that the difficulty never really goes away. It just stops being alarming.

So the existing system always feels worse than the imagined one. That feeling is a fact about the reading instead of a fact about the code. Code I wrote myself 18 months ago feels like this. I’ve proposed rewriting my own work out loud to people who knew perfectly well I’d written it 🫣

You’re comparing a known mess against an imagined clean thing. All of the old system’s complexity is visible because it’s sitting in front of you as evidence. None of the new system’s complexity is visible because nobody has discovered it yet.

The new one will turn out to be about as complex, because most of the complexity comes from the problem instead of from whoever typed the code. The second system is famously where that gets taught. I once budgeted an afternoon for adding one field to a product and lost four days to a data model. That wasn’t the previous developer’s fault either.

And rebuilding is more fun. Nobody says that part out loud in the meeting, but tbh I think it does a lot of the work. Starting from scratch reads well on a resume and there’s a demo at the end of it. Maintenance is archaeology. Its deliverable is a system that still works, which nobody photographs.

The flyers

The strongest argument against a rebuild is also the hardest one to make out loud because it comes out sounding like sentimentality.

A system that’s been in production for six years contains six years of accumulated response to reality. That’s hundreds of small corrections for cases nobody wrote down: the customer whose zip code has no space in it, the supplier whose feed sends dates in a different format one day a week, the payment provider’s sandbox that behaves differently from live, the redirect that exists because somebody printed a URL on a run of flyers.

Every one of those looks like cruft, the exact kind of thing a rebuild would clean up on its way through. And every one of them is a bug a real customer hit and reported and then waited on while somebody spent an afternoon figuring out what was different about them. Then it got fixed, once, at a cost.

(None of those six years were mine, incidentally. So I’m defending work I didn’t do, which is either a point in my favor or evidence that I’ve gotten romantic about a codebase. Take your pick!)

Rewriting means finding all of them again in production the same way, which is a customer hitting one and calling in.

That’s the last 20% everybody talks about. It isn’t 20% of the features. It’s every behavior in the system nobody wrote down. There’s no document you can read to shortcut it because if that document existed then this wouldn’t be the problem in the first place.

So when is it right?

I’d have no credibility on any of the above if I didn’t mean this part. I’ve argued for a rebuild myself twice.

When the platform is genuinely dead, like a runtime with no security patches and no upgrade path or a framework whose maintainers have wandered off to other things. At that point you aren’t choosing whether, you’re choosing when. The useful conversation is about the date.

When it’s small enough to be wrong about. I think this is the single biggest predictor of how it goes and it gets underweighted every time. A rebuild you can finish in five weeks is a different animal from one estimated at nine months, and not because the work is different in kind. The five-week version can go badly and everybody survives it. Nine months can’t.

When the requirements have actually changed. If the business now does something structurally different then you aren’t rebuilding the same thing at all. Nearly everything I said above stops applying because those accumulated edge cases describe a problem you no longer have.

Moving a store off a server we controlled was roughly this shape. It got sold internally as an infrastructure decision when it was really a decision about which problems we’d be allowed to have.

When it’s demonstrably cheaper than keeping the old one running. Sometimes it is! Just make somebody show the math instead of the feeling.

Yes, and

The practical part, because “this is usually a bad idea” isn’t a sentence you can say in a meeting without turning into a character.

Agree with the goal and question the mechanism. The goal is never “rewrite it.” The goal is “this is too hard to change and it’s slowing us down,” which is true and which everybody in the room already agrees with.

So what specifically is hard? Which changes take longest? About 20 minutes later the two of you are looking at a list instead of at each other.

Ask for a range and for the reason it’s that wide. A rebuild estimate is the widest one anybody will ever hand you. The honest version of it clarifies things in a way one number never does, which I went on about at length in 2018.

Asking what the pessimistic case is and what makes it pessimistic isn’t hostile. It’s the same question I’d want asked about my own numbers.

Ask what happens if it takes twice as long. Not as a gotcha, but as planning. Every rebuild I’ve watched has run at roughly double. If double is fatal to the business then the plan has no slack in it, which is worth finding out beforehand instead of afterward.

Propose replacing one piece instead. Take the worst part of the system and redo it behind the same URLs in a few weeks. If it goes well you have evidence and momentum and a pattern you can repeat. If it goes badly you’ve spent a few weeks and learned the thing the nine-month version would have taught you in month seven, at roughly a twentieth of the price.

And be willing to lose the argument. Whoever wrote that proposal has spent five months inside the code and has a far better map than I do of which parts hurt. They might know something I don’t. If I’ve already decided then the conversation is theater and they can tell it’s theater.

This meddlesome stockroom

The year before I had a job in tech, I learned the one-piece-at-a-time rule the expensive way in the men’s shoe stockroom at a department store.

It was a mess. Somebody had once made an attempt at order and nobody could tell you what it was.

Then somebody, a manager I think, said in passing that it’d be nice if the whole thing were alphabetized. It was a “will no one rid me of this meddlesome priest?” moment. I was the one who heard it that way. Nobody asked me to do anything.

So I started pulling boxes off the shelves and re-sorting them. My shifts were about four hours if I was lucky, sometimes days apart. Every one of them got interrupted by somebody on the floor needing a 10 and a half in brown.

I never once had a block long enough to finish. Every shift ended with the shelves half in the old order and half in mine, which is worse than either. By the time I left that job the stockroom was a complete disaster, stuck in the middle of a refactor and arguably worse than I’d found it.

I should have done one brand at a time and finished it before I clocked out, so each shift left something the next person could use. That’s the same five-week argument. I make it in meetings with a straighter face than I’ve earned.

The boy who cried no

The part underneath all of this took me about eight years to notice.

The developer who objects to everything stops being heard. Not because they’re wrong (they’re usually right more often than average) but because “they’ll say no” becomes a known quantity and people start routing around it. They stop asking. Decisions get made in a channel you aren’t in and you find out afterward.

So opposition is a budget and it’s smaller than anybody wants it to be. Spend it on the ones that matter and say yes to the things you’re merely unsure about. Be visibly delighted when you turn out to be wrong, because the times you’re wrong pay for the times you’re right.

Five weeks instead

With the August proposal we actually took the worst part of the system, the ordering flow, and gave it five weeks behind the existing URLs. It went fine. It also turned up two behaviors nobody on the account knew were there. We’d have found both of them much later and much more expensively.

Nobody has raised the full rewrite since. I don’t think that’s because anybody won an argument, either. “This is too hard to change” just stopped being true of the part that was actually hurting. All three of those documents were downstream of that feeling instead of downstream of the code.

That leaves me not really knowing what to do with the other two. Filing them somewhere the next person will find them feels like the right instinct. It also feels a little like leaving a note that says we considered this three times and decided against it, which isn’t what happened. We didn’t decide against it three times. We ran out of appetite three times. That’s a different thing to write down.

Read similar posts

View posts by tag

#accessibility #agency #ai #careers #cross-browser-compatibility #css #culture #debugging #documentation #ecommerce #forms #git #html #images #javascript #performance #php #privacy #scss #security #shopify #small-print #tooling #typography #wordpress