by AC Gillette

A Linear View of Competence

I once saw a chart on the internet titled the Four Stages of Competence. It distilled the process of learning into a neat, linear pyramid, as if getting to mastery just required climbing from one step to the other.

hierarchy of competence

Looking at advice on the internet just seemed to reinforce this notion. The gulf between beginner knowledge and competence was one that was a linear journey. If you put in the work, the hours, the projects, then eventually you would find yourself at the peak of competence.

My First True Failure

There is failing, the low stakes kind where you sort of try at something and it doesn’t work, and then there is failing, that gut wrenching feeling when you throw yourself into a problem and only realize in the thick of it that you simply do not have the knowledge to succeed.

The first time I truly failed at programming was during the early part of my bootcamp program. At this point I was solidly in the beginner phase of my coding knowledge, with some basic Ruby knowledge under my belt.

As a side project I had built a project using openFrameworks, a creative coding library in C++. It was the first time I had created a compiled program, a pulsating 3D visual synthesizer that changed in response to audio input. I decided that it was something that I would like to put on a website and found Emscripten, a C++ to JavaScript compiler. At this point, I’d never programmed in JavaScript before, and had at best a rudimentary knowledge on using web tools or compilers.

I imagined, like most programming I’d done at this point, the process would go something like this:

expected programming process

Instead, it turned out something like this:

actual programming process

The deeper I got into it, the more I realized I didn’t begin to have the knowledge to troubleshoot my issues. When I first started programming, I was using mostly self-contained tools to build simple command line apps. Suddenly I was thrust into the deep sea of external dependencies, GitHub issue threads, and reading cryptic error logs.

After a couple of weeks of wrangling with an ever-growing list of attempts, I finally gave up. I couldn’t do it. I abandoned my code and ultimately erased it from my computer. The shore of competence was still a long ways off.

The Line Closes

The obvious lesson for this, and the one I took at the time, is that I hadn’t been programming for a long time and didn’t have the skills to attempt this particular problem. I just wasn’t competent enough.

I think this is partially true. But as the months wore on and I completed my bootcamp and entered the world of working with other software engineers, I began to see it in a different light.

The model of competence as a linear progression, and the pervasive idea we have that good programming comes with physical hours and elbow grease and if you fail it’s because you’re not putting in the work, puts so much of the pressure of success on the individual. When I started working with and talking to other engineers, however, I discovered something shocking. Even competent people were failing, and learning all the time, because programming is just plain hard.

Where I thought learning programming was like this:

expected learning progression

It actually turns out to be more like this:

actual learning process loop

Programming is not easy. It’s not intuitive a lot of the time, no matter who claims to be a natural. It’s a wild world full of languages, tools, frameworks and ever-changing standards that oftentimes aren’t built to be particularly human friendly. Even as a beginner, your failures are not solely due to lack of competence. The truth is, even with competence, the path to solving problems remains difficult.

There’s a certain sort of pride you see in programming communities sometimes in keeping programming difficult, a railing against perceived “easy” disciplines such as web programming or certain languages. Not as many people seem interested in discussing how we can make programming easier, more accessible, or at least acknowledge and support each other in working through difficult problems. A concrete example of making programming human-friendly is the Ruby programming language, which is beautifully designed to be read and written as naturally as possible. What would it look like if we made every tool we use this way?

As someone who has had imposter syndrome, as someone who bought into the meritocracy that the failing of understanding is on you, and as someone very new to tech, this realization was an important paradigm shift. Maybe we should stop shifting the burden of failure onto the individual, and start realizing that most of the problems will be hard ones and that’s okay.

AC is a web developer currently living in the Bay Area. When she’s not coding she can be found reading science fiction and dreaming of a better tech future.