Welcome to a series of articles called "Not Our Fault", where I show bad design decisions and all sorts of bugs they lead to.
When building a house, you start with the foundation. It is important to make it solid for two reasons:
- if you make it weak, it will ruin everything you build on top of it, no matter how amazing it is
- fixing it would require an enormous amount of effort, if it's even possible
The same applies to programming. When you want to write some code, you don't start with metal and silicon. You use hardware and technologies already created by someone else, and that becomes your foundation. And the quality of this foundation affects everything built on top of it.
Recently I started noticing cracks in these foundations. Guys, they're everywhere! And more importantly, they affect all those beautiful houses built on top. We write code, but it breaks because the foundation is weak.
It's not our fault.
Lemme show you.
Let's talk about stupid names in this part.
Naming things is important. If you name a place "Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwhenuakitanatahu", you make trouble for people trying to spell it. If you give two subway stations the same name, people will fail to meet all the time — I've seen it in real life. Naming things in a confusing way leads to mistakes.
Programming is no exception.
In Python, we have re.finditer() to find all occurrences of some pattern. We also have a somewhat similar re.findall() (what for? I have no clue!). Now you want to find a single occurrence — how do you do that? Well, take the first result of re.findall() or re.finditer(), right? No, you fool! Python has a separate function for that, and it's called… no, not re.find(). What's wrong with you? It's called re.search()!
To remember, here's the rule:
- If you want to FIND one occurrence, use
re.search - If you want to SEARCH for many occurrences, use
re.find
Easy-peasy!
Now you want to work with a database and instantiate PostgreSQL. Which databases are there by default? Yeah, as you would expect: postgres, template0, template1. Now try to guess what they are for. What if I named them default, frozen_template, and template? See, it's much better with better names!
Aside from just choosing bad names, one can simply choose the same names. In Linux, there are useradd and adduser commands. They are different. I always prefer one of them, but I don't remember which one! There are also groupadd and addgroup.
In addition to the name clash, useradd has flag clashes as well:
-g, --gid GROUP name or ID of the primary group of the new account
-G, --groups GROUPS list of supplementary groups of the new account
-m, --create-home create the user's home directory
-M, --no-create-home do not create the user's home directory
-p, --password PASSWORD encrypted password of the new account
-P, --prefix PREFIX_DIR prefix directory where are located the /etc/* filesTry not to confuse -p and -P: the password is not important, so it gets the "small letter p", and the prefix is really important (you always change prefixes, right?), so it gets the "big letter P". Maybe. And nobody really knows what will happen if you write useradd --create-home --no-create-home. Maybe the universe will collapse.
Want more similar names for different things? git checkout <branch> switches to the selected branch, while git checkout -- . resets all unstaged changes. Don't ask, just remember.
On the opposite side, there is also the opportunity to take two similar things and name them as differently as possible! Just like in CSS:
justify-content: center; /* center horizontally */
align-items: center; /* center vertically */Another example of similar things with different names? Sure — git is a champion here! git switch <branch> is the same as git checkout <branch>. Pick one depending on your mood.
The examples above mostly just slow developers down by confusing them. But can bad naming do something destructive? Sure thing!
In JavaScript, they have a method that checks whether a pattern matches, and they decided to name it test():
> const regexp = /1234/
> regexp.test("12345")
trueWhat if someone one day forgets that test() does not actually test the whole thing, but just the beginning? Well, that someone could expose the AWS JS SDK repository, because an account ID check would compare only the start, granting access not only to account 1234 but also to 12340, 12341, 12342, etc. Isn't that nice?
Python also wanted to add some delightful confusion. strip("something") will strip the letters "s", "o", "m", "e", "t", "h", "i", "n", and "g" from the beginning and end of a string. "ethereum".strip("something") results in "reu", and I absolutely love how confusing that is! A classic example is url.strip("https://"), which looks harmless but behaves unpredictably.
One of my favorites is Bash's &. Look:
&&is logical AND, letting you combine the results of two commands&runs a process in the background
Yeah, just one more symbol triggers completely different functionality! So instead of writing A && B — which runs A and then B — people write A & B, which launches A in the background and immediately launches B. I suspect everyone who's ever written something in Bash has made this mistake. I sure did.
See the pattern? These errors happen because programmers make them, sure — but only because the mistakes were possible, practically handed to us by design! That's why it's called "Not Our Fault" — most of the time, we're just conductors, delivering someone else's chaos straight into production.

I can carry bad design straight into your project and make it explode! Oh, wait… something's wrong. Ah, I got it backwards — I'll actually make your project just work as intended, without unexpected outages. Boring, I know. But if you're into boring, working things, I'm the person to hire, and SlashHash.dev is the company to call.