I have been trying to notice more often the kind of mental models I use while programming. By mental models I mean some heuristics I use to guide my thinking when making decisions, planning my work, using my processes. In particular mental models related to adding non trivial features to large codebases.
I think having good mental models and knowing when to apply them is what Dreyfus considers developing an intuition to guide decisions.
This is not an exhaustive list (you could likely find a programming related example to all the mental models explained in this article). But here are a few things I have observed about the way I do things recently.
I imagine working in a non trivial feature to be something like going through the idea maze. There are many potential solutions to a given problem, multiple branches of a decision tree and my goal is to navigate through the possibilities and choose one.
Choosing a solution is similar to doing cost optimization: I want to minimize development/maintenance time, defects, complexity, while maximizing business value. Ultimately any feature is going to cost something, and I just want to make sure that the costs are reasonable within the value that the feature is bringing. The questions that are often running on my mind are “Is this harder/more complex than it should be? Does this fit with the code/assumptions/patterns that are already in place? Is this the simplest way to solve this problem?”.
The decisions around a potential path to follow are often made at the beginning of a project when I have the least knowledge/information available. So, I like to mitigate the risks related to “unknown unknowns” by trying to validate/falsify my hypothesis as soon as possible. I will often do the tasks with the most inherent risk first, even if chronologically they should’ve been done later. Mocking behavior, feature flags usually help a lot with this.
Adding non trivial functionality to a large codebase involves getting acquainted with the code that affects/affected by what we wish to change. Effective code reading requires (quickly) getting a general sense of the structure/purpose of the multiple components but also thoroughly understanding the critical pieces. I think there is value in developing the intuition to distinguish the things that we need to comprehend deeply from the things we can just skim.