Expensive Cheap Code

by Malte Skarupke

I was going to write a blog post about how to avoid a specific problem, until I realized that I should probably outline the problem first. I call this expensive cheap code, and I realize that the name is not a good name. It comes from buying the cheap version of something expensive.

When you buy something expensive, you do not want to get the cheap version. Because the cheap version will work, it just won’t work well. For example if you buy a big screen TV, but go for the cheap version, you may end up with a bad image quality that nags you every time that the colors are wrong. Or the image is stretched and you can’t unstretch without ruining all other channels. The right thing to do would be to get a new TV and get rid of the old one, but you don’t want to do that because even though it was the cheap model, it was still pretty expensive. And after all it only has small problems.

This is even more frustrating if you buy tools at the hardware shop. Since you probably don’t use your tools all that often, you will be frustrated for years with something that works, but doesn’t work well. And you don’t want to throw it away, because it works after all, and you don’t use it all that often.

You can run into the same problem with software. If you have a piece of software that does everything you could want it to do, but it just doesn’t do it well, you have a problem.

If it does everything you  want it to do, but you need to use workarounds to get around some problems in the code, or if it crashes 30% of the time while converting a file so that you have to run it twice times, or if adding a feature to a piece of code is a giant pain in the butt, you’ve got a problem.

If you’re lucky, that code needs refactoring and bugfixing, and you can solve your problem. If you’re not lucky, it is a scary piece of code full of dependencies and statefulness and undocumented necessary special cases that nobody wants to touch. Or the person who wrote it says “you have no idea how much work it was to get this working, I’ll never touch this again.”

Because hey, it works.

And so you’ll be working with this thing for years, and it will frustrate you over and over again, and waste a ton of time and money. And if you need a new feature from it, you will work around the edges and make the code even worse.

The best thing would be to either put in the amount of work to make it clean, or to throw it out. But you won’t do that because who has the time for that amount of work to fix a piece of code that is not broken? It’s just a bit tedious to work with, after all.

So I’ll probably write another blog post about how to avoid running into a situation like this in the first place. It’s all about how you go about writing your code and planning your systems. The short version of it is to write your first implementation as simply as possible, because you will never get your first implementation exactly right, and if you put in too much work you may get stuck with it. And plan for your first implementation to be replaced at some point. So design a clean, small interface for it.

I’ll write more about that soon.