LIMITED TIME OFFER: 50% OFF OF PREMIUM WITH OUR ANNUAL PLAN (THAT'S $294 IN SAVINGS).
GET OFFER

Book Review: The Programmer's Brain

Recently I read the book by Flienne Hermans in the title of this article .
In 4 parts, it shares theories and practical tips on how we can Read, Think, Write, and Collaborate better on code. I will summarize its highlights, mixed with my own examples and opinions.

Part 1: On reading code better

1. Decoding your confusion while coding

This chapter introduces the 3 types of confusion and how they are related to which part of memory we are using:

  1. lack of knowledge —> Long Term memory issue
  2. lack of information —> Short Term memory issue
  3. lack of processing power —> Working memory issue

Lack of knowledge can be alleviated by getting more familiar with the programming language.
Lack of information takes patience and practice, to search through the codebase and collect function definitions and which other parts of code is calling the function (commonly called “tracing the code”), and to read documentation on any language built-in or library functions.
Lack of processing power can be supported by taking notes and writing thoughts/new findings/question on paper as they come, then organizing and dealing with them.

2. Speed reading for code

This chapter talks about memorizing and reproducing code as a measure of how well you can speed read. I disagree with the idea that the more code you can memorize and reproduce, the better programmer you are, because it doesn’t take much effort to ctrl+F (search) and F12 (Go to definition) in an IDE to refresh memory.
However, I agree having a good memory is important to learn data processing pipelines, when many pieces of data and types of data structures may be transformed through a series of functions existing in different files.

An interesting idea of chunking is introduced, which talks about how experts have better ways of remembering abstract concepts because they have been exposed to more of such frameworks. An example would be a beginner sees a list comprehension [2*item for item in iterable if lambda item: item[1]>10] and would be reading it from left to right, looking at 2, then item, then the iterable, then the lambda . Someone more familiar with the language would chunk it as [EXPRESSION for VARIABLE in SEQUENCE (optional conditional)] , then read in the order of SEQUENCE, optional conditional, EXPRESSION (kind of like reading SQL beginning with SELECT vs FROM). A large part of getting better in python is about knowing all the different data types and patterns that can go into each of these 3 chunks, something which experts have more experience in. Besides single line expressions, knowing about design patterns also helps programmers read larger blocks of code faster.

We can help readers by writing self-documenting code (comments explain why, code explains what), such as using variable names that explain the physical meaning. For example for i in data is more tedious to read than for row in two_dimensional_data , which still conveys less than for level in building.

3. How to learn programming syntax quickly

It talks about flashcards and spaced repetition. You can use online flashcard programs to help with this. 2 concepts to strengthen memories are retrieval practice (actively recalling) and elaboration (actively connecting new knowledge to existing memories), both of which take passion, effort, discipline, and some creativity.

A simple example of elaboration is when you know list comprehensions are [i for i in iterable] and set comprehensions are {i for i in iterable}, you may ask are tuple comprehensions (i for i in iterable)?

Another example is when you learn that instance attributes of a class can be accessed using dot notation, then come across namedtuples also using dot notation to access its fields, you start to thinking about what are their similarities and differences and how one can replace another in various scenarios to strengthen understanding.

4. How to read complex code

This chapter talks about 3 types of cognitive load (intrinsic, extraneous, germane) relating to how fundamentally difficult a problem is, how its representation (bad naming, file structure) adds to the difficulty, and how a student may have no energy to summarize small lessons into the big picture after an intense practice session respectively.

Two techniques to reduce cognitive load are:

  1. dependency graphs
    1. It helps to trace function definitions vs function calls, and how the arguments that go into a function are created, and how the return values are used. Pycallgraph2 (https://github.com/daneads/pycallgraph2) and pyan (https://github.com/davidfraser/pyan) are tools that help visualize function calls (how many times called, who called who)
  2. state tables
    1. This is suitable for loops where the same variable represent different values at various points during runtime. https://pythontutor.com/ is a tool supporting this.

https://images.unsplash.com/photo-1522435229388-6f7a422cd95b?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

Part 2: On thinking about code

5. Reaching a deeper understanding of code

This chapter introduced 11 Roles of variables framework (Fixed value, Stepper, Flag, Walker, Most recent holder, etc) by Sajaniemi, abstractions that help think about their purpose rather than just remembering the surface level name.

6. Getting better at solving programming problems

The bird between two trains problem was introduced (https://math.stackexchange.com/questions/784888/apparent-paradox-for-the-bird-traveling-between-two-trains-puzzle) to explain the importance of problem framing and not over-solving for information you’re not asked of.
Another time I went the hard way because I didn’t frame the problem was with this (https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/), you will feel like smacking yourself if you did the hard way, then realized the easy way that comes with reframing.

The most interesting example in the book: What happens to a snowman if you dress it in a nice, warm sweater? Will it melt faster or slower than it would without a sweater?

If your mental model is “sweater means warmth”, then you will say it melts faster, if your model is “sweater insulates” then the conclusion is it melts slower.

Different models are suitable for different problems, for most problems, the 1st model that comes to mind will work well, but having multiple models prepared can help deal with issues that basic models cannot explain.

7. Misconceptions: Bugs in thinking

Misconceptions are defined to be beliefs that are faulty, held consistently across various situations and with confidence. This occurs when someone has basic knowledge of a concept and tries to transfer it to other scenarios beyond its scope.

This often shows up when the mental model of mutability and variable assignment is not robust and people wrongly predict how the contents of mutable objects change or stay the same after multiple variables are assigned to the object and manipulated.

Also, beginners assume that variable names can only be used once, including inside functions because they transferred that knowledge from the idea before they learn’t to write functions, that each variable (in the global namespace) could only be attached to 1 object. After learning named functions, the learner then has to grapple with the scope of variables in unnamed lambda functions and how they are late binding (Common Gotchas — The Hitchhiker's Guide to Python).

https://images.unsplash.com/photo-1491245338813-c6832976196e?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

Part 3: On writing better code

8. How to get better at naming things

Feitelson’s 3-step method for better variable names is:

  1. Select the concepts to include in the name
  2. Choose words to represent each concept
  3. Construct a name using these words

The chapter introduces examples of name molds(max_benefit, max_benefit_per_month etc), different ways of arrange similar elements to express concepts.

9. Avoiding bad code and cognitive load: Two frameworks

This section lists some code smells from https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672 and organizes them into Method level, Class level, Codebase level codesmells.

10. Getting better at solving complex problems

This chapter was saturated with theory that doesn’t feel like it helps daily practice, but ends with some useful links to system design http://aosabook.org/en/index.html

https://images.unsplash.com/photo-1603841592856-8cae29c8a8be?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

Part 4: On Collaborating on code

11. The act of writing code

This chapter talks about the various activities (Exploration, Searching, Comprehension, Transcription, Incrementation) a programmer engages in, and how to handle interruptions. Mostly common sense stuff, but the frameworks are valuable.

12. Designing and improving larger systems

The author generalizes https://en.wikipedia.org/wiki/Cognitive_dimensions_of_notations to apply to codebases and terms it “Cognitive dimensions of code bases”. Knowing these ideas provides some criteria on how a code base can be good or bad for a particular purpose or at a particular phase in development and provides a common language for collaborators to communicate what they want to optimize in the code currently.

13. How to onboard new developers

After all the preceding theory, I like the human touch here on a senior staff can support a newcomer. It talks about the different stages of proficiency a newcomer can look to achieve, and how to work through a code base (how to take notes, what questions to ask to understand the code).

What I like about the book

  1. Many cognitive studies described and referenced at the bottom of pages
  2. Many frameworks introduced with easy figures and bullet lists that I can go back to work through
  3. Covers a wide array of topics concisely

Why you may find it boring

  1. Tons of theory that is not immediately applicable
  2. Common sense ideas that do not require the book to understand

How I will use the book

I foresee that many of the ideas can only be appreciated through actively thinking and disciplined practice, so I haven’t extracted the most value out of it in my one reading session.

Whenever I see a new codebase, I will take notes using the frameworks I learn’t to raise my self-awareness of why the codebase is difficult to work with, monitor my cognitive load, offload with pen and paper, segment tasks into smaller to-do lists and help me plan breaks and prepare big picture question to think of during breaks.

5 Likes