Trying to be a Good Code Teacher
It’s a privilege to be responsible for the education of others. But it’s also tiring, relentless and a tough lesson in modulating your emotions. Undoubtedly, teaching programming is hard, especially on-the-job training where you are under pressure to produce deliverables.
Thankfully, playing the role of teacher also confers enlightening personal growth. Guiding a learner’s progress is rewarding; dynamically tailoring their learning plan in real time is a vigorous lesson in empathy; and trying to inspire the persistent desire to learn in others is a marathon of emotional intelligence training.
The opportunity to teach others is an opportunity for immense self-growth and self-exploration. By writing this blog post, I hope to solidify my learnings as a teacher and contemplate how I can improve on my many weaknesses…..
Walter White certainly found teaching to be a huge psychological challenge that took him on a voyage of self-discovery
A Bit of Context
There are many different contexts in which you can teach someone to code. From informal lessons on the weekend to structured classroom or remote training plans.
Beginners and students also vary in terms of experience. Some may be completely fresh to the concept of programming and technology. Others may be gamers who have hacked a few games and grown fond of programming. Some people might be extremely-talented experts in one field, and fancy learning to code.
For each type of environment and each type of student there are many variables that can affect how and what to teach them. To clarify, in this post I am speaking from experience of teaching people who are probably overall more intelligent than me, but only have basic coding experience, where all of the teaching is on-the-job with schedule and deliverable commitments.
Also to clarify, when I say teacher, I mean a programmer teaching someone else who is a programmer. Ergo, the role of teacher and not the job title.
Psychological Teaching Principles
Without doubt, the psychological aspects of teaching are the hardest in my experience. You need to continually control your own emotions whilst helping the student feel comfortable, respected and keen to learn.
Rule Number 1: Stay Calm and Respectful
I consider it a failure to get angry with a student or make them feel uncomfortable due to aggressive or edgy behaviour.
Whilst I always have rule number 1 at the forefront of my mind, sometimes I feel like I’m on the edge of transgression.
The problem is, when you are teaching one-to-one relentlessly over the course of weeks or months, it’s immeasurably fatiguing. That’s not an excuse for showing frustration, but an acknowledgement of the challenge in taming your emotions.
Regardless of the emotional challenge, I still do not excuse myself for showing frustration. Fortunately, I now recognise the problem as it happens. I am sometimes able to judge when I am slipping into that kind of mood, and I have found that getting away from the desk really helps.
Feeling a bit tetchy? Time to get away from the desk (image courtesy of http://www.freedigitalphotos.net)
Another trick I have is that I look at the person and think of a good time we’ve had together. Within seconds I feel a shiver of guilt at my behaviour, followed by an enthusiastic rush to redeem myself.
When I know that my emotions have convincingly beat me, and I let the student down by getting overly-frustrated, or a bit tense, I find a genuine apology is the best way to continue. For example: “Sorry about this morning. I got frustrated because I couldn’t convey my thoughts clearly and I can see that made it uncomfortable for you and hard to learn. How about I take the keyboard this afternoon and you direct?”
From my studies of psychology, I know that positivity enhances learning. And whilst negativity can sometimes shape more realistic perception, it is generally counter-productive for learning.
Therefore I think it’s vital to help a learner maintain enough confidence that they are enthused about learning, whilst not being overly-complimentary to give them a false sense of progress.
This is an aspect of teaching that I struggle with.
At present, I’ve found that genuine praise and empathetic reassurance do help. For example, I try to prove their self-doubt wrong with examples.
For praise I just explain when I think something is good and why. I might praise the expressiveness of a piece of code, or show delight at appropriate use of advanced language features.
Do you learn best when you are happy? (image via http://www.freedigitalphotos.net)
Believing people with an assertive voice is a natural tendency many of us have. Because someone speaks confidently or boldly and makes uncompromising assumptions, they must be right, right?
Unfortunately, these people are often wrong. Sometimes very wrong. Ingraining harmful or inaccurate opinions into the minds of others as facts.
You must use code comments abundantly. If you’re not doing TDD you’re a rubbish programmer. We are programmers, we just take requirements and write code — it’s not our job to ask probing business questions. You must not pass DTOs into your views.
None of those assertions is true or false. They all depend on context. Yet many people will take an uncompromising view on similarly-contentious topics and dictate that their sub-ordinates or students assume their context-insensitive opinion.
I try to maintain balance by caveating my opinions. I’ll often say: “they are x ways to do this. I prefer this way because it provides y benefit. But a lot of people do it this other way, which appears to give z benefit, even though I don’t like that way”.
Before you can be balanced, you have to admit to yourself that the your opinion is driven by emotion. That strong-held belief you have might be bad advice. It’s a big challenge, but it causes you to questioningly challenge your own assumptions.
I sometimes imagine that I am being streamed on youtube to a herd of angry programmers all waiting to jump on my opinions. This makes me try to precisely quantify my opinions to the point that no-one could take them out of context and flame me for (which is impossible obviously).
Transparency is a common tactic I employ. I try to explain why we are carrying out an activity in a certain way.
“I could give you the answer but I want you to gain independence at this kind of task”, “this code is messy, but it lets us focus on the underlying patterns which is what we are trying to learn” or “I know you want to learn, but it’s easier for me to teach this concept by me doing an example first and then explaining it to you”. These are a few examples of what I mean by transparency.
My belief in transparency is that it shows I am not a micro-manager of dictator. And just like good code, if you describe your intent the learner knows what you are trying to teach them, even if your execution is not logical to follow.
Technical Teaching Principles
Not only is teaching someone to code an adventure in taming your raw emotions, but you actually have to teach them technical skills. That’s an enormous challenge, too.
I firmly believe that pairing up is the way to go. But I have a few other tricks, too…
Balancing Pairing and Solo Time
Undoubtedly, pairing is my favourite practice for sharing skills, especially to inexperienced coders. Paradoxically however, one aspect of being a junior developer that frustrated the life out of me was constantly having to watch others and not getting any time to explore challenges alone.
As a junior (and still now) I found profuse learning benefit, and personal enjoyment, from the autonomy of exploring codebases and the freedom to create something functional using new technologies — when I had time to organise my thoughts and go at my own pace.
Working alone helps people grow (image via http://www.freedigitalphotos.net)
Also as a junior (and still now) the mistakes I made and the thinking patterns I developed when engaged in solo activities were complimentary to those developed when pairing up.
Large amounts of both solo time and pair programming have helped me to continually improve as a software developer throughout my career. When teaching someone, I try ensure that they are given adequate opportunities to build both skill sets.
If I’m unsure, I’ll ask the learner how they feel: “Want to tackle this on your own, or fancy pairing up”?
Minimum Possible Teaching
Painful. That’s how it feels as a junior when your teacher owns the keyboard and does everything, or when they relinquish the keyboard only to dictate every stroke. Unsurprisingly, I feel like this approach was the least effective for helping me to learn.
Instead, as a teacher, I continually think: “what is the least amount of help I can give the learner to help them learn the valuable lesson(s) from this activity”.
One actualisation of this philosophy is letting the learner make mistakes. For example, when there’s a bug in their SQL statement, I’ll wait for the system to blow up at run time, even though I can see it’s going to go wrong.
Firstly I think this is a more effective way of learning that creates a stronger memory and understanding. Secondly, I want the learner to feel that I am not going to help them fix every mistake. I want them to feel some independence and not just feel that I’m a safety net.
I perceive minimum possible teaching like holding a toddler’s hands ever lighter until they can finally walk unassisted.
Deconstructing a Problem into Small Solvable Tasks
This is where my psychology education firmly drives my beliefs. I know that studies have consistently shown that it is easier to learn something small in isolation. In essence, remove everything that is not directly related to the learning activity.
But extraneous detail is abundant in code — especially an advanced language like Scala. With intricate concepts deeply connected, there is a lot of complexity that overwhelms the learner.
A classic example is syntax. If you want to teach someone a particular language feature, say pattern matching, using a real code base, there will be so many details in the code: frameworks, design patterns, other complicated syntax. How can you just explain the pattern matching with all the noise surrounding it?
Conversely, how can someone understand the code if they don’t understand the basic syntax and modelling building blocks?
To remedy this problem I try to break down the code into small chunks. One tactic is to refactor out the specific block, e.g. a pattern match, into it’s own method. Then, just explain the method to learner, or ask them to implement it.
Sometimes I think it’s better to get away from a real code base and just dive into the REPL to teach basic concepts.
Expressing the Bigger Picture — It’s not Just Code
A common experience of mine is developers whose lives start in Jira and end in their IDE.. with very little in between or either side.
When I teach someone, I encourage them to focus on the bigger picture. Even for simple programming tasks, I ask them to think about what value it creates for the business.
I try to point out how we might be building the wrong thing or wasting time if we don’t understand the benefits of what we are creating. And as a DDD enthusiast, I always encourage people to increase their linguistic precision — to show off their knowledge of business concepts by expressing them in code.
Architecture diagrams and whiteboards are also good at making the discussion more high level. For example, encouraging learners to sketch out the flow of HTTP requests, I find, is a great way for them to better understand the flow of the user journey and the nature of HTTP (if they are learning it). Win-Win!