Shooting hoops and why learning is non-linear

It’s April and the sun is slowly becoming more powerful, warming the people in the green and white deck chairs in Green Park in London. A few minutes ago, I took the tube to travel back to Heathrow Airport, and afterwards home. Next to me a man is playing a game on his mobile device. Despite feeling drowsy from the steady cadence of the train, I watch the man shooting hoops. For every ball that goes through the ring he scores two points. The man, in his mid-forties, scores most of his shots. After a while the game notifies him that in addition to two points for direct shots, for every shot that goes through the ring via the board he will receive four points.

The next level

I wonder what happens next. Shamelessly observing his mobile device I see the man changing his aim to make sure the ball hits the board. He fails and tries again. Again the man fails. He makes about eight attempts and continues to fail. Clearly frustrated about this, the man reverts to two point shots. After a couple of successful shots, he changes aim, with a slight change in movements. Again he aims for the board.  He fails again, but gets closer to his goal. He makes four more failing attempts before he finally shoots the ball through the hoop via the board. The game congratulates the man. He’s reached the next level.

image

Earlier this week I presented a talk on agile and related topics at DevWeek 2016, a conference for developers held in the great Westminster Central Hall, in the heart of London. As I think continuous learning and improving is an important and strong aspect of agile approaches to writing software, I made an attempt to explain that learning is not a linear process. My point is this: when you’re at a certain level, be it in shooting hoops or writing code, you slowly get better at that particular level. However, at some point you will reach the ceiling. And to get to the next level, you will have to come up with new strategies, new ways of coding, new design patterns you might apply. Now if learning was a linear process, you would slowly get better and there would be now level and no ceiling either.

New tricks

However, in my opinion, learning doesn’t work like that. In my opinion, there actually are levels. And to get to the next level, you do have to apply new strategies, new patterns, new idea. And when you do, this is what will happen: you will fail at first. In fact, the man on the train shooting hoops is a pretty good example of how this works. Not satisfied anymore with his achievements at the current level – all two-point shots – he aims to reach the next level – four-point scores – and fails. He changes his strategy. And for a while he doesn’t get any points at all.  No points. Be it counter-intuitive, but his performance drops when he first applies a new strategy.  It is only after a while, experimenting and applying new tricks and strategies, that he reaches a next level.

This pattern is not different when writing code. Whenever I have to solve a problem I start by just writing the code to do it. I make sure my code just does the job, and my unit tests run (usually). But then, often after having thought things true over lunch or a good nights sleep, I come up with a better solution. Less code, and likely more elegant code. So I start editing the existing, working solution. In most cases this results in even more code, or more messy code, and sometimes I even break the working code. So no points for me either. But then after a while and trying to apply different patterns or different constructs I always end up with a much more elegant solution, often with just a fraction of the lines of code I had earlier. I’ve reached the next level. I’ve learned.

Try

A few months ago one of the developers on my team, who is strongly in favor of a more functional style of programming, ported the Try class from Scala to Java, which is the language of choice with our client. The Try class is basically a monad that catches exceptions and allows you to concatenate functions without having to deal with endless try … catch blocks. So on a Tuesday morning I gave it a spin on an existing, working piece of code. At first, I didn’t really figure out how it operated, and it puzzled me greatly. My code broke, my unit tests failed. I thought this just wasn’t for me. But I could clearly see the benefits of not having to support all that ugly try … catch code. So the week after I gave it another spin, and this time I got it. And it changed the way I code. Almost all of the methods I write nowadays start with a return statement and only contain a single statement, wrapped in a Try monad. We’ve found new strategies, ran into some issues at first, but now we have reached the next level. I’ve even ported the Scala Try class to C# recently for another project. You can find it on my GitHub page (at github.com/aahoogendoorn/monads).

Experiment, fail and learn

You might ask yourself: why is it so important to recognize that learning is not linear? The importance lies in the fact that right before you reach the next level, there is a serious dip in your scores, in your productivity. In my opinion, too many organizations and far too many managers do not realize that in order to get better, you will need to try, to experiment, and to fail and find a different direction. Quite often there is no room to try, experiment or fail. Managers will show you the nearing deadlines,  and put the pressure on delivering your code faster. Even in most agile projects, there is a constant pressure to deliver as fast as possible. “We have to finish the sprint.” Even though I’m all fore fast and frequent delivery, there is a serious drawback, a price to pay. Because if you do not allow yourself the time and room to experiment and to fail occasionally, you will never reach the next level.  So dear managers, please allow your teams to experiment and fail, in order to get better. And please, dear developers and testers, allow yourself to do so too. Experiment, fail and learn.

This post is published in SDN Magazine, April/May 2016