I hear this question a lot, typically from kids who have just discovered that there’s more to a computer than a web browser, and who are curious about where to go for here. The people who ask this question typically don’t have any specific project in mind; if they did, it would be a lot easier to answer them. Instead, they’re really saying “I don’t know much about programming, but I think it might be kind of fun. Where’s the best place to start?”
An experienced programmer on a dark day might answer the question “What programming language should I learn?” with “None. Learn to play a musical instrument instead.” Today is not a dark day, however, and I’ll do my best to answer it.
The person I’m addressing this article to isn’t the person that has as their objective “I want to write a Windows application” or “I want to write a GUI for Bittorrent on Linux” or “I want to write a little tool that will run on my Mac to talk to iTunes.” The target of this article is someone who has a general desire to become a software developer but doesn’t yet understand how to get there.
So in that context, the high level, vaguely accurate answer to the question “What programming language should I learn?” is “It really doesn’t matter.” Partially this is because the question is ill-formed. The specific language one uses is mostly orthogonal to developing the skills one needs to be a good software developer. Let’s look at what those skills are, first, and then later we can come back to the question and make some actual recommendations, rather than just rejecting the question.
High-Level Skills
A developer needs to be able to describe a problem to be solved. She needs to be able to break the problem down into smaller, easier problems. She needs to be able to describe a set of conditions that constitute solving the problem. She needs to be able to think of tests that determine whether a given program or part of a program are correct.
Those are the sorts of skills every good developer has regardless of whether they’re writing code for themselves or for the marketplace. If a developer wants to work on a project with other people, be it open source or commercial, she needs additional skills. She needs to know how to find and read documentation. She will need to know how to use an Applications Programming Interface (API) that someone else has provided. She will need to be able to know when to use an already-existing API (“almost always”) versus developing a new API (“almost never”). She will need the discipline to not be constantly reinventing the wheel. She will need to know how to write documentation. She will need to understand what makes code maintainable (correct and adequate documentation, proper use of namespaces, consistent formatting, useful comments), and to actually use that knowledge when she writes code.
All of those skills apply no matter what your weapon of choice is in terms of language.
Classifying Languages
There are three rough categories of languages of interest to the modern programmer: imperative languages (sometimes you’ll hear these described as procedural) such as C, C++, Java, Pascal, and Modula-3. Imperative languages are about providing a sequence of commands for the computer to execute. In functional languages such as ML, Lisp, and Scheme programs aren’t so much executed as they are mathematically evaluated , as with the lambda calculus. And scripting languages such as Perl, Python, and Tcl which allow for rapid prototyping of simple tasks. Note: yes, I understand that there’s no academic reason to separate scripting languages from their imperative compiled brethren, but there are practical reasons which I’ll discuss later.
When programming almost any (modern, useful) language, you’re going to find yourself using a variety of directives. Some will be part of the core language specification: in C, integer arithmetic and assignment will be the same on every platform. Others will be part of a library that is likely to exist on any platform your program runs on (eg, stdio in C). Lastly, there are APIs which are platform-specific; a C library routine to open a dialogue box on a Win32 OS would be an example of this.
Specific Cross-Language Skills
Learning to program skillfully is something that comes only with great time and effort. There are plenty of programs that will compile just fine and run correctly that can still be called “bad programs,” in the sense that when you look at the source, it is clear that the author doesn’t have a grasp on some fundamental concept. The three little pigs built houses of straw, sticks, and brick. All of them served just fine as shelter, but only the brick house was strong enough to withstand the wolf. Your goal should be to not just learn how to make your programs run, but how to be confident in their correctness, robustness, and performance, before you’ve written a single line of code. To achieve that state, which may seem like a paradox, you need to understand the concepts underlying the craft of programming.
A shorter way of saying this is: don’t worry about learning the syntax of a language. Don’t concentrate on it. Don’t spend time worrying about it. Learning where the semicolons or parentheses go will come by itself, as you write code and go through compile-run-test cycles. Look that stuff up when you need to, but understand that “learning what a constructor in Java looks like” is, in the long term not a valuable thing to concentrate on. Learning what a constructor is and what it does is a valuable thing to concentrate on.
So that’s what you shouldn’t focus on: syntax. What should you focus on? Here, in a vague sort of didactic order, are concepts that I expect a skilled programmer to understand regardless of the language they are using — even if the language they are using at the moment doesn’t actually support the item in question.
- What a variable is.
- How variables are typed. Why type is important.
- Scope (Lexical, Dynamic).
- Assignment.
- Basic data structures.
- Basic control structures. Conditionals.
- Pointers.
- Dynamic storage allocation. Garbage collection. How to manage memory if your language doesn’t have GC.
- Linked lists. Hash tables. Btrees.
- Iteration. The off-by-one problem. How to avoid it.
- Recursion. When to use it. (“almost never”).
- Basic algorithms — sorting, searching, etc.
- Categorizing the run time of a piece of code (O(n), O(n^2), etc).
- Debugging techniques, from diagnostic prints to using a debugger.
- Assertions and how to use them properly.
- Basic object oriented programming concepts (inheritance, encapsulation).
- Threads. Typical concurrent programming mistakes, and how to avoid them. The producer/consumer problem.
- The difference between locking a mutex and waiting on a condition variable.
- Synchronous vs. asynchronous operations. Callbacks.
- Event-driven models.
- Exceptions. Strategies for handling errors generally.
- Advanced testing strategies. Fault injection.
Any one programming language you choose, unless you’re really going out of your way to be obscure (e.g. Prolog), should get you through at least half of that list. Then you can decide whether to stick with the language you started with for the rest of the list, or start on a new one to fill in the gaps.
Practical Considerations
Programming is fundamentally a “learn by doing” activity, so your language choices are somewhat constrained by the need to use a language that can actually run on your operating system of choice. This still leaves you with a fairly wide set of options.
Language availability isn’t the only practical consideration. If applicable, is there a debugger for the language you want to use? What set of libraries will you be using? How much documentation is available for the language you want to learn? Is there an active community you can turn to for help?
Enough Already. Just Tell Me What to Learn!
OK. I’ve tried to make the point here that whatever languages you decide to learn, you should be able to develop your skills over a period of years such that when you decide to learn a new language, it will just be a trivial matter of absorbing the new language’s syntax. However, in the interests perhaps of sparking debate, I’ll give my own personal opinion on teaching languages. Nothing in this section should be construed to mean that I’m saying that languages other than the ones I’m recommending aren’t any good (except Modula-3. Modula-3 isn’t any good. I’m saying that.)
First, learn a compiled imperative language. I very much like Java as a teaching language. I have a few reasons for liking Java. In addition to being somewhat cross-platform (cue mocking laughter), it is actually a fairly elegant language with a robust, extensive, powerful and most importantly for the novice, well-documented set of APIs. One of the things I like about Java as a teaching language is that it’s always very clear, because of the namespace design, when you’re using a “built in” command versus when you are calling some library API; I’ve seen novices using C and C++ get confused when the distinction wasn’t as clear to them. There are many resources to help the novice Java programmer get off the ground. A student learning Java can learn about Object Oriented programming concepts, threads, events, dynamic allocation and garbage collection, advanced data structures, and most of the items on my list above. The fact that Java runs in a virtual machine is both a benefit and a drawback — it will probably slow your development of understanding how these high level data structures map to the architecture of the machine you’re on, but you can always go back and learn C later. Also, the syntax of Java is simple enough that it won’t pollute you or ruin you for other languages (the way, say, Objective C would).
And in the interests of disclosing any bias on my part: I don’t program in Java on a day to day basis. My day job is all C, all the time.
Next, learn a functional language. Lately I’ve been toying around with OCaml and ML, and I like them, but really its hard to go wrong here. Lisp, Scheme, ML — these are all fine choices. I haven’t examined it yet myself, but I’ve been told that Microsoft Research has a neat language called F# which is basically a version of OCaml that can call .NET library functions. That’s pretty tempting, because it has such an aura of the forbidden about it — take a pristine, educational, not-very-useful-in-practice language and turn it into something that can be used to develop Windows applications. Mmmmmmmmmmmmm, forbidden transgressive language.
Uh, what? What was I saying? Um, yeah, F#. Very bad. Don’t use that! It’s morally wrong. Learn Standard ML. Yeah.
Lastly, learn an interpreted scripting language of some sort. I like Perl, but Python has a big following, too. People will tell you that scripting languages are just as powerful as compiled languages. They’re right. But it’s been my personal experience that because of the environment scripting languages grow up in (“Oh my gosh, I have to change all occurrences of this string in every file on the server within 10 minutes, or I’ll be fired“) the idioms in common usage aren’t as carefully thought out. Shortcuts are taken. Error cases are punted. Sloppiness is rampant. I agree fully that this is more of a cultural matter than anything intrinsic to the design of a language, but I can’t ignore the reality, and that’s how I see it.
If you’re an experienced developer and you’d like to chime on this topic, please feel free to comment below. The only thing I ask is that you keep in mind that the topic is languages for learning the craft of programming, not languages for best accomplishing a specific task. Thanks.
Additional Resources
- The article that inspired me to write this when I came across it: Peter Norvig’s Teach Yourself Programming in Ten Years.
- I recently wrote an article on why we use pointers. You might like it.
- My favorite Java book is Peter van der Linden’s Just Java.
- Microsoft Research’s F# project.
- Wikipedia entry for the lambda calculus, the formal system behind functional languages.
- In the interests of balance, the author of CVSup explains why Modula-3 is great. (But he’s wrong).
- The Skeptic’s Guide to Objective C.
wrong question. the question is not which programming language to learn, but “how shall I learn programming?”
if English is not your native language, you should first, before ever seeing a computer, learn English to a level where reading novels is no problem.
the language of choice for learning programming is Common Lisp. once having learned programming, you can teach yourself any language you want.
Personally, I think Java is too C-like, with all the negatives that go along with that. If you’re wanting something for your resume, it’s the best choice, but if you’re wanting to learn programming…
I’d recommend Python instead. It can be used interactively. It is fully object-oriented, but does not require you to use OO techniques. (It also has functional capabilities that you can use or not.) It has a clear syntax that is not cryptic, but isn’t overly-wordy either.
It runs on every platform and it’s bundled with MacOS X (which I use).
Last, I like Python’s culture, which is practical and helpful. And that’s a key. Perl’s culture is to be everything to everyone who will do it in a different way. This has led over the years to a kludgy, cryptic language whose devotes (I used to be one) love to do things in odd ways. Ruby has a culture that is rigidly small-talkish and insists on a OO purity that isn’t always appropriate. Python gets it just right. At least for me.
Look at the slogans that the language’s users and leaders use. Python’s is “Batteries included”. Perl’s is “Everything to everyone.”
Dammit. No mention of PHP.
Now what’m I going to do with these books I’ve bought?
I’m no programmer, unless HTML is a language (snort, giggle), so I’d like to know where PHP fits into all of this.
won
Won,
I personally consider PHP to be a perl-like scripting language that is executed in a webserver context. That is not to denigrate it or say it’s not a useful or powerful tool, but it’s probably not what I’d recommend to someone interested in learning programming as a craft.
-Peter
Peter, I am interesting in having this article mirrored on my site. Please contact me if you are interested. idg@mxi.netwave.or.jp
p.s. Thanks for mentioning Modula-3
C, C++, Java, Assembly, BASIC, etc.
It doesn’t really matter which language you start with. In reality every new programmer should start with Analysis and Design (logic) for the problem they are trying to solve. Once a programmer (he or she) has defined the problem, only then can it be solved by programming. This is why so many programmers fail, they start from the top down instead of drawing the blueprint first. As a software engineer and home builder, every day I am reminded how planning can save effort, time and money at a later date.
I’m curious as to why you recommend learning a functional language before a scripting language? I suspect scripting languages are vastly more useful, and much less of a pain to learn. Also, from a community standpoint, who are you going to talk about the functional language with and get help?
Does java have a console interface? Forcing students to learn such a confusing architecture like java (events, and all that inheritence, I mean) would be awful.
A scripting language seems like the place to start, because it’s forgiving and better designed for quick problem solving (as opposed to efficient maybe), which gives newbies a better environment to learn to think about how they’ll solve the problem, not why they are segfaulting. Eg. Some of my peers early in college just never got “it,” and couldn’t solve the simplest of problems – I’m not saying C++ was the whole problem for them, but a simpler language might have helped frusterate less and afford them more time to figure out the logic required of them. After a scripting language the newbie can study pointers, linked lists, and more complicated stuff with any language they want (probably something popular and useful like C++/Java).
I like perl and C++ myself. However, I’m finding the perl syntax for classes to be a little strange.
I don’t agree with Rolf on learning english. A second language is hard! One only needs to understand the alphabet and pronunciation, since I expect there are many resources for programming in most popular natural languages (but Japanese especially).
I think learning a functional language really helps you develop the mindset necessary to become a good programmer. I wrote my first programs in Logo, starting at age 6 on a simple home computer. For those of you who don’t know it: Logo is a language targeted at children, but interestingly, it is (at least partly, depending on the implementation) a functional language. Having mastered Logo, I started learning BASIC, since it was the only language available at the time on my MSX home computer.
BASIC was horrible. Inelegant, messy programs, with unclear structures. I still hate it today, and loathe Visual Basic. I keep as far away of it as I can
When we got our first PC, I started learning Pascal. At the time, that was a very useful language for learning proper imperative programming. I can still recommend it, although, just as Modula-2 and Modula-3 it is no longer mainstream enough to be used in any serious work. One could also take a look at Delphi, although I’m not too fond of that.
Java is an excellent choice at this time and place, although I’m in doubt whether you want to dump the full weight of OO on a learning programmer.
Personally, I like Java best for its clean, well defined architecture. But for a living, I mostly write C and C++. Where power of expression is concerned, I like C++ best, but would never ever recommend it to a learning programmer.
Finally: if you’re interested in functional languages, take a look at Miranda (or it’s free cousin Amanda).
Matt,
You’ll note that “useful” and “easy to learn” weren’t actually criteria that I was applying.
Learning the craft of programming is a marathon, not a sprint. In my experience, most scripting languages are indeed useful and easy to learn, and if they are the first exposure a new programmer has will teach her bad habits that may take years to unlearn.
Functional languages also encourage developers to abstract data in powerful ways that scripting language, by their very “get it done NOW” nature, don’t.
Anyone who learns a functional language first will have no trouble learning any scripting language there is. Some people who learn scripting languages first -may- have a harder time going to a functional language.
I had to spend years unlearning the damage done to me by Applesoft basic. Somewhere out there today is someone who someday will be a great programmer, after he unlearns his Tcl.
Good article.
I would say that from my point of view, having gone through this over the past 6+ years, that scripting languages are a good place to start.
My reasoning is slightly different. Scripting languages are fast. You see results of your effort in near immediacy. And they are fun. Including these added enjoyment incentives early in the process of learning to become a developer was a boon.
Then the neophyte can travel down the well, to interpretted languages such as Java or C# and finally (if they choose too) move on to C++ or even C.
Like you say this whole process is a marathon, not a sprint. I agree that bad habits can be learned if scripting languages are your first exposure, but I would argue that is part of the learning process (at least for a self taught programmer). They will need to be unlearned, but even that process can help in understanding the why’s and wherefors.
My last point and really one of the most important is READ. Read, read, read. And when you’ve finished the latest book on structure, pick up the next on design patterns, and when you finished that, pick up one on extreme programming, after that, how about one on hardware or compilers. And when you finish those ask your freinds what books they recomend.
Two great books that really helped me along the way:
Code Complete – McConnel
The Object-Oriented Thought Process – Matt Weisfeld, Bill McCarty
I started with Lexico. It’s very simple object-oriented language to newbies. The codes are in spanish and others idioms by the way “synonymous”.
A few years ago I started learning Visual Basic, solely by available online resources. I learned enough of it to make a good amount of programs, properly read syntax, find errors, etc. My problem was I didn’t and honestly still don’t know what most of the keywords meant. I don’t really know what constructors do, or how Windows API _really_ works.
After that I started picking up some perl for quick and dirty scrips. As with Visual Basic I just learned how to write a script, but not understanding how it’s working.
I find this troubling because I fully support Open-Source, but see problems if I continue with this mindset. One obvious problem is I would just be definitely be re-inventing the wheel as without a proper in depth understanding of the underlying components, I’m stifled not in my creativity but actually applying it.
Anyway I’m at a point where I want to start from scratch, and if I don’t understand something, instead of skipping it, I’ll ask someone(pride’s a doozy). I want to ultimately create powerful applications that could be used on multiple platforms, database-driven, maybe even support some low-level type of enterprise base.
With this, what would you suggest. I really _want_ to learn C#, but I’m worried about it’s limits. The code that I’d read is almost somewhat intuitive. It’s also very secure from what I read about exception handling and garbage collection. What does everyone think, and what would be the pros and cons on learning C# as my primary language?
Thanks
JP
I’ve been teaching programming for over fifteen years and I still prefer Pascal – or now Delphi. It develops good habits, is readable and easy to debug. Now it’s OOP it’s a great platform for moving on to other languages like C++. Also Delphi is good at interacting with databases. I also tell my students that I am teaching them programming not a programming language. They need to be prepared to move on.
Useful article. The learning programming versus learning a programming language differentiation is spot on. But everybody wants the shortcut these days. Java in 24 hours/C# for Dummies.
Just about any endeavour that is worth achieving a degree of competency in requires discipline, work and structured learning. Be it golf, playing the piano or writing poetry – there are skills to acquire and perfect (through practice). Bad habits, learned early on are an impediment to the long-term goal.
GB
gbyrne D0t xit on google mail
Give them Visual Basic. They can drag a couple of controls onto the form and write some inconsistent code without having even thought about the real problem. No, serious, I think ANSII C++ is good for the beginning so they can concentrate on the true problem-solving part that so many Visual Babytalk wanna-be’s never get under the belt.
This has become even more evident with .NET; they have 10 years of experience and in .NET, most of them are still at beginning level – four years after .NET was launched. Books on this technology are so shallow that if .NET were an ocean, you could cross it without getting your knees wet. They simply don’t get OOP because they’re worried about where to drag that handy-dandy control. VB .NET code is much too often plagued by inefficiency because the guy behind the keyboard didn’t get the changes. How many of them still code the way they did in previous version? Almost all of them. Oh, yes, and using the VisualBasic namespace is another thing they shouldn’t do – but who cares? It’s fast, and the guy won’t even care whether code is good or not.
Learning Java? Why not? It’s another dead programming language that nobody will pick up in a couple of years. It’s the same thing I said about COBOL, and everybody laughed at me at that time. Now, does anybody still program in COBOL? Yes, a handful of dinosaurs still do.
As RobC said, it doesn’t really matter which language you start with. What does matter is the thinking behind all this. They’re supposed to solve problems, so it’s about time they understood this. And if PHP solves a problem, won, then by all means use it. It needs different abilities than making applications, but it fits the needs, right? And when I see truly well-written code, I actually don’t care what language it was written in. Recently, some people from VB have understood that, but this is a minority. I would wish they could slow down and think for a moment or two, but I have reason to doubt that this will ever happen.