free geoip The Most Common Question I Answer on a Regular Basis: "How Do I Learn How to Write Code?" - Jayson's Blog

The Most Common Question I Answer on a Regular Basis: "How Do I Learn How to Write Code?"

 

This is one of the most pervasive questions asked in my industry from folks who are not professional software developers, but perhaps have an interest in pursuing it as a hobby, or as a career: "So, how do I learn how to write code?" I'll start with my own experience as to how I got into this industry as a professional, will mention how some of my colleagues got started, and will try to wrap it all up with what I would have done differently and/or the ideal way to learn how to write software.

A common misconception about writing code is that it's difficult. Writing code is a very abstract process, and is only as difficult as you choose to make it. There are an infinite number of ways to achieve a working piece of software, some of them right, many more wrong. It's only through years of making lots of mistakes that you learn how not to write code, but I think very few professionals no matter what their skill level produce code that is 100% correct, and even the word "correct" in the software business is extremely objective. It's a craft that requires discipline, and the ability and patience to understand that you will make mistakes, miss deadlines, and go down tangents that end up in complete disaster. If you don't like constantly learning and reinventing yourself every few months, learning how to write code is not for you. You also do not need to be highly technical (though it certainly helps): Some of the best developers I've worked with wouldn't know a CAT 5 cable from a USB cable, but they can hammer out quality code like there is no tomorrow. Also, most folks think you need to be a mathematical genius to write code. It certainly doesn't hurt, but I think the most fundamental knowledge anyone needs to have is at least a high level mastery of Boolean Algebra and Predicate Logic and their sub-disciplines. Neither of these are as scary as they sound, and can be learned in a couple of weeks by anyone who has completed high school level algebra.

So how did I learn how to code? I actually learned the basics of coding long before I ever even considered making the transition into becoming a professional. I took Geometry when I was in middle school, and this was right around the time that programmable graphing calculators were making their mainstream debut (the TI* line from Texas Instruments). I was probably one of the few students who took the time to actually read the manual, and I discovered that the TI shipped with a rudimentary form of the BASIC programming language. I quickly picked it up and started writing simple programs to do geometric functions like finding the area of a circle, or the volume of a tetrahedron. By the time that class was over, I had written what would be in programming parlance a fairly sophisticated console application that presented the user with a list of function names that the user could choose from, then supply the necessary parameters needed for the calculations, and provide the correct answer. I ended up selling this app for 5 bucks a pop to anyone who was interested, and the teachers were none the wiser. Cheating? Perhaps, but just like any computer is, my TI was a tool to accomplish a specific set of tasks. As with any tool, if you can unlock its full potential, productivity goes up, and you needn't burden yourself with repetitive tasks. I actually learned more about geometry through programming the calculator than I did in class, because it forced me to really understand how these functions worked rather than just memorizing them. For those who bought my little program, probably not as much.

A couple of years later, my family purchased our first computer, a Macintosh LC II. I won't bore casual readers with the specs of that machine, but it was paltry at best. But, I started pouring through computer journals, and of course the LC shipped with a BASIC compiler, as well as this new language called AppleScript, as well as the precursor to the modern day framework of the web in that "cards" were "linked" to one another via "hyper" constructs. It was similar to Access, or more accurately, FoxPro in that it was a simple easy to use all in one RAD (Rapid Application Development) environment. I wasn't creating anything terribly useful, I just knew I thoroughly enjoyed typing instructions into a machine, and getting results back. I had no idea what I was doing was even a path I could eventually pursue as a career path. To keep this story short, fast forward to college (my first round) where I was majoring in Mathematics, and decided to take a computer science 101 course. It was this class that would cement my decision to pursue writing code for a living, I was exposed to the granddaddy of all modern day programming languages, C. Bear in mind Java was still just a twinkle in some engineer's mind somewhere, and the architect of .Net (Anders Heljsberg) wasn't even working for Microsoft. C and C++ were pretty much it in the programming space, and were core staples in any computer science curriculum. The power of C is pretty infinite: It powers the entire phone system, the power grid, nuclear powerplants…C pretty much runs most of the mission critical systems on the planet. It's worth mentioning that when I say I know how to program in C, I do NOT know how to implement the national telephone switching infrastructure, nor do I know how to write an operating system like Windows (which is written in C). The rest was history. I started taking numerous technical courses, as many as I could afford at the time that covered all aspects of computers, and within a year I was gainfully employed and writing code for a living. I initially started out in Java, then switched to .Net/C# (which is what I do most of my work in)…but this brings me to my #1 most important bullet point on learning how to code:

DO NOT PIGEONHOLE YOURSELF INTO ONE SPECIFIC LANGUAGE OR FRAMEWORK, NOR A SPECIFIC STACK OF TECHNOLOGIES.

I cannot emphasize this enough. Sure, plenty of programmers are experts in one specific field or area, and that's all they do (and are quite successful at it). What makes a great programmer is someone who becomes a student of languages and frameworks themselves, and learns the pros and cons of each one. No one can ever master all of them (there are thousands of languages), but knowing most of the big ones, as well as studying the history of programming (new languages always build off of old ones) is hugely beneficial. It's only by knowing from whence we came can we figure out where we're going. But, baby steps first. Once you completely understand my above underlined statement, it's time to hit the books and start doing.

I read. A lot. If I'm not writing code, I'm reading about code, or studying the history of coding, or thinking about how new(er) languages can help me out in projects. This industry changes so incredibly fast, it doesn't take much to fall behind the curve if you're not reading. Define "a lot of reading?" Before I ditched my physical books in lieu of replacing them all with their eBook counterparts, I had well over a hundred tomes on languages, programming theory, design patterns…each one averaging about a thousand pages, and I read them all cover to cover, hammered out every exercise in each one…repeatedly. This is in addition to the thousands of online journal articles, blog posts, forum threads, user groups, videos, podcasts…you get the point. In this industry, if you're not tryin', you're dyin'. The good news is that once you understand the fundamentals of programming, and learn the jargon/nomenclature, picking up new languages and frameworks is fairly trivial. I'll provide a list of the languages/frameworks I consider myself fluent in (e.g. I use them on a regular basis to get my work done), and follow up with a list that I think all programmers should know, or at least know about (as some of them are a bit arcane, but still fundamental in modern language design). In no particular order, I use the following on a regular basis (I will not provide wiki links for each, please use Google if you want more info for a specific item):

  • .Net/C#
  • C++
  • Java
  • JavaScript/ECMAScript
  • HTML/CSS
  • SQL
  • Ruby/Rails
  • Python/Django
  • XML (and all X* variants)

These are the languages I believe every professional programmer on the planet should know at least at a high level (concepts and theory). If you are new to programming, first learn:

  • C (for learning about pointers, the stack, and memory management)
  • BASIC (learning flow control/logic in programming as ALL languages implement these constructs)
  • SQL (if you are new, this language will not make much sense, but knowing WHAT it does is essential)

If you can become fluent in the above, you can pretty much learn any new language. However, learning a slew of languages does not a competent programmer make. Computer science students are notorious for the following: In most computer science regimens, students are subjected to a barrage of languages, and come graduation time throw all of these on their resume/CV without actually understanding why they were shown these languages, and what their strengths are. Languages all programmers should know by name, and be familiar with the theory behind them (read: at least know how these languages influence modern day languages. I consider the following languages the most important contributors to modern day programming:

  • Smalltalk (the entire concept of Object Oriented Programming owes itself to this one language, invented at Xerox-PARC, and the precursor to windows based OS's (Windows, Mac OS, *nix)). I personally think this one language has had the greatest impact of any language on programming, and computing as a whole.
  • Lisp (this language pretty much invented the idea of artificial intelligence). The concepts behind this language are incredible, and all modern day languages borrow something from Lisp.
  • Functional languages: Candidates are Haskell, OCaml, Scala (the hot new language du jour), and F#.
  • At least one compiled "enterprise level" language (Java, C#, C++)
  • At least one interpreted "enterprise level" language (Ruby, Python, Perl, JavaScript)

Ok so you've done your research, and have learned at least one programming language. What's next? Build something…and this is always the 2nd question I get after the person has gone off and learned a language: "Well, what should I build?" This is perhaps the hardest obstacle for new programmers. I almost always say "find a solution to a problem you are having"…such as my case where I decided to write a program to help me with my geometry formulas. Almost all of my personal projects involve making something I do on a regular basis easier to do with a computer. Or, I come up with little brain teasers to solve with algorithms, and then test the performance of my code. What are some of the brainteasers I've come up with?

  • Write an algorithm that accepts a string as an argument, and then reverses the string without using any built in string manipulation libraries that are available for the programming language.
  • Write a program that accepts a string as input, then tests to see if the string is a palindrome (e.g., reads the same way forwards as backwards, regardless of whitespace or punctuation).
  • Calculate the Fibonacci sequence using only recursion.

I'll provide my C# solution to the 2nd bullet from above, as well as a C++ solution that a buddy of mine wrote: How to figure out if a string is a palindrome:

   1: using System;
   2:  
   3: namespace Palindrome
   4: {
   5:     public class PalindromeString
   6:     {
   7:         static char[] _firstHalf = null;
   8:         static char[] _secondHalf = null;
   9:  
  10:         static string _stringToTest = null;
  11:         static int _halfwayMark = 0;
  12:  
  13:         static PalindromeString() { }
  14:  
  15:         static public bool IsPalindrome(string stringToTest, ref int numberOfIters)
  16:         {
  17:             ++numberOfIters;
  18:  
  19:             if (_stringToTest != stringToTest)
  20:             {
  21:                 _stringToTest = stringToTest;
  22:                 char[] stringChars = stringToTest.ToCharArray();
  23:  
  24:                 foreach (char character in stringChars)
  25:                 {
  26:                     if (!char.IsLetterOrDigit(character))
  27:                     {
  28:                         stringToTest = stringToTest.Replace(character.ToString(), string.Empty).ToLower();
  29:                     }
  30:                 }
  31:  
  32:                 _halfwayMark = (stringToTest.Length / 2);
  33:                 _firstHalf = stringToTest.Substring(0, _halfwayMark).ToCharArray();
  34:                 _secondHalf = stringToTest.Substring(_halfwayMark).ToCharArray();
  35:  
  36:                 Array.Reverse(_secondHalf);
  37:             }
  38:  
  39:             for (int i = 0; i < _halfwayMark; i++)
  40:             {
  41:                 if (_firstHalf[i] != _secondHalf[i])
  42:                 {
  43:                     return false;
  44:                 }
  45:             }
  46:             return true;
  47:         }
  48:     }
  49: }

In C++:

   1: #include <string>
   2: #include <iostream>
   3: #include <ctime>
   4:  
   5: using namespace std;
   6:  
   7: static bool is_palindrome( string t )
   8: {
   9:     const char *char_data = t.c_str();
  10:  
  11:     for( const char *start = char_data, *stop = char_data + t.length() - 1; start < stop; ++start, --stop )
  12:     {
  13:         while( !isalpha(*start) )
  14:             ++start;
  15:         while( !isalpha(*stop) )
  16:             --stop;
  17:         if( tolower(*start) != tolower(*stop) )
  18:             return false;
  19:     }
  20:  
  21:     return true;
  22: }
  23:  
  24: static bool is_palindrome_sl( char *t, int length )
  25: {
  26:     for( const char *start = t, *stop = t + length - 1; start < stop; ++start, --stop )
  27:     {
  28:         while( !isalpha(*start) )
  29:             ++start;
  30:         while( !isalpha(*stop) )
  31:             --stop;
  32:         if( tolower(*start) != tolower(*stop) )
  33:             return false;
  34:     }
  35:  
  36:     return true;
  37: }
  38:  
  39: static bool is_palindrome_ss( char *start, char *stop )
  40: {
  41:     for( ; start < stop; ++start, --stop )
  42:     {
  43:         while( !isalpha(*start) )
  44:             ++start;
  45:         while( !isalpha(*stop) )
  46:             --stop;
  47:         if( tolower(*start) != tolower(*stop) )
  48:             return false;
  49:     }
  50:  
  51:     return true;
  52: }
  53:  
  54: static bool is_palindrome_f( string t )
  55: {
  56:     const char *char_data = t.c_str();
  57:  
  58:     for( const char *start = char_data, *stop = char_data + t.length() - 1; start < stop; ++start, --stop )
  59:     {
  60:         if( tolower(*start) != tolower(*stop) )
  61:             return false;
  62:     }
  63:  
  64:     return true;
  65: }
  66:  
  67: static bool is_palindrome_fsl( char *t, int length )
  68: {
  69:     for( const char *start = t, *stop = t + length - 1; start < stop; ++start, --stop )
  70:     {
  71:         if( *start != *stop )
  72:             return false;
  73:     }
  74:  
  75:     return true;
  76: }
  77:  
  78: static bool is_palindrome_fss( char *start, char *stop )
  79: {
  80:     for( ; start < stop; ++start, --stop )
  81:     {
  82:         if( *start != *stop )
  83:             return false;
  84:     }
  85:  
  86:     return true;
  87: }

Once you've come up with a few short programs/algorithms to write, start writing! One thing I have done in the past is that I will attempt to write each of my algorithms in multiple languages, and then compare performance, how long it took to implement the algorithm in each language, and the ease of which it took to author. Repetition is key here, and once you begin to do the above over, and over, and over, you will begin to learn the intricacies of various languages and their strengths and weaknesses (something I do on a regular basis is "translate" applications from one language to another…note that this does not mean simply translating the syntax itself, you need to to accomplish the same functionality into the target language's best practices, and utilize any built in libraries to further simplify the solution).

Like any other discipline, repetition is key. Practice, practice, practice. Write code for fun. As strange as this may sound, I view many common problems that I see on a daily basis, and I then start to think to myself: "How could I solve this via a computer program?"  It's said that math is the universal language that can be spoken by anyone. I think computer programming is almost on par with math. Computing is ubiquitous amongst all industries, ergo, learning to speak the language of computers is a universal language that can form a bridge between disparate systems and frameworks. Computers glue everything together, and knowing the underpinnings of how computers work at a fundamental level, at the code level, will empower anyone who uses a computer to get their job done to make the machine work for them, and not against them.