“Education comes from within; you get it by struggle and effort and thought.”
— Napoleon Hill
We all know the feeling of flow while coding. It's that moment when you hit a consistent stride and leave the surrounding world. It becomes effortless to glide over problems in an autopilot state and obstacles shrink from the size of mountains to the size of pebbles. Of course, being able to hit this flow means that you have practiced the problems you're facing to the point where it's of second nature. But, how did you get here? You practiced in two ways. First, you practiced moving forward to a place outside of your boundaries. Second, you also practiced the skills acquired from this action. Typically, practice is associated with the latter, but what is missing from this view of practice is the need to feel uncomfortable again. For me, when I begin to see problems as pebbles, it becomes time to deliberately seek a new mountain to climb. Both the acquisition and the polish of skills are important, but I want to shed some light on the practice of pushing boundaries, better known as deliberate practice.
As programmers there are many ways to do this. Here are a few that I find the most helpful.
Impose Artificial Constraints
In order to challenge myself I like to constrain the way I write solutions to problems. I once attended a code retreat where we were not allowed to use if or case statements in writing Conway's Game Of Life. This constraint forced a movement from a comfortable solution to one that left my pair and I feeling uncomfortable with the proceedings. We were forced to think in new ways that expanded our ideas of what constituted a solution. The solution we eventually came up with was a challenge to write.
When the event was over I thought back on my experience and realized that not only did I challenge myself, but I had a lot of fun doing it! It's interesting to see the creatively that flows from constraints. Now, when I approach problems that would have forced me into a solution involving if statements, I can feel comfortable moving outside of that solution and benefit from the understanding my new perspective has brought.
Learn New Languages & Paradigms
Steve Kim has a great post about learning a new language yearly. I want to echo his sentiment as an important part of deliberate practice. When I begin to feel comfortable with a language I know it's time to pick up a new one. The first language I felt comfortable with was Java. While in school I was forced into taking my first jump to another language when, as a class, we dove head first into C++. It was extremely intimidating at first and I started to feel discouraged (I have to manage memory?!?). Thankfully, I didn't back down and when I got the hang of it I was able to write some fun code for an embedded project. If I had stayed inside of my Java comfort zone I would have surely missed the chance to work on the embedded project.
The next big jump for me was to Clojure. This endeavor was another tough challenge because it introduced new paradigms. After some time and many struggles it started to click. Now, Clojure is one of my favorite languages to work with.
When you're feeling comfortable in a language pick up a new one. If you're a Java programmer, like I was, try out C++. If you're a Ruby programmer try out Python. When you feel comfortable in a certain paradigm switch to a new family of languages. There are many paradigms to explore including:
Switch Domains
The development community has many subcommunities such as web developers, front end developers, embedded developers, game developers, and so forth. One way to deliberately practice my craft is to extend myself into other communities. There are new ideas to be shared in the areas of design patterns, system structure, and much more when developers begin to blur the lines between each of these subcommunities. As I said earlier I took on an embedded project. While it was hard at first, the practice of the embedded design craft is important to the learning process and the movement towards greatness. I encourage everyone to take a look at the opportunities to deliberately practice in new domains.
Challenge Yourself
Practice is a process which will ultimately move your skills into a better state. Part of treating software as a craft is to continually raise the bar and engage the surrounding community to raise the bar. When programming begins to feel a little bit mundane seek out an exciting new mountain to climb. I challenge everyone to take a portion of practice time to deliberately practice.