This post is about a story that happened a few months ago.
Back then, I attended a three days Software Craftsmanship training on Test Driven Development. More accurately, it was about practicing TDD to gain back control on a legacy C++ code base.
Trainings, just as code, are never perfect. Trainers often have to take some shortcuts, provide only half truths, in order to get trainees from point A to point B in a short period of time. I know and accept this. Most of the value of a training is in the leads it provides you to go further.
Trainings are also quite surprising. Even those that looks like they have nothing to teach you are never completely pointless. There are great insights hidden in most knowledge you think you already acquired.
This training was no exception and definitively taught me much. That being said, it could have gone much better. Let me share with you that little story.
This article might seem like a bit of rant for some part. It will express some criticisms regarding this TDD training. Keep in mind though that these bad points do not represent the entirety of the training.
This training was still valuable and taught me much. I do not regret having attended it. It was definitively not in vain. I do not consider it a waste of my time.
But we should not be afraid of discussing things that went bad. On the contrary, identifying and describing symptoms is the first step to solve a problem and turn bad experiences into good ones. We will discuss this in the second part of this post.
First, the story
Do not worry, I will kept it rather short.
We are in March 2017. The 10 trainees come and sit in the training room. The trainer waits for 9 o’clock to start his training and chit-chats while doing so. Look like it is time. Here we go.
Presentation and build-up
Right from the start, the trainer tells us that he was a former developer, but has not written code in the past 6 years. He also tells us that he plans to discontinue this training. Technical trainings are pretty disregarded in his consulting company and he feels it hurts his career.
There is a slight bit of disdain in his voice too. Not a good sign. Let us try to forget that.
After the presentation, the training itself starts. The goal is to refactor a legacy C++ code base inspired from the Bowling Kata. A quick look at the code base: it is pretty crappy code. Lots of concerns mixed, dead code, bad naming… This is good. It is not one of these unrealistic examples. I like it.
The trainer gives us a quick recap on refactoring technique and TDD. We then form two groups of 5 developers. Each group has to work independently, refactor the mess, applying the techniques previously exposed.
In each group, there are 2 developers on the screen – one on the keyboard, one copilot helping with suggestions – and the three other developers just watching. Every 5 minutes, we switch.
Code 5 minutes. Alarm clock. Switch chairs. Help as code assistant during 5 minutes. Alarm clock. Switch chairs again. Watch the others struggle during 15 minutes. And so on.
I like pair programming a lot, but this is a bit stressful. Not much time to pause or think as a team. Not much time to draw or exchange. The fact that there are two teams makes it look like a race.
But hey, this is just a game, so let’s play it.
First misunderstandings & tensions
All hands on deck, we start to refactor the legacy code. We slowly manage to add acceptance and unit tests as instructed by the trainer. We move forward and we, as a team, feel quite proud of it.
We introduce our first STL algorithms, extract functions, separate classes, all to clean up the mess… This is when we receive a first slightly sarcastic comment from the trainer:
“Why are you C++ if it is to write functions outside of a class? Do you know about Object Oriented Programming? Why would you use C++ over C if it is not to write classes?”
This is an obvious lack of knowledge about the language. Someone tries to explain the multi-paradigm nature of C++. But the discussion is leading nowhere. The objections are dismissed. C++ is obviously an Object Oriented language. The trainer laughs a bit. Hard to know whether he is actually making fun of us.
I obviously agree with my teammate. The guys looks quite stubborn. But maybe we are too (we C++ developers are sometimes a bit too picky).
Anyway, learning C++ is not why we are here. We came to practice TDD.
Again, let us try to forget this and carry on.
Selling ideas vs Imposing ideas
Because the temperature of the room heated up with a series of misunderstanding like the one described before, communication slowly gets more complicated. The short 5 minutes round of code also participate to the tension.
Things starts to heat up again upon discussing some aspects of TDD, and more precisely regarding its application in our specific case.
Do we really need to add a test for this implementation detail? It seems to couple the test with the implementation and hinder refactoring instead of help it.
Do we need to add this test too? It seems to expand the contract of the function.
Isn’t that much mocking in our test a code smell? Could we try something else?
Looks like it’s fine to expand the contract of a function. And mocks are not a code smell.
These answers do not plainly satisfy us, but we understand there is no way around it. With a bit of frustration, we start to do things without fully understanding them.
We often hear that the best way to convince someone of something is to make this person part of the process of acquiring the idea (like making us rediscover the idea). This is clearly lacking here.
We are not 100% convinced. Tensions are stacking up.
No compromise, no apparent trade-offs
“Extraordinary claims requires extraordinary evidence”, said Carl Sagan.
One cannot sell ideas such as “tests replace comments and documentation” or “you do not need specification if you have tests” without solid evidence to back them up.
We ask questions and raise objections. For instance, C++ developers are pretty happy to have access to the documentation available in cppreference.com instead of having to read the unit tests of the STL. Surely some form of documentation or comment is needed, even if limited to some specific contexts.
But the trainer insists on these guide-lines being universal truths. We know it cannot be that simple. Similarly, he insists applying TDD has no trade-offs. We know there are always trade-offs. Most of us are not convinced.
It really starts to sound like dogmatism.
Now, we all know there are times where we need to blindly apply a recipe, before we can learn about its problems, and finally reach enlightenment.
We all know it, but we just forgot it. Frustration does not help.
Let us stop there
I think you got the picture. This story clearly shows a situation in which the trainer and the trainees gradually split in two camps, suspicious of each others. The dreaded “us versus them” phenomenon (*).
Be reassured. It never turned into an open war. No animal was hurt during the training. No blood was split on the ground. Everyone kept his calm. But the tensions were there, definitely.
Overall, it could have been a much more pleasant experience.
(*) Because of the “us versus them” effect, my story is biased. My facts are biased. My interpretations are biased. I cannot be sure that the trainer said the things I think he said. Maybe he never said them, but we as a team understood it that way. But I am stuck here, I can only share my version of the facts.
Random thoughts on potential improvements
This training did not traumatised me per say, but kept me thinking. What happened? How can we avoid this situation to happen again? And if it happens, what can we do to learn from the training anyway?
Let us answer each of these questions separately.
What went wrong? What happened?
I still did not figure out completely.
I think some of the tension started to built up from the start. The way the trainer presented himself, as a non-developers, and as someone that did not want to pursue this training, this clearly did not help.
I discussed with another group that did the training 2 months later: they mentioned the same initial bad feeling about this presentation. It is amazing how a first impression can stick and never leave.
The second group of developers also reported a first misunderstanding, from which mistrust followed:
The trainer asked them to represent a Bowling Game as a hand written linked list of Frame, each Frame containing a pointer to the next Frame.
This design was (wrongly) justified by Domain Driven Design. The attendees got the feeling it was imposed on them. They did it, but reluctantly, after a discussion that heated up the room.
In both experience, once tensions started to build up, it quickly led to each camp defending their own views more aggressively. It then led to “us versus them” and a feeling of the other camp falling into dogmatism.
Once trust is lost, it is really hard to bring it back afterwards.
How can we avoid to reproduce these kind of situation?
Trust, respect, empathy, the will to learn, the will to teach…
For trainees, it is important to understand that the trainer will have to take some shortcuts. It also means not despising the trainer just because he is the trainer and not among the trainees.
For the trainer, I am convinced that it must be a developer. Doing the same job favors empathy, helps avoid the “us versus them” syndrome and enables better communication. It helps maintaining trust and respect too. Knowing about the job is also a must to be able to discuss trade-offs or avoiding dogmatism.
For both the trainer and the trainees, accepting we might be wrong is a must. Being proved wrong is kind of a gift, if we see it as a way to move forward. Obviously, this assumes the wish for everyone to move forward.
And this is critical.
Trainings should not be given by a trainer that does not want to offer this training anymore (and learn from the training as well). Trainings should not be attended by trainees that do not want to learn from this training.
This was not the case in this training.
How can we profit from such an experience anyway?
Let us say the training you attended was truly terrible. Most of what you were taught looked like bullshit. You are not convinced. No one from the audience seems to be convinced either.
What do you do?
Most good ideas get misinterpreted. Hearing about TDD (or Functional Programming, or anything) in an awful training (or presentation) does not mean the idea itself is terrible.
In fact, it may be completely the opposite. If the idea came to you, without you particularly looking for it, this idea is likely very popular:
- Most ideas do not get popular without some good reasons
- There is likely a real good idea hidden behind what you heard
So the best is just to go back to the source (at least if the subject interests you). Read the original books, publications or blog posts. Keep in mind that most popular ideas are victim of misinterpretation or dogmatism.
This is in fact the main lesson I learned from this experience. This is how I came to read Test Driven Development by example, to understand the idea behind TDD. This is also how I came to read Type Driven Development, right after a presentation on Idris that did not convince me.
Even if it turns out that, after some research on your own, the idea is just bad (quite unlikely), learning about it might still teach you how to distinguish deceptively attractive ideas from real good ones.
Key points for more enjoyable and valuable trainings
I would like to finish this post with some of the key points, stuck in my mind, which I think participate in making a training experience more enjoyable for everyone. Here are my best guesses:
Make sure to hire a trainer that enjoys doing the training. Do not hire someone who is not motivated doing it. Do not hire someone from a company whose trainers are usually not motivated.
Make sure to hire trainers that used and still use the techniques they teach, preferably in real life projects, preferably in a context close to your business. This greatly favors healthy discussions.
Do not be the jerk trainee that raises objections on every single simplification done by the trainer, generally on purpose and to facilitate the learning process. Trust the trainer and his experience.
Consider trainings as a starting point. Whether the training is good or not will not change the fact that you will have to work to acquire the skill. A good training will lead you further down the road, but you will still have to walk.
Finally, do not waste your time attending training you are not interested in.