02 July 2014
Programming all day is fun, but the reality is that I am in college studying something non-technical. I just wrapped up my third year of pursuing a BBA in International Media and Entertainment Management, a degree that focuses mainly on topics such as marketing, social research, and as the name suggests: management. While those fields are interesting in their own right, it is not the thought of The Lean Startup methodology or Alan Bryman's Social Research Methods that have me behind a keyboard late at night drinking coffee. Tinkering with computers is something special, there truly is nothing like it. Writing code gives you the chance to create systems only limited in their complexity and potency by your own capabilities and imagination.
Because the curriculum of my formal studies rarely ventures into the technical side of things I have to resort to refining my programming skills in my free time. Writing code during school nights and in the weekends is great but doing so during a break is great on a whole other level. The prospect of being able to sit down and hack away at the ideas in my head without disturbance is what has me counting down the days on the calendar for these rare long stints of uninterrupted time. Reaching that state of total immersion and focus is just a bit easier if the deadline for the next paper isn't in the back of your head.
For the past two years I have tried to use a large part of my summer break to sit down and teach myself something of value. In the summer of 2012 I spent many nights poring over Beej's Guide to Network Programming and taking apart the source of various packet forging tools in order to cook up a way to send data over wifi without associations, a project that in retrospect turned out to be an impractical solution for the problem that I was trying to solve but nonetheless served as a valuable learning experience. Last year I used the summer break to brush up on my PHP. I took a five month back-end web development internship after the summer and I felt the need to prepare myself because I wasn't really sure what to expect when transitioning from a hobbyist writing code to doing so in a professional environment for the first time.
Even though I ended up doing fine during my internship, there were moments where I struggled because of being a self-taught programmer. Those moments could often be attributed to situations where I had simply never before seen the problem at hand. There were also situations where I had encountered the problem before but in my non-traditional studies had only seen a specific implementation of the solution, failing to comprehend the abstract concept behind it.
When I think about autodidactism I remember reading Richard Feynman's biography Surely You're Joking, Mr. Feynman! where he mentions "having peculiar methods for doing integrals" because of being self-taught using the book Advanced Calculus by Frederick S Woods. Feynman argues that he had an advantage over his peers because he had a different "box of tools". He explains that the advantage manifested itself because only after his peers would have exhausted their own more standard "toolkit" they would come to him with their problem. If he was able to solve it with his less conventional methods he would then be regarded in a positive manner. During my internship I noticed this pattern as well, but unfortunately the dynamic works both ways. There were times where I felt at an advantage because of possessing some skills that might not generally be taught at a formal education, like jumping around in the command-line and configuring servers. A unix environment had always been my IDE so these things were native to me, but when it came to things like design principles and programming paradigms I felt at a loss. There was this layer of common understanding that the people with a background in formal education seemed to be having, a foundation of shared knowledge that made them able to communicate ideas to each other on a basis of relating the problem presented to a set of core principles that transcended implementation. A shared foundation that I was never forced to pick up on in my self studies.
Differentiating between programmers that are self-taught and those that have had a more traditional education is difficult because in reality all programmers are self-educated. The only way to really learn is by tinkering, and that is something that in the end you have to do on your own. Learning software development is an iterative process where you bounce back and forth between doing and soaking up information. Being self-taught and being formally educated are not mutually exclusive in programming, this is what makes it possible for people to be formally educated and have unconventional methods but also possible to be self-taught and have conventional methods. It is perfectly possible for someone to sit at home all day studying on coursera or reading through college textbooks to learn the same things as someone who is attending a computer science course at a university. Conversely it is also possible for someone who is a computer science major to pick up on unconventional skills because he chooses to start working on his assignments without reading the course literature, we can all understand the urge to start building the proverbial IKEA closet without reading the manual. What I observed for the real difference to be among programmers is the distinction between having learned using a structured set of information, and by means of the concept of "bricolage".
The word "bricolage" comes from the French "bricoleur", which means "handyman". Bricolage literally translates into the infinitive phrase "to tinker". Anthropologist Claude Lévi-Strauss used it in his 1962 book The Savage Mind to draw an analogy about mythical thought and how it "can reach brilliant unforeseen results on the intellectual plane" even though "the characteristic feature of mythical thought is that it expresses itself by means of a heterogeneous repertoire which, even if extensive, is nevertheless limited". This quote describes that mythical thought tries to solve new problems with the use of an existing collection of resources. Lévi-Strauss continues with his analogy where he states that:
The "bricoleur" is adept at performing a large number
of diverse tasks; but, unlike the engineer, he does not subordinate each
of them to the availability of raw materials and tools conceived and
procured for the purpose of the project. His universe of instruments is
closed and the rules of his game are always to make do with "whatever
is at hand"
The analogy of bricolage fits writing code really well, it is at the very core of hacker culture to celebrate the creative misuse of whatever tools and systems that are available. It is exactly this spirit that drives people to pursue incredible feats such as for example implementing a LISP in sed. It says a lot about the culture around programming that the collective instantly recognizes the ingenuity of such projects and have it upvoted to the top of Hacker News and /r/programming. The problem however with bricolage in a context where any task can be completed with any tool is that it becomes unnecessary to look for alternative and more appropriate solutions when encountering a new problem. If any task can be completed by "working with what you have" you are never forced to expand beyond your comfort zone. Here lies the danger of the Law of the instrument.
The general process for my learning has generally been a. form an idea of what needs to be done, b. find a way to do it, c. do it. This works very well for doing rapid development and picking up a wide range of knowledge along the way, however this bottom up approach forces you only to learn the bare essentials for everything you want to do, making it more difficult to form a big picture in the long run. Step b. "find a way to do it" is where the bricolage manifests itself. The way this works is that you start searching for the things you know (the available materials). You google for keywords that in your mind are related to the goal you are trying to achieve and when you find the solution you remember where to find it for the next time. This cycle repeats itself until you have a network of knowledge that enables you to solve many problems, but it won't necessarily be the best solutions. You keep adding knowledge to your toolbox based on the limited set of knowledge you already had, essentially bubbling yourself. You can not google for what you do not know.
Only looking for what you need when you need it introduces many blind spots (unknown unknowns). I believe that in order to minimize the effect the things that you don't know have on your work you can do two things: 1. get exposed to ideas novel to you and 2. move as far away from implementation and as close to concepts as possible by focusing on abstraction. The first one is like watching cable television instead of Netflix, how would you ever know you like watching manatees on National Geographic if all you do is queue the next Person of Interest episode? The second one is about learning "why" instead of "how". Both those solutions point to a formal education in computer science because a university will guide you by telling you what to study. Seeing as I am already in the process of getting a different degree I'm going to have to settle for something else.
I like books. Fiction, non-fiction, everything. They are a good use of trees and bytes and they often present information on a topic from start to finish in a nice structured fashion, something that the web often does not offer. Whenever you scour the internet for recommendations for programming books the top results are often K&R and SICP. While finishing K&R is still on my bucket list, SICP seems a more appropriately fit for current learning goals.
Structure and Interpretation of Computer Programs authored by Hal Abelson, Jerry Sussman and Julie Sussman is a well known computer science textbook that used to be taught as an introductory course at MIT. It is a book often praised for its focussed attention on abstraction and being one of the first book to teach "programming" instead of teaching a "programming language". Many have argued that even though the book was originally published in 1985, there still hasn't been anything written that teaches the concepts from the book better than the book itself. The book uses mit-scheme (a LISP dialect) to explain it's concepts. LISP is a family of programming languages that has been around since 1958 and is still relevant to the current industry, especially since functional programming languages are on the rise again. You can't bat an eye before come across someone's blog about that next new cool thing in Haskell or Clojure.
So as an attempt to break out of the cycle of predominantly learning only what I need to know in order to make things work, I have started working through the SICP exercises. So why specifically this book instead of any other book on computer science? I could argue that articles such as the one from Brian Harvey or Peter Norvig and Paul Graham's reviews on Amazon convinced me, but the reason why I haven't give up yet is because of the available community support. I have worked through a couple of exercises already and because of the large amount of blogs available from people who have already done the exercises, there is a unique opportunity to look into the thought process others had solving the same problems, which is really nice.