What is cognitive load and why do we want to reduce it? When you are reading a block of code, cognitive load is the mental effort needed to understand it. The greater the complexity, the higher the cognitive load—but there are tips to make the process more efficient.
Here are some examples.
Java code prior to Java11 could have very long declarations. Trying to read code like that is both painful and exhausting.
Java 11 introduced the var statement; C# did it as well, including C++ 11 with the auto keyword. Even replacing long type names with var makes a noticeable difference to cognitive load.
Here’s an example in C#:
public static class AnalysisVariables
{
public enum SurveyStatus
{
ssNext,
ssNewLevel,
ssEnd
}
}
The older way to declare an enum variable of this type is:
AnalysisVariables.SurveyStatus status = AnalysisVariables.SurveyStatus.ssNewLevel;
The newer way:
var status = AnalysisVariables.SurveyStatus.ssNewLevel;
What Causes Cognitive Load to Increase?
It’s tied into memory and what you can hold in your head. Without using any memory tricks, the typical human can remember seven objects plus or minus two in a list (or digits in a number).
But with code it’s worse because your brain needs to remember more than just digits; it’s using more brain resources remembering various code functions. Functions that are longer than a page can be a problem, as you need to scroll up or down or jump between bookmarks to handle it—all of it adding to load.
Programming Trade-offs to Reduce Cognitive Load
Here are some tips to make your programming experience a little bit smoother, cognitively speaking:
Try and Simplify Logic Where Possible
A very long block of code can be made more readable by extracting parts of into functions, even if the function is only called once. However, you need a balance, as too many small functions can be bad.
Make variable and function/method names just long enough to make sense but no longer. (A colleague insists on using really long names and it makes his code a bit harder to read; too-short names can be also confusing as they don’t reveal their purpose.)
Like most people who started off programming in Basic, my earlier code had lots of variables with really short names such as ‘a’ or ‘b.’ To be fair, RAM was a bit limited back in those 8-bit days, but there’s no excuse for that these days—with one exception: loop variables. Yes, good old ‘I’ gets used a lot in for loops and indexing arrays, a hangover from the days of Fortran when ‘I’ and ‘j’ were integer variables by default.
Remove Non-Alphabetic Symbols If Possible
When reading, some non-alphabetic symbols break up the flow, especially * for pointers. You have to pause and think, ‘What does it mean?’
In C/C++ by using typedefs to get rid of * for pointers, so that instead of
char * filename;
use this instead:
typedef char * pchar;
pchar filename;
However, sometimes, pointers can simplify things:
In a game, there are several places where you can index through an array, with code like this:
bullets[i].active=0;
bullets[i].x = 0;
bullets[i].y =0;
By switching to a pointer, the [i] could be removed from the assignments.
struct bullet * pbullet = &bullets[i];
pbullet->active = 0;
pbullet->x = 0;
pbullet->y = 0;
Other Ideas for Reducing Cognitive Load
Don't write clever code unless it makes the code significantly easier to read by others. Unless there is a very strong reason—say, performance that needs clever code—it’s not worth the effort and will make it harder to understand.
Limit the depth of the function calls and nesting of loops. Lots of function calls makes figuring out what’s going on harder, as do nested loops. Complicated guard logic can be simplified turning code like this:
func Something;
if thiscondition and thatcondition and not thirdcondition then
DoSomething;
end;
Into this:
func Something;
if not thiscondition return;
if not thatcondition return;
if thatcondition return;
DoSomething;
end;
Both have identical logic, but the early return statements simplify it.
Choose Composition Over Inheritance
This applies to object-oriented programming where you have a choice of composing objects or building them up using inheritance. For instance, if you have a ‘Vehicle’ class, you might create a ‘Bicycle’ class from it, or an ‘Automobile’ class. If you used inheritance, then your base class might be the ‘Vehicle’ class and the ‘Automobile’ class inherits from it.
The simpler way, though, is using components such as ‘Automobile’ plus ‘Motor’ plus ‘Wheels.’ It’s more flexible than inheritance, and easier to maintain.
Avoid Recursion
Unless your code is doing something that needs recursion—for example, doing a fill algorithm—an iterative approach is preferable. Recursive solutions need more thinking and care; you don’t really know how much stack memory it will use and it can even overflow the stack.
Conclusion
Modern IDEs come with excellent refactoring tools that lets you correct any badly named variables, functions, and so on.
If you want to see a programming language that pushes cognitive load to the maximum, try malbolge. For example:
(=BA#9"=<;:3y7x54-21q/p-,+*)"!h%B0/.
~P<
<:(8&
66#"!~}|{zyxwvu
gJ%
Which reads a string from a user and prints that string, I think.
Here are some other handy tips for dealing with cognitive load:
- Prioritize and Break Down Tasks: Divide large projects into smaller, manageable subtasks. This helps prevent feeling overwhelmed and allows you to focus on one thing at a time.
- Practice Mindful Coding: Pay attention to the present moment while coding. Avoid multitasking or letting your mind wander. This can help improve focus and reduce stress.
- Take Regular Breaks: Short breaks can help prevent burnout and improve productivity. Get up and move around, or simply close your eyes and relax.
- Optimize Your Workspace: A well-organized and comfortable workspace can contribute to a more productive and enjoyable coding experience. Ensure your computer is set up ergonomically and that your environment is free from distractions.
- Use Code Formatting Tools: Consistent code formatting can make your code easier to read and understand. Consider using automated tools to help maintain a clean and organized codebase.
- Learn and Use Shortcuts: Familiarize yourself with keyboard shortcuts for common coding tasks. This can save time and reduce the cognitive load of remembering commands.
- Document Your Code: Clear and concise documentation can help you and others understand your code more easily. This can be especially helpful when revisiting projects after a long time.
- Collaborate Effectively: If working on a team, establish clear communication channels and use version control systems to track changes and resolve conflicts.
- Manage Stress: Practice stress-reduction techniques like meditation, deep breathing, or yoga. These can help you stay calm and focused, even under pressure.
- Set Realistic Expectations: Avoid setting unrealistic deadlines or goals. This can lead to unnecessary stress and can negatively impact your productivity.
Keep all of these in mind, and you’ll have an easier time programming with cognitive efficiency. Reducing your cognitive load can not only translate into productivity gains but also make you feel more relaxed and balanced, especially during long workdays.