Become a Good Programmer in Six Really Hard Steps

One of the more popular topics here on the GDNet forums goes something like this:

"Hi, I just [bought a computer | wrote a simple game | discovered a game engine] and I want to know where to go from here. I'd like to [accomplish some particular goal] eventually. What do I need to learn to get there?"

First of all, understand that Peter Norvig nailed this on the head a long time ago: it takes ten years to learn to be a programmer. There's a glut of "learn X in some small number of days" type books out there; there are hordes of blog posts about "how to improve your programming-fu in a few easy ways"; and in general a lot of people come around looking for advice on how to become a whiz with minimal effort.

I'm going to change up the pitch a bit. Instead of Five Easy Ways to Make Your Code Amazing in 21 Days, I'm going to tell it like it is. Welcome to How to become a good programmer in six Really Hard steps.

Step One: Suck It Up. Get in it for the long haul, or take up bird watching.Sure, you can fiddle around and make nifty shell scripts and maybe a small game or four; if you're content with a limited skill set, by all means go for the fast-and-easy route. I'm not trying to diminish the legitimacy of that option at all - some people don't have the time (or even the desire) to become a master programmer. If you don't relish the idea of practicing this craft for ten years before you get good at it, then don't bother - but don't be fooled, you'll always be limited in what you can do and do well. If that is a reasonable trade-off for you, cool! You don't need to finish this article.

For the rest of us, though, there's something alluring about getting Really Good at programming. We want to be experts, ninjas, gurus - whatever noun of superlative mastery strikes your fancy. For us, ten years seems like a reasonable investment. Maybe a bit hefty, but hey, if it's worth doing, it's worth doing right... right?

So the first step to being a really good programmer is to bite the bullet. Accept that this is not just a ten year process, but a lifetime process. And as Norvig so rightly notes, do it because you want to. Nobody becomes exceptionally good at doing something they'd rather not be doing; the world record holders don't make it into the history books because they kind of accidentally ate the most hotdogs ever in one sitting, but didn't actually feel hungry that day.

Step Two: Write Lots of CodeIt doesn't have to be good code. It won't be good code, for a long time. Just crank stuff out. Any time you encounter a small annoyance in your daily computer life, think about how you could write a program to help solve that problem. Any time you find something interesting that you want to experiment with, do it. Play with new concepts and tools and languages, as much as possible.

The learning process is never going to stop, so if you approach this with the attitude that you get the most mileage out of cramming as much learning as you can into a given day, you will go far. Get into the mentality that a day/week/month in which you have not learned something interesting is a failure. There's enough stuff out there that you surely can learn something cool every day; this gets harder after the fifteen year mark or so, but it's still totally possible. No one mortal can assimilate all of the knowledge there is in the world about programming, so if you ever feel like you've run out of stuff to learn, find a new project and write more code.

While you're doing this, pay attention. Look for patterns - things you do often that might be useful to automate, or things you write a lot in your code that you might be able to separate into shared libraries or other centralized locations. Look for languages that make certain tasks easy. Look for other languages that aren't so good at those same tasks, and figure out why one is more productive than the other.

But most of all: write code. Every day, even if it's just a regular expression to search through your email history or something. Do something programming-ish as often as you can. And remember, if this stops being fun, go do something else; there's no point in this if you aren't enjoying yourself.

Step Three: Read Even More CodeOnce you have a small body of projects accumulated, start reading other people's code. At first, it will be difficult; they will do things you haven't seen before, or use styles you aren't used to, or even languages you haven't learned. If you find something cool, read its code if at all possible. Don't worry about deeply analyzing any given project, at least not at first; it can be a full-time job just to understand existing code bases like those of many large projects. Pick one or two things that you wish you could learn how to do, and find out how they were done.

Reading new code exposes you to ways of thinking that are new, and this helps stretch your brain. Stretching is vital to keeping up progress, and it will help ensure that as you go along you keep discovering new stuff to learn.

Be sure to talk to other programmers, too. Ask how and why they did certain things. Ask if they would do things differently in retrospect. Ask if they have any suggestions for your code. (But be polite; a lot of high-profile programmers are extremely busy and don't necessarily have the time or inclination to dredge through other people's work for free. Respect will carry you a long way; this is a tight-knit industry and reputation means a lot.)

Step Four: Learn Many Languages. Master a Couple.You will not have a practical surplus of time, at least not enough to master many languages simultaneously, unless you are exceedingly lucky. Therefore, learn as many languages as you can at a shallow level - enough to learn what makes them tick, what makes them good at their specific jobs, and what their weaknesses are. Stretching is important here; don't just stick to imperative languages like C, or "object oriented" languages like Java, or whatnot; expand into functional languages and declarative languages as well.

Learn a Lisp dialect. This is why. It won't do anything for your day-to-day programming, because you aren't going to use it; but it will make you a better thinker, and it will give you a deep understanding of the beauty of simple recursive systems. Stick with it until the "aha!" moment occurs; until then, it will seem like a soup of weird syntax and bizarre conventions. After that, it will remain with you for the duration of your career as one of the most astoundingly elegant concepts ever devised by mankind.

Then, learn a purely functional language. I recommend Haskell for this, because it forces you to be pure in ways that other functional languages (including most Lisp dialects) do not. You will have to bend your mind a bit, but once the inevitable "aha!" moment occurs (sometime around the point where you understand the purpose of monads, in my experience) you will again move forward a level in your thinking and ability to design elegant systems.

Finally, learn a declarative language. SQL counts, although it's a bit weak-sauce to just learn SQL. Prolog is often recommended, but isn't necessarily hugely accessible. In the realm of the practical, XAML, XSLT, and XQuery are good tools to know, and will introduce you to the concepts behind declarative programming. (In a nutshell, you tell the computer what you want it to do, and it figures it out; this is in direct contrast to imperative programming, where you tell the computer how to do things and hope it does the right "what", and functional programming, in which you describe transformations of data and types.)

As a bonus, learning XML-based tools after you learn a Lisp dialect will make it painfully obvious how desperately hard XML is trying to reinvent s-expressions, and just how poor a job it does.

Step Five: Create a Language.It doesn't have to be complex, or rich, or sophisticated, or even particularly elegant. It doesn't even have to be original; I often suggest writing a Lisp interpreter (bonus points for doing this in a Lisp dialect!) as a good way to learn the basics. In essence, you want to get a feel for the fundamentals of computer programming design: lexing, parsing, compilation, interpretation, virtual machines, and the myriad ways in which basic design decisions in a language affect how useful it is for various tasks.

This will accomplish three things for you:

You will gain a deeper understanding of how your tools of choice work, which will give you the ability to be more effective with them.

You will start to see reasons behind the design decisions of major languages and tools, which will both fascinate and irritate you (if you do it right). This insight will help you choose your tools more effectively when starting new projects.

You will glimpse the untapped possibilities that still exist in the creation of tools and languages, and hopefully open your horizons to a host of new opportunities for cool things to learn about and experiment with.

Step Six: Learn Something That Nobody Else Has Learned YetThis is the hardest and final step. Up until now, you have primarily been learning things that are already known; things that you can find out by reading other people's code, or books, or academic papers; things that are good to know, but not novel.

Now it is time to break free of the boundaries, and truly ascend to mastery. Now it is time to blaze a trail into territory that nobody else has ventured into yet.

Make no mistake; this is something you won't want to tackle until well after your "tenth year" of experience, mainly because until then you are far more likely to just be reinventing a wheel than actually doing original, novel research. But once you have a good grasp on the field, it isn't exactly difficult to find the sweeping frontiers of untapped knowledge that await computer science.

Chances are, this will take you another ten years, if not forever. Don't give up; remember, this should still be fun. If at any point in time you stop enjoying it, go do something else. Life is far too short to waste time trying to do something you don't want to do anymore.

Not everyone will succeed here, but everyone who makes an attempt will benefit from the effort. Don't let the odds get you down. Even if you never win the Turing Award, your continued growth as a programmer and your journey towards ultimate mastery depends on you constantly stretching - and, to that end, tackling hard, unsolved problems is the best way to stretch.

Congratulations! You are now a good programmer!Oh wait... actually, you just died of old age. Sorry. Better luck next life!

In all seriousness, though, don't expect to ever finish. The instant you stop making forward progress in your journey, you start to die, and become irrelevant. Some of the saddest failures I've seen in the world of programming stem from people who got a certain way down the path and decided they were done learning; to a man, they are now completely unimportant in the software world, and will likely never move beyond their current situation - unless, of course, they decide to start learning again.

Now, go forth, and code! Maybe someday when you're a great programmer, you can tell me how you did it.

U'r rigth dude, I've been coding for 10 years. I've seen from black screens to mobile programming, passing through visual object-oriented programming. You need to know databases, language fashion of the week (Anyone remember visual foxpro or delphi ? what's CORBA or SOCKETS ? and so on). A old saying says "Renew or die" I think i'm a older programmer but while i have some free time to learn new things i keep in the line. Regards

So, are you old enough to have actually completed the six steps and speak from personal knowledge? Or just speculating?

I've written maybe half a million lines of code, read millions and learned/used over 100 languages/dialects (mostly obsolete now, but including Lisp, Haskell, Prolog, SQL, XML, etc); truly mastered about 5; created/implemented 3 or 4. From this lofty viewpoint I have to say we part company around that point. I don't buy anything from step 5 on.

Write anything at all for other programmers to use and find valuable, and then support it and try to explain why it is the way it is. I've done that too.

There is nothing magic about knowing or learning stuff other people don't -- that's for academic papers. The magic lies in producing code that other people use and value, and the worth of a programmer is how many people use and value and are affected by the code you write. If you can write it and a thousand programmers value it and a million people use it, then you're a great programmer in my book.

I like the "bite the bullet"part. I am student and I have female peers that think just getting good grades at college will get them the job. They have no idea what is waiting for them . I have top grades too, all A's actually, but I don't give it importance. Coding everyday my projects is much more important.

Haskell, what an experience that was. I solved around 50 Euler problems in it. Boy was it a mind stretch at first, but it was worth it. I back you up on learning as much programming paradigms as possible, imperative, functional, oop, logic and so on... Assembly programming is good too.

Step five, I plan to start a simple language soon. Tried it once and failed, now I am better, I will be able to pull it off. Will be a cool project.

About step six, that is possible only if you are in Microsoft, Google or one of those. Doing it on your own is kinda hard I guess.

All of those are certainly valuable; I've done all of them at one point or another, and they certainly contributed to my skill set as a programmer.

However, my point about building your own language is not that it is merely a complex piece of software to write; my point is that it yields fundamental understanding of programming itself. Not every programmer works with databases or game engines or math libraries; every programmer works with programming languages. If there is one thing that any programmer can learn from, regardless of specialization, it's building a language.

Note that merely writing a compiler/interpreter/VM for someone else's language doesn't count - you have to design and implement something new. This is what provides the insights and opportunities for understanding. Building on someone else's design may teach you things about language implementation choices, but it won't teach you anything about design choices and how those affect the outcome of the language ecosystem itself. My argument isn't that there is nothing more valuable than writing a language for any given programmer; my argument is that all programmers stand to benefit from tackling this particular challenge.

There is nothing magic about knowing or learning stuff other people don't -- that's for academic papers. The magic lies in producing code that other people use and value, and the worth of a programmer is how many people use and value and are affected by the code you write. If you can write it and a thousand programmers value it and a million people use it, then you're a great programmer in my book.

I didn't intend for step six to be a blanket requirement per se; but anyone who succeeds at step six will be considered at least a damned good programmer, if not outright great. My point isn't that you have to do something novel to be "good" - my point is that to ensure that you are good, you have to be willing to venture into places that are foreign, scary, and unexplored. It's more about never stopping the learning process than about a mandatory milestone on the road to success.

Success will be defined differently for every individual programmer anyways; that's a personal decision and it isn't my intent to dictate to people how they measure their own progress towards what amounts to a subjective personal goal. I just want to encourage people to move beyond what is already known; far too many programmers are content to shrug off pioneering research as the territory of academia and ivory-tower theorists, when I personally feel that there is much fascinating discovery waiting to happen on the fringes of practical, applied software development.

I certainly wouldn't claim to know absolutely everything or hold a monopoly on valid perspectives on the issue, though; that was sort of the point of the article's conclusion.

I disagree that you can only do novel research at a major company (or even in an academic environment). Plenty of people do new, interesting things every day who are not at such locations. Startups often do this; many famous successful projects began that way.

I think it's self-defeating and ultimately a bit tragic to decide that one can't do anything cool and pioneering just because of where one works (or doesn't work).

I've worked as a programmer (in the sense that I get paid for it) for 26 years, but I've been a programmer since before I knew what the word was. When I first found the jargon file, I felt as though I'd found the elder scrolls of my long lost people.

Writing a new language, or at least a compiler/interpreter for an existing one, is extremely valuable, and I do recommend it. Creating a DBMS is also good. Any project like that goes as far as possible under the hood gives a person skills that spread across all other programming activities.

I would also recommend learning some sort of machine language or assembler. For most people there won't be any real practical application, but that's where all the work gets done, regardless of the language being used, and knowing what's happening down close to the bare metal has been enormously helpful to me.

I also find studying mathematics and physics (which I enjoy on their own merits) to be a great help in my programming. Learning the specific symbols and caveats that the author of a particular paper has used to create formulas for a human to read gives me great insight into to the algorithms people create for a computer to read.

Actually creating a new idea or learning what has never been learned may not be acheivable for everyone, but yearning for that goal is absolutely what sets the great programmers apart.

I am a programmer for around 4.5 years (Professionally anyhow, programming for approx. 12 years)
I've done most of these things myself and they are quiet valuable.

In my opinion there are 3 things missing from the list.

Communication - I know it's a bit cheesy but this is something that has to be kept in mind during ones professional development\career. Programming is not all about paradigms and technologies (which are completely awesome), it is also about cooperating with peers in a productive way.

Design theory - I am guessing it is implied that you're bound to run into this doing such diversified programming activities. Personally I have found a lot of merit in reading books that deal specifically with software design.

I love the article, working my way through step 4 with ventures back to 2 and 3 A LOT. In the pursuit of my B.S. I took a formal languages class, maybe I'll bust the book back out and see what I can do about step 5...

I like the article in general, the only exception is that I would suggest that step five be cut down to "create a domain language". Maybe 10+ years ago writing a language was a good idea, anymore it is a serious waste of time unless you focus on a specific problem. Given that you can name about 50 "script" languages and probably another 50 variations of full compiled languages available which could be used without much effort. Unless you have a real purpose for the language don't do it, it is more useful to learn to bind say Lua or Python into your code base than trying to write a generic script language from scratch.

As to domain languages, I write them quite often and they can be very useful. Say I want to script the input of a game to reproduce random inputs, a simple little domain language is a great way to deal with this. You don't have to get fancy with this but the effort leads directly to the items of learning needed. As you increase the abilities of the language, bad things usually happen trying to parse the extensions to the language and generally explain how we ended up with C++ complexity.

I was learning programming in the high school (actually we were the first generation in the school who learned informatics), then abandoned it to study politics and philosophy . After 8 or so years I'm engaged again into programming, unfortunately only as a hobby, but this give me so much motivation and engagement to pursue my current preoccupation and learn as much as possible. Now somehow i'm sorry that I gave up and not continued, and sometimes wondering if it's possible to bridge the gap? Opinions?

I have to second Nick's first point of communication though I'd like to build on this a little. As programmers, communication doesn't always come naturally. However, there are numerous tools available to facilitate communication without requiring the programmer to do anything more than they should be doing. What should a programmer be doing?

1) Commenting code!2) Using cource control and actually typing messages with each commit.3) Writing code that tests their code

We can probably go a lot further here but I'd like to keep it as brief as possible.

1) Commenting code!We need to communicate how our code works so that other programmers may find it easier to work with. Commenting does this but doesn't serve as a reference. Using a standard format for commenting allows documentation to be generated automatically with the build. Use DOxygen, JavaDoc, etc.

2) Using cource control and actually typing messages with each commit.We need to communicate that we are in fact working. Our higher-ups are rarely all technical people and, even for technical supervisors, we don't want them to have to look over our shoulder or, worse, "facilitate" meetings where we run down our list of work completed. Our commit messages may be scripted to send e-mails or, better yet, generate a log. Even better yet, there are online services that do just that, even providing ticketing systems to allow for a two-way conversation between employer/client and programmer. I use repositoryhosting.com (SVN) which provides Trac for ticketing and hooks-in to Basecamp (this further generates an RSS feed of all goings-on including commit messages from RH).

3) Writing code that tests their codeWe need to communicate that our code works but, more importantly, when our code is broken! If a change elsewhere in the software breaks our code, we should communicate that immediately. When writing modules, I typically write test applications for them. However, when I've completed the module, I move the test code from the application and place it into a static test() method. This function serves as a regression test that can be called during the build process. If something breaks, it usually sets a red flag right away.

...So, you're doing all of this anyway, aren't you? (If not, then BAD programmer!) Why not convert the common things you do as a programmer into communications to your team and employer? I'd say this would be the #7 step to being a good programmer, but the title is "Become a Good Programmer in Six Really Hard Steps". This isn't hard and therefore doesn't qualify.

@esimovIn my opinion it is very much possible, the real question is if you'll love programming or not.

<br><br>oh, definitely. As a matter of fact i'm trying to engage myself as much as possible into coding, but unfortunately only in my spare time i have the occasion to tinker with code. At my current job, where I'm a server configurator technician there were periods when I had a lot of time to read, learn and try, but at the moment the situation has changed a lot. Nevertheless I'm fully motivated and committed to code learning and want to pursue my goal. The ideal situation would be to have all the day at my disposal, because there are a lot of good books, sites out there, and I'm very convinced the development is inevitable. thanks<br>