How to control the metacognition process of programming?
by Laurence Chen
There is a famous quote: Programming is thinking, not typing. After doing this job long enough, sometimes, I feel I am doing too much typing. No matter whether humans are thinking or typing, they use their brains, so I believe the word “typing” is a metaphor: typing refers to the kind of activities that we are doing unconsciously, doing through our muscle memory, not through our deliberate attention. Many of us, with enough experience, use quite a lot of muscle memory. On the other hand, do we use enough thinking when we need to?
We, humans, make a lot of decisions in our daily life: a decision like buying a car, or a decision like naming a function. Evolution makes us become the kind of animal that we can delegate certain parts of decisions down to our subconscious minds, which we may refer to as the background process in our brain. Therefore, we can focus our mind on something that matters. Here is the problem: what if the subconscious mind is not doing a good job? Most of the time, it is not a big deal, and escalating the issue back to foreground thinking can solve it. For example, when you press <localleader> e e
to evaluate a form, but mistakenly evaluating the wrong form. You detect that, then you use your foreground thinking to decide what to do next. However, sometimes, when you know that the subconscious mind can not handle the job well before you begin the job, what can you do to prevent your subconscious mind from taking over control? Do we have any mechanism similar to the linux command fg
, which can bring a process from background to foreground?
I feel somewhat embarrassed to confess that, although I have been programming for ten years, sometimes when I encounter a bug, my brain first goes to the panic mode for hours, and then goes back to the analytic mode. Why? My theory is that when I developed my skills as a junior developer, I solved my problems in the panic mode: crazy goolging, trial and error, and etc. Year over year experience has trained my behaviors and muscle memory to debug in the panic mode. However, now I want to fix that. There are two methods that can help me control my subconscious mind:
- Explain the code to another person. (Rubber Duck Method)
- Ask myself some pre-made questions. (Drucker Method)
Remote work taught me the Rubber Duck Method
When working with the Gaiwan team, we are working fully remotely. Sometimes, when I want to find someone to discuss, I need to wait. Several times, when I encounter a bug and I want to ask for help, I write down all the details about the code, the environment, and how I have attempted to solve the bug. After I paste my bug report in the Gaiwan’s communication channel and take a 15 minutes break, the magical thing just happens: the muse comes to my mind. I solve it quickly and edit the message that I have already posted. The Rubber Duck Method really works!
Actually, I think the idea of thinking by explaining has different names: Rubber Duck, Literate programming, Feynman Technique, etc. They are all similar things.
Right question is like the fg command on your brain
Now, when I encounter a bug, I ask myself three questions:
- Do I use the scientific method to chase this bug?
- Do I have the correct system view of this problem scope?
- Do I have the necessary telemetry tool?
I have similar issues when I write a function, write a module, or prepare the deployment: Typing too much and thinking too little.
Here are some questions I made for myself, but still alpha version:
Questions for writing a function:
- Should I keep command and query separate?
- Do I write the contingent designs for errors like
try/catch
and logs? - Do I write the preventive designs for errors like
pre
condition orassert
? - Should the function name describe the purpose?
- Do I add some suitable doc strings on functions?
Questions for writing a module:
- Should I explicitly specify the APIs of this module, and make these APIs apparently different from internal functions?
- Has all the unnecessary dead code been removed?
- Do I design or use suitable Clojure records to model some immutable concepts of the domain problem?
Questions for integration and deployment
- Do I add appropriate tests on domain functions?
- Do I design appropriate feedback messages on setup scripts?
- Can some manual setup steps be replaced with automation scripts?
The question of using records needs more explanation: For some immutable concepts like uri, date, or connection, to represent them with some well-designed records will make the implementation details hidden in the proper layer. These immutable concepts tend to have a fixed set of related operations, which can be modeled using Protocol
.
I found that both explaining or asking questions can help me effectively. They help me train my subconscious mind and the more analytic thinking I use the better divergent thinking I get. Are you also using some questions? Tell us your fg
command.
Comments ()