What are mental models?
Mental models are like the maps in our minds that help us make sense of things. They’re the reason we think some things are more important than others and they help us figure stuff out.
Basically, a mental model is our own understanding or representation of how something operates. We can’t remember every tiny detail about everything, right? So, we create these mental models to break down all that complex info into bits we can easily manage and understand.
“You do not rise to the level of your goals. You fall to the level of your systems.” – James Clear
We can aim our sights high, but they need to be matched with our support systems. Or more simply, what you achieve is the result of your systems, the result of how to follow your internal/external processes, and not the result of aiming high.
Why are they important to you as a software developer?
In a previous blog, we discussed the difference between junior, mid-level, and senior devs being Ticket Closers, Problem Solvers, and Problem Framers, respectively. If you haven’t yet, take a quick minute to read Redefining Seniority: From Ticket Closers to Problem Framers.
If you want to be that Problem Solver, or even if you start out as a Ticket Closer, you need a system, processes, and ways of thinking that support your work. You need a way to face problems, read that code you have to maintain it in the most healthy, productive, and professional way. Most importantly: you need to do it without reinventing the wheel.
Mental models can be comparable to design patterns – they are general, reusable solutions to frequently encountered problems. They aren’t ready-made solutions that can be directly applied; instead, they function as a set of best practices that can be utilized in a variety of situations.
Mental models for software developers
There are catalogs of mental models you can get online or in physical format. But, just as with design patterns, there can be instances where it’s challenging to apply the abstract description of the pattern to a practical, real-life situation where it would be beneficial.
Here’s a few examples of some mental models, along with real-life examples for practical application, that could be incredibly useful for software developers.
Occam’s razor
Occam’s razor is also known as the law of parsimony. It suggests that when trying to understand a complex phenomenon or solve a problem, one should always opt for the simplest explanation or strategy among the available options. It doesn’t guarantee the correctness of the simplest solution; just suggests that it should be pursued first.
In the software development realm, this model could be used when you’re trying to solve a bug. After some time hunting it, you start thinking you can’t fix it; then you start having a crisis of confidence (hello Impostor syndrome!); a couple of hours later you are questioning your career to end the day questioning your whole life. The next morning you realize that it was just a missing semicolon or a simple typo. The real problem (and the simple explanation) was that you were too deep down in the rabbit hole (or just exhausted).
The model of simplicity being utilized in software development also ties into the KISS design principle — Keep It Simple, Stupid.
Circle of competence
This model refers to the idea that each of us, individually or as an organization, has a range of abilities or understanding in certain areas. The concept emphasizes the importance of staying within your areas of expertise for decision-making and endeavors. Being aware of our limits allows us to understand when we have an advantage in a certain situation vs. when we have a rough edge that makes us vulnerable.
Defining our circles allows us to improve decision-making without our egos blinding us. Have you ever found yourself discussing a topic outside of your expertise, just to avoid admitting that you’re clueless? It’s not a comfortable position to be in, especially when it comes to making decisions. Knowing and honestly expressing the limits of your professional abilities ends up being better for overall communication.
Inversion
This is a simple but very powerful one. Inversion is a mental model where you approach a situation from the opposite end of the normal starting point. Instead of thinking about how to succeed, you think about how to fail. This helps you understand what mistakes to avoid.
Suppose you and your software development team have promised a client that you will produce maintainable code. What does that really mean? If you ask them, they will answer “Clean code”, as if that’s enough to guarantee the maintainability of your code. Instead, you can ask your team what they can do to make your source code unmaintainable. They may tell you “Don’t add any comments”, “use cryptic variable/function names”, or “code everything inside a single class/file." This will give you a handy list of things to avoid in your coding process, creating a guard rail for greater maintainability.
Inversion, as a method, can be challenging for us due to three key scientific reasons:
- Disrupts conventional thinking patterns
- Forces us to contemplate unwanted outcomes
- Shifting from regular problem-solving to inversion puts extra strain on our brains
Though it may be difficult to shift one’s mind to the inversion gear, it can be very useful to potentially revolutionize our own problem-solving abilities.
Second-order thinking
Second-order thinking is a mental model that involves considering not only the immediate results of decisions but also how those results might cause further effects in the future. This type of foresight can help prevent potential problems that weren’t immediately obvious and enable us to make more informed, strategic decisions.
This way of thinking is key in software development because we make so many choices throughout the day. “Should I update this tool to the latest version for this cool new feature? Or should I go with this new design style?” Every choice we make has an instant effect, and we usually get that part right. But if we don’t think ahead about what might happen next because of that choice, we could mess up other parts of our project, or end up with unexpected problems down the line because of unstable updates.
This mental model is especially important at the beginning of a project. At this time, you make many choices that are hard to change later on. Think about the ripple effects from architecture decisions, database types, cloud providers, and other foundational considerations.
Reciprocity
This one is a very simple, but powerful one. If someone does something to you, you’re likely to do the same thing back to them or to others.
An example of this could be when we do a code review for someone. If we’re kind, honest, and polite in our feedback, that person will likely do the same for us and even with other devs when doing their own reviews.
Inertia
Inertia is a basic rule in physics that says that if something is moving in a certain direction, it will keep going that way unless something else stops or changes its direction. This idea can also apply to different areas of our lives, including our jobs.
In many companies, even as they grow and change a lot, the technical parts like databases and programming languages don’t change as quickly. This is especially true for foundational aspects such as databases, programming languages, and cloud providers. Although it’s important to keep making things quickly and efficiently, we should also make sure they’re easy to maintain.
This idea of inertia applies to software engineering projects. Have you ever tried to shake things up right after joining a new project? It usually doesn’t go too well. The mind wanders to compare this model to Raiders of the Lost Ark, with Indiana Jones as the junior developer and the massive boulder as the project, rolling with all that seemingly unstoppable momentum behind him.
Sunk-cost fallacy
The Sunk-Cost fallacy is when we keep doing something because we’ve already put a lot of time, money or effort into it, even if it might not be the best thing to do now. The mistake is thinking that because we’ve already invested so much, we should keep going, even though we can’t get back what we’ve already spent. Basically, it means letting what we’ve done in the past affect our decisions now, instead of thinking about what’s best for the future.
This last mental model is very common in our field. How many of you have been involved in a software development project that ought to have been stopped far earlier? Yet, management pushed on until its completion, resulting in dissatisfaction all around, and the final product now lies forgotten on an unused server.
Don’t just point fingers at the managers. As software developers, we often create complex systems that can be expanded in every possible way, as per the client’s wishes. But we later realized that the client’s needs were much simpler than we initially thought. Understanding the risks associated with getting attached to projects for the sake of tradition can better inform us when to cut the projects loose and focus our time on more worthwhile endeavors.
Tools in your kit
In the world of coding, having mental models can help us think better and make smarter decisions. They’re like a guide map that helps us understand tricky situations, solve problems, and guess what might happen next. But there’s no one-size-fits-all mental model. They’re just tools for thinking, not strict rules to follow. It’s best to have a bunch of them in your toolkit so you can apply them to different situations.
At first, it might take some effort to get used to these mental models as you start using them in your daily work. But after some time, they’ll become like second nature and will subtly influence how you make decisions, making it easier for you to handle the complex world of software development. The goal isn’t to have an answer for everything, but to develop a way of thinking that lets you look at problems from different angles and come up with effective solutions.