In programming, there are many lessons to be learned from experience. I had to learn the following nine programming life lessons the hard way!
The Cheapest, Fastest, and Most Reliable Components Are Those That Aren’t There
Gordon Bell once said this. The lesson to draw here is that you should keep a system or piece of software as simple as you possibly can. Reduce complexity to reduce the number of bugs.
A well-known software principle called KISS (Keep It Simple, Stupid), originating from the US Navy, basically says the same thing:
Most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.
Complexity can present itself in several ways. First of all, when building a system, you should carefully consider what components you need. E.g., if you’re using both MongoDB and Elasticsearch, you might want to use one of the two to reduce the number of components. The advantage, besides less maintenance, is that there’s less stuff that can break. Always be on the lookout for stuff that can be combined or stripped.
In your code, you should carefully consider which packages to include. If you are using just one function from some large package or dependency, maybe you’re better off implementing or copying just that one function.
Voodoo Coding
Sometimes, you manage to fix a bug but don’t understand why. Most programmers have been there but never, ever leave it at that. Always make sure you understand your code. Find out why this change did the trick.
This mindset will teach you more than books ever could. Don’t be ashamed and ask someone else if you need to. At some point, you’ll notice you’ve become the one people turn to instead.
The same holds for code you didn’t write yourself. Code from Stack Overflow, a blog post, or an AI assistant can save you a lot of time, and there’s no shame in using it! But AI assistants in particular produce code that looks convincing even when it’s subtly wrong. If you don’t understand the code, don’t use it yet. Read it line by line, ask the assistant or a colleague to explain the parts you don’t get, and test it. You are the one who has to maintain it.
Creating or using code you don’t understand is also referred to as voodoo coding. It’s a bug waiting to happen.
Code Never Lies, Comments Sometimes Do
Comments have a vital function, but if you can, don’t use comments and write more descriptive code instead.
“Wait, why?”
Comments are often overlooked while you change your code. Hence my statement: Comments sometimes lie (are incorrect) because the code around them has changed, and the comment was left untouched.
There are three ways to document code:
- Use comments inside your code.
- Write documentation in a separate document.
- Write self-documenting code.
Let me elaborate on that last point because that’s what I mean by writing more descriptive code:
- Use good design. Ensure your codebase is easy to navigate and structured logically.
- Don’t try to save characters. Use full names for your variables, classes, and functions. So, instead of
wm, name itwindow_manager. Instead ofrf, call itread_file_to_string. This name helps tremendously when you or others try to understand what’s going on after a few months of not looking at the code. - Extract as much as possible into functions and make these functions do one thing. Name them accordingly. For example, create a function that reads a file into a string, and name it
read_file_to_string(file_name). Without reading the code in detail, people will know what it does. Ideally, your code is a sequence of function calls like this that almost read like human language. Only when needed the reader can dive in deeper. This code documents itself!
Regular Expressions

When confronted with a problem, some people think, “I know, I’ll use regular expressions!” Now they have two problems.
It’s an old joke, but it’s true. Regular expressions are a pain. When you think you finally got it right for one case, it matches 70% of the next case you feed it.
This is just my opinion, but I’d suggest avoiding regexes like the plague unless you really can’t do without them. Often, a combination of string methods like split(), startswith(), endswith(), find() and slicing will do the trick and result in more readable code.
Software Is Like Cathedrals: First, We Build Them — Then We Pray
This one makes fun of the old way of building software: design everything up front, build it in one go over months or years, and hope it works when it’s finally finished. It usually doesn’t. By the time users see it, their needs have changed, and the bugs are buried deep in a huge system.
The lesson: build software in small steps. Get a simple version working first, show it to the people who will use it, and add features one at a time based on what you learn. Each step is small enough to test and easy to fix when it’s wrong. Eric S. Raymond made a similar point about open source in his essay The Cathedral and the Bazaar, where he contrasts carefully planned “cathedral” development with the “release early, release often” style of the Linux kernel.
Cheap, Fast, Reliable: Pick Two
I love this one because it makes the people hearing it (your managers) think for themselves:
- Do you want it to be reliable and fast? It can be done, but you’ll need to pay the best developers.
- Cheap and fast? Sure, but don’t expect it to be reliable!
- Reliable and cheap? Maybe if you’re lucky. But it will take more time to find someone who can do it cheaply, or it will require a lot of iterations (hence more time) to get it right.
There Are Two Difficult Things in Software Engineering
0. Naming things
1. Cache invalidation
2. Off-by-one errors
We humans generally start counting at one. Computers start at zero. This simple fact has been the fuel for numerous bugs and difficulties. Chances are, you’ve had your share of off-by-one errors already. If not, one day, they’ll get you too.
A Good Programmer Looks Both Ways Before Crossing a One-Way Street
The best software can handle all errors, and I mean all. Even those that “will never happen.”
Most software is written to carry out the “happy flow” in which everything works as expected, and the user doesn’t do weird stuff. The real world is messy, and over time, stuff that can go wrong will go wrong. Try to catch as many errors as you can — especially when your software is fulfilling crucial functionality.
Measuring Programming Progress by Lines of Code Is Like Measuring Aircraft Building Progress by Weight
More lines of code do not equal progress. For the same reason, writing more code than others does not mean you’re more productive.
The best code uses the least amount of lines to get the job done. However, this code is also the hardest to write. You might compare it to this famous quote:
If I had more time, I would have written a shorter letter.
It requires time and effort to write concise, well-functioning code. Usually, you need to refactor your initial codebase several times to end up with something that might come close to the most optimal, readable solution to a problem.
Thank you for reading. Please let me know in the comments what your biggest life lessons have been in your programming career.