Cognitive load is an indication of how hard the brain works to perform specific actions. Although often used as just a conceptual model, cognitive load can be measured by watching cerebral blood flow while performing different tasks, and many formal studies of programming tasks do exactly this.
There are three different kinds of cognitive load:1
- Intrinsic load: How complex the problem is in itself?
- Extraneous load: What outside distractions add to the problem?
- Germane load: Cognitive load created by having to store your thoughts to long term memory.
If the intrinsic and extraneous loads have taxed working memory then there won’t be enough capacity to push information back into long term memory. This means that while we may solve the problems we were working on, we won’t remember what we did and certainly won’t be able to take any learnings out of it.1
When the cognitive load of the work we’re doing is too high then we stop writing to long term memory. Effectively, we stopped learning.
To ensure that we are learning all the time, we need to adopt strategies that will lower each of these kinds of cognitive load.
In the context of programming…
The intrinsic load is about the problem itself. Can we split the problem into smaller pieces to make it easier to understand? Can we look at other times we’ve solved similar problems to see if there are hints or “recipes” to follow? Could we work with another person to get a different perspective?
The extraneous load is about the outside distractions that add to the problem. If we have accumulated technical debt then this will add to the cognitive load.
We know that linguistic antipatterns, code that implies one behaviour and then does another, will increase cognitive load. “Furthermore, the results from the fNIRS device indicate that the presence of linguistic antipatterns in the source code significantly increases the average oxygenated blood flow that a participant experiences (ie the cognitive load that is induced by the snippet is higher)”1
Code smells also increase extraneous cognitive load.1
If we take the time to pay back that technical debt, we will lower cognitive load for all work we do here. Not only will that make us more efficient at working with this code base, it will also increase the likelihood that we will learn from the work we are doing.
Complex code, linguistic antipatterns, code smells, and other things we collectively lump under “technical debt” all increase cognitive load. There is a real cost to allowing these things to continue.
Multitasking will also add extraneous load. What if we focused on just this one problem until it was done?
Lastly, germane load is the cost of writing to long term memory. We either have enough capacity for that and information is saved for the future or we don’t, and we forget everything we’ve been working on as soon as we need short term memory for something else.
In conclusion, it’s not bad to work on cognitively challenging work. The problem only occurs when it so demanding that we no longer have the ability to write back to long term memory and therefore don’t learn anything from the experience. Any steps we can take to simplify the problem will be a win in these cases.
Related: SonarQube offers a cognitive complexity metric in their reports. While their approach seems reasonable, I haven’t been able to find any studies around the accuracy of this metric. That shouldn’t be taken as a reason to not pay attention to it, however. It’s very likely that the things it identifies, really will help.
-
The Programmer’s Brain: What every programmer needs to know about cognition by Felienne Hermans ↩ ↩2 ↩3 ↩4