Lots of people (particularly people associated with LessWrong) are telling me I should become a computer programmer; in response I've taught myself a little Python using this site, written a couple Python scripts on my own, and just now sent in an application to App Academy. But if I don't end up going to App Academy, what's the best way to develop some actually marketable programming skills? I've heard people recommending getting involved in open source projects on Git Hub, but when I looked at Git Hub I found it overwhelming, with no idea of how to find a suitable project to work on. Advice?

New Comment
69 comments, sorted by Click to highlight new comments since:
[-]shev620

I strongly disagree with the approaches usually recommended online, which involve some mixture of sites like CodeAcademy and looking into open source projects and lots of other hard-to-motivate things. Maybe my brain works differently, but those never appealed to me. I can't do book learning and I can't make myself up and dedicate to something I'm not drawn to already. If you're similar, try this instead:

  1. Pick a thing that you have no idea how to make.
  2. Try to make it.

Now, when I say "try"... new programmers often envision just sitting down and writing, but when they try it they realize they have no idea how to do anything. Their mistake is that, actually, sitting down and knowing what to do is just not what coding is like. I always surprise people who are learning to code with this fact: when I'm writing code in any language other than my main ones (Java, mostly..), I google something approximately once every two minutes. I spend most of my time searching for how to do even the most basic things. When it's time to actually make something work, it's usually just a few minutes of coding after much more time spent learning.

You should try to make the "minimum viable product" of whatever you want to make first.

If it's a game, get a screen showing - try to do it in less than an hour. Don't get sidetracked by anything else; get the screen up. Then get a character moving with arrow keys. Don't touch anything until you have a baseline you can iterate on, because every change you make should be immediately reflected in the product. Until you can see quick results from your hard work you're not going to get sucked in.

If it's a website or a product, get the server running in less than an hour. Pick a framework and a platform and go - don't get caught on the details. Setting up websites is secretly easy (python -m SimpleHTTPServer !) but if you've never done it you won't know that. If you need one set up a database right after. Get started quickly. It's possible with almost every architecture if you just search for cheat sheets and quick-start guides and stuff. You can fix your mistakes later, or start again if something goes wrong.

If you do something tedious, automate it. I have a shell script that copies some Javascript libraries and Html/JS templates into a new Dropbox folder and starts a server running there so I can go from naming my project to having an iterable prototype with some common elements I always reuse in less than five minutes. That gets me off the ground much faster and in less than 50 lines of script.

If you like algorithms or math or whatever, sure, do Project Euler or join TopCoder - those are fun. The competition will inspire some people to be fantastic at coding, which is great. I never got sucked in for some reason, even though I'm really competitive.

If you use open source stuff, sure, take a look at that. I'm only motivated to fix things that I find lacking in tools that I use, which in practice has never lead to my contributing to open source. Rather I find myself making clones of closed software so I can add features to it..

Oh, and start using Git early on. It's pretty great. Github is neat too and it basically acts as a resume if you go into programming, which is neat. But remember - setting it up is secretly easy, even if you have no idea what you're doing. Somehow things you don't understand are off-putting until you look back and realize how simple they were.

Hmm, that's all that comes to mind for now. Hope it helps.

  1. Pick a thing that you have no idea how to make.
  2. Try to make it.

I second this whole post, but especially that part.

I would add one more bit: It helps a lot to have a friend who's already a programmer. Not so you can say "teach me how to program", but so you have someone to go to when you don't know what words or phrases you need to Google. IRC channels or newsgroups relevant to the language/library/application you're using can substitute for that but aren't quite as helpful.

[-][anonymous]20

If you do something tedious, automate it.

I work in programming, and I agree with just about everything you said and I want to put my biggest, boldest circle of agreement around this. I don't think I started getting into what seems like a more advanced style of programming knowledge until I received a large enough stack of tedium that I had to automate through.

The other key step was realizing something was tedious. If you've only worked on a few things related to a system, then everything seems novel, but if you do the same type of thing over and over again, you'll frequently see a tedious pattern and then you can automate THAT tedium.

[-][anonymous]90

A word of caution: It is possible to get so caught up in automating and other meta-work that you lose focus on the object-level goal. I know this because I've done it.

"Oh, I could probably automate this with a script...you know, I should really optimize my vim setup for script-hacking...you know, I really need a way to keep track of my vim plugins...I could probably tweak these plugins to work better with what I'm used to..."

A lot of these time investments end up paying off (e.g. you really should use vundle to manage your vim plugins), but every now and then you should push through at least a bit of tedium to make sure you have a good idea of the problem, how much pain it's causing you, the scope of similar-enough problems which are likely to have the same solution, and exactly what you need to do to solve it.

A word of caution: It is possible to get so caught up in automating and other meta-work that you lose focus on the object-level goal. I know this because I've done it.

It depends what you want to learn. If you want to learn programming then spending time on automating stuff is useful practice.

The LessWrong site is written in Python, is available on GitHub, comes (*) with a fully configured VM image to avoid the pain of setting up a functional system, and has some outstanding feature requests. This might be an excellent way to hone your newly acquired skills, since you have easy access to a community of users (in fact you're one yourself).

(*) Came, as of eighteen months ago - it's possible that "bit rot" will have happened meanwhile.

I am not a Python programmer, so I would like to ask those who are... how difficult it really is to understand the LessWrong code and do some modifications? Okay, I know it depends on the kind of modification, but let's suppose I just want to understand how the existing system works, and by "understand" I mean: know what happens in which function and why.

My guess (but I am not a Python programmer, I just guess based on reactions of other people) is that LessWrong code is rather complicated, and can scare away even people fluent in Python.

And if that guess is correct, telling a beginner to look at the LessWrong code seems like a bad idea.

Frankly, I don't know. Yes, the LW codebase is pretty complicated. It's probably fairly typical of real-world programs of the same size and functionality.

As a beginner programmer, I got started not by working on simple, small or "toy" programs but by diving head-first into gnarly complicated codebases and doing very simple things to them.

This served me well as a learning path, but I'm wary of generalizing to anyone else's experience.

On the other hand, "a bad idea" strikes me as strong language. If you're brave enough to attempt to learn to code on your own, getting stuck while attempting to tame a complex codebase shouldn't be a traumatizing experience. What's the worst that can happen? That you quit and set your sights on something simpler.

Experience helps a lot in reading something like the LW codebase. If you have an idea of how Web frameworks tend to organize behavior, you won't be too surprised by where things are and navigation will be relatively easy. If everything looks new to you, you'll be getting lost quite a bit.

But in learning your way around Web programming there's no substitute for getting lost. Any other Web framework is going to confuse you to some extent, and any app built on top if it.

My main idea with this recommendation was that at least you wouldn't have to build up a mental model of what the application is for, whose needs it serves and how those people experience it, since we all already have this model in place from a user's perspective.

[-]kalium130

Check out OpenHatch if you're interested in getting into open-source development. They've put together a directory of open-source projects needing bug fixes or other contributions, organized by difficulty and language. They also run several workshops and have a helpful and friendly IRC channel (#openhatch on Freenode).

[-]Shmi130

You said that people told you that you "should" become a computer programmer. But it only makes sense if you enjoy programming 8+ hours a day (and have aptitude for it). Did you have fun learning Python or was it a chore?

Do most people enjoy their jobs?

[-]gjm170

Wrong question, I think. Chris isn't "most people" (no one is) and what matters is the available tradeoff of enjoyment, money, social value, etc., in the jobs he might take.

My impression is that most people who are in a position to make a decent career out of software are able to find jobs they enjoy pretty well. Not necessarily jobs in software -- they might like something else better. Chris might still choose to take a job he doesn't enjoy (e.g., if it pays much better) but he probably has the option, even if it turns out that "most people" don't enjoy their jobs.

I agree.

[-]Shmi60

You may end up not liking the grind, but the least you can do when choosing a career is to make sure you like as many parts of the job as possible as much as possible.

I don't know, do most people enjoy their jobs? (Where "job" = "whatever people are paying you a living to do".) Do most people of an LW-ish sort enjoy their jobs? Do you? Or is it a grind that you do for no reason but to pay the bills?

Do you?

Not recently. Honestly, though, I'm not sure typical programming work is the sort that people who think they like programming enjoy... think writing glue code and tracking down other people's bugs.

Or is it a grind that you do for no reason but to pay the bills?

I decided a while ago that I'm an extrinsically motivated person and trying to figure out "what I loved" wasn't going to be a good strategy for me. My impression is that careers like doctor, lawyer, and banker are typically pursued by extrinsically motivated people who aren't actually passionate about doctoring/lawyering/banking.

Cal Newport wrote a book called So Good They Can't Ignore You: Why Skills Trump Passion in the Quest for Work You Love. 80,000 hours has a summary on their blog: 1, 2. Other blog posts.

Why do "typical programming work" then? Do more interesting programming work. Have you spent significant time trying to find a programming job you'd like more?

I used to do "writing glue code and tracking down other people's bugs" type work, as well as building new features (in a system I already knew well, not learning much) based entirely on someone else's designs and priorities.

I changed jobs in January and the new one's much more challenging and fun. I have creative input, leadership opportunities, and mostly do my own tasking, working on whatever I think is important or interesting. I also have more variety in tasks, which I enjoy. I probably only spend about half my day coding now and spend the other time project planning, learning new stuff, designing and architecting new features, or doing other non-coding tasks. The new job also pays better :)

I'm a lot happier, and I feel like I'm actually learning and improving, whereas I was kind of stagnant before. The good programming jobs ARE out there, and IMO it's worth trying to get them.

How much do you enjoy your job?

[pollid:471]

Oh, yup, Python has been fun so far.

Personally, I find it a chore to learn programming languages, but I find it very enjoyable and rewarding to write software which helps solve problems I'm interested in.

programming 8+ hours a day

From both my experience and what little research I've done on this topic, programmers do not program 8+ hours per day.

Do you have any more information on this?

My personal experience has been that it's almost impossible to consistently put in more than about 2 hours/day of highly focused 'flow' coding. I was previously worried that there was something wrong, but at this pace I'm able to complete big projects on a regular basis. Could this be normal even for productive programmers?

I have heard a lot of people say that around 3-4 hours is typical. (That is also the average for professional writers, so it makes sense for that to generalize to other kinds of creative work.)

[-]Shmi10

2 hours a day seems low, but you might be unusually effective. My experience is that the duty cycle is closer to 50/50, and lower with overtime, the latter being common, especially in startups.

The only way I can get actual 8 hours of focused programming work is if it's the sort of tweaker monkey work where I just try a whole bunch of combinations trying to achieve the thing I've already figured I want to do. Examples of this are long debugging sessions, writing FFI bindings and writing an assembly subroutine. If I actually need to keep figuring stuff out, 2 to 4 hours is generally the amount I can manage.

Probably belongs in the latest Open Thread.

Depends on what you're interested in. If you're a mathematician, Project Euler is a collection of recreational mathematical problems that need to be solved with programming (some can be solved with pen-and-paper in a reasonable amount of time, but the majority require the processing power of modern PCs) - in other words, a good way to learn to re-phrase mathematical thinking in terms of the programming language you're trying to learn.

Consider taking some of your routine computer activities (batch photo manipulation, organising files, filtering email, etc) and automating them. Python is a great language for that, it can easily interface with system shells on just about any OS and has a ton of well-supported libraries for just about everything. Yes, you'll be reinventing inferior solutions to problems that have been solved long ago, but the point is to learn.

I've gone and done 20 problems on Project Euler, and learned a little, but it didn't seem like the fastest way to learn. Some of the problems took me awhile, but mostly they could be done with things I already knew. There was just one that I had to resort to Googling how to do, which led to learning a bit more about Python's max command. But maybe I should take most of Project Euler seeming relatively easy as encouragement?

But maybe I should take most of Project Euler seeming relatively easy as encouragement?

If you did 20 problems at random, certainly. If you started from the beginning, all I can say is keep going. A good way to judge difficulty is to sort the problems in descending order of the number of people who solved them.

Learn math too, to understand data structures, graphs, algoritms and all the basic CS stuff.

A fun way to explore more advanced features of Python is the Python Challenge. It's a series of online riddles that you're encouraged to solve using various features of Python.

Thank you for pointing me to this!
I just picked Python up for the first time at the weekend because this looked fun. 6 questions down so far and feeling smug out of all proportion to the accomplishment :)

[-][anonymous]30

Go to Kaggle and enter a data competition. It is super, super easy to start (usually you just have to submit a solution which is a bunch of 1's and 0's) but to win, or even increase your rank, requires learning of real, practical data skills. I believe some companies even do recruiting through kaggle competitions.

If you go this route, download the scipy superpack which includes scikit-learn. You can spend five minutes reading about e.g., Naive Bayes classifiers, and then five minutes later you can be checking out how it works on your data!

Chris, if your goal is to get a job, it may help to think about what an employer wants to see when to make you an offer for a good first job.

Don't let this distract you from the joy of learning, or from learning material that is not directly relevant, but it may provide a motivator. In the end, you'll be providing value to someone, so you may as well start thinking of it now.

Why not choose an open-source project that is well-known, and which has been historically open to accepting patches. Then find some bug that you can fix. There are tools to help you find all this. Then submit a patch, and you can honestly say that you contributed to the famous project.

You're talking about Linux, right? This is a serious question; cryptic doesn't work well with newbies.

[-]maia50

Not necessarily. There exists more than one famous open source project.

I'm not very familiar with contributing to open source but Linux is written in C and from what I've heard the standards are pretty high. Probably you'd rather be looking at a smaller open-source Python project. But really, shev's post seems like the most practical advice.

I believe JoshuaFox wasn't talking about any specific project, just suggesting that you find one.

If you want to contribute to an open source project, I recommend you look at the most-watched python projects on github.

Pick one that looks interesting to you (ideally one you're already a user of, but it doesn't need to be) and download the source code. Most should have a README file that explains how to actually run the code (which sometimes involves installing dependencies, editing some config files, etc.). If the README is any good, it should have line-by-line instructions of what to type into the command line. If you can't get it working, either ask for help or try a different project.

Once you've got the code running, take a look at the source code. It will be impossible to understand everything immediately, but try to get a very basic idea of how it works. Try editing what's displayed somewhere or adding "print" statements to make sure you have some idea of what's going on.

Then, take a look at the "issues" page of the github project. This will have lots of reported bugs and feature requests. Pick one of the bugs, and make sure that you can replicate it (i.e. make the bug happen for you -- this doesn't involve writing or editing any code, just running the program). If you can, try to track it down and fix it (this means editing code).

Once you fix a bug, make a github account and learn the basics of git and how to submit pull requests (github has pretty good tutorials). If you can't figure this part out (it's a little tricky at first), ask for help on stackoverflow, the project's IRC channel, LW, or from someone you know). Some would suggest you learn git before downloading the project or fixing the bug, but I think it's better for you to start working on the projects asap rather than trying to learn git immediately.

RIght, like maia said. There are plenty of well-known projects in every language. Here's one tool to help find a project and there are other tools as well.

Why not choose an open-source project that is well-known, and which has been historically open to accepting patches.

How do you know as someone who never participated in an open source project whether a particular open source project is historically open to accepting patches?

  1. Here is a recent article with statistics on openness to accepting pull requests in various projects.

  2. An article on ways to contribute if you're not yet ready to contribute large amounts of OS code: Bug reports, bug fixes, documentation, etc.

  3. At Ohloh, you can browse data on lots of projects and get a feel for how active each one is.

  4. CodeHatch is designed specifically to get volunteers on-board OS projects.

[I]f your goal is to get a job, it may help to think about what an employer wants to see...to make you an offer for a good first job.

It seems to me that part of the purpose of the post is to ask what this might be.

It seems to me that part of the purpose of the post is to ask what this might be.

Until I get the chance to write an essay on what employers want to see, I'd say:

Coding well is essential, but employers want to figure out who has a professional attitude towards the job. Contributing to OS shows that you are willing to take on aspects of software development beyond coding up an application: Testing (for bugs, performance, etc.), bug-tracking, documentation, and more.

I've recently been looking into the Python Natural Language Toolkit, and thinking the book would make a good set of exercises for the linguistically-minded aspiring Pythonista.

  1. Learn a framework for developing web applications. Specifically, learn Django.

    This is because most new applications are web applications, and because you can write a satisfying application without knowing much. Also, you get immediate feedback on your code -- you can see whether or not the app is coming out the way you want.

    Django is recommended because (a) it is written in Python, (b) it is relatively popular, and (c) it is similar to Rails, which is very, very popular and thus easy to get hired for.

  2. (in parallel with 1) Decide on an application that you want to write, and write it. Put the code on Github or Gitorious or Bitbucket (as you go -- not just once you finish).

  3. If you are exited about getting involved in free and open source software, it's usually best to work on a project that you actually use. That way, you at least understand some of how users expect the program to work. Unfortunately, the programs that you use are likely to be the ones used by zillions of other people, so much of the low-hanging fruit will be already plucked. But maybe you have a more obscure interest which involves software? For instance, I have added features to electronics schematic software, vector graphics software, an interactive fiction virtual machine, a search engine, and a bunch of other random stuff. If you don't see a feature you want to add or a bug you want to fix, just take a look on the bug tracker and see if anything catches your eye. Don't worry if you can't fix any given bug; if it were easy, someone would have done it already!

This is because most new applications are web applications

Or smartphone/tablet apps? Many of which are just web apps reskinned for a phone, but there's a lot that aren't. But I don't know the industry enough to say which is bigger these days, in terms of either developer jobs, or new ideas waiting to be plucked from the tree of knowledge.

I'm a mobile & web & backend developer & startup founder, and I will strongly claim that mobile is the future and that web apps are dying. Backends are still ridiculously useful, but they're much more in the form of an API.

My recommendation to the OP would be to learn another language, and make that language Objective-C or Java (depending on what kind of smartphone s/he has), and practice building apps with Python backends.

That's totally a big area, yes. And if it's what excites Chris, then he should totally go for it. But it isn't my first recommendation, because most mobile apps are written in Objective C or Java, while Chris has learned Python. There's a fairly large amount of new stuff that one has to learn to transition from Python to a statically typed language, so it's not the most efficient path to a working app.

(It doesn't feel that different if you have been programming for a while, especially if you learned a statically-typed language first, but you've probably forgotten about having to learn about covariance/contravariance/invariance, or about memory allocation, or about type-casting).

After short googling, perhaps this could be interesting: http://kivy.org/ An open-source Python library for making programs that run also on Android and iOS.

[-][anonymous]00
[This comment is no longer endorsed by its author]Reply

Oh, and one more thing: Consider taking the Algorithms and Data Structures class on Coursera. It will make you a better programmer, and help you with job interviews. When I am interviewing programmers, I always ask candidates to name any algorithm or data structure and tell me how it works.

I'm in a similar boat; also starting with Python. Python is intuitive and flexible, which makes it easy to learn but also, in a sense easy to avoid understating how a language actually works. In addition I'm now learning Java and OCaml.

Java isn't a pretty language but it's widely used and a relatively easy transition from Python. But it, I find, makes the philosophy behind object oriented programing much more explicit; forcing the developer to create objects from scratch even to accomplish basic tasks.

OCaml is useful because of the level of discipline it imposes on the programer, e.g. not being able to mix an integer with a floating point, or even--strictly speaking--being able to convert one to another. It forces one to get it right the first time, contra Python's more anything goes, fix it in debugging approach. It also has features like lazy evaluation and function programing, not supported at all in the case of the former (as far as I know) and as a kind of add on in the case of the latter, by Python. Even if you never need or want these features experience with them goes some way to really understating what programs are fundamentally.

Java is primarily useful for huge things. Since it makes so many things explicit, you can orient yourself very quickly in a project. If you see a symbol, you don't need to pull out a special tool (like cscope for C) to tell where it was defined - the code tells you. Yes, it is possible to write spaghetti Java, but it's easy not to.

Also, if you have something that will be on for a long time and need it to eventually act with compiled speed (e.g. a webapp), java with the JIT is soon as fast as an always-compiled language.

The inability to pass functions as arguments without creating a class for them is one of the annoying parts. Maybe some syntactic sugar will be (or recently has been?) added.

The inability to pass functions as arguments without creating a class for them is one of the annoying parts. Maybe some syntactic sugar will be (or recently has been?) added.

Java 8 (currently scheduled for March 2014) is adding proper lambdas.

There are other JVM-based languages that do have more easily accessible functions, but most of them come at a performance cost - the JVM really isn't very flexible.

To the best of my knowledge, no-one has tried to design a language that gets the best possible performance from the JVM while still throwing away C-style syntax and unnecessary limitations.

What I'm talking about here would still compile to Java bytecode. It would just be some syntactic sugar to easily wrap static functions in anonymous classes.

Sure, that's what I was talking about.

Though Java syntax really isn't that great, and if you're changing it at all, there's a lot more low-hanging fruit than just functions.

The only thing that really bugs me is the inability to use variables declared in a try block in an ensuing catch or finally block. That would let you scope things much better.

What are you thinking of?

Lack of multi-parameter polymorphism, lack of return-type polymorphism, lack of algebraic data types, lack of parametric polymorphism, etc.

Okay, essentially I want Java to be Haskell. That's an impossibility, but most of the type-level stuff needs no runtime support whatsoever.

You can do polymorphism with generic types, and that's been around for a while.

Like,

List listOfThings = new ArrayList(); listOfThings.add(new Thing()); Thing t = listOfThings.get(0);

Is this not what you're talking about? Generics need no runtime support, but they do enable a lot of compile-time checks.

Generics certainly don't do parametric polymorphism or algebraic data types. Of course anyone can write a Pair or Triple class with trivial get and set methods, but that looks (and acts) silly.

Ooh, another thing I'd love is to have there be a Bracketable interface that lets you use brackets to call the class's get and set methods. Then you could access Lists and even Maps with array syntax. It'd be sweet.

All three of the things I asked for in this chain now exist as part of Java -

-- Lambdas - code snippets you can pass (without even declaring them as functions, even!),

-- brackets for accessing Lists and Maps, and

-- a way to declare variables for both a try and its associated catch and finally blocks.

I'm kinda floored.

OCaml is my favorite language. At some point you should also learn Prolog and Haskell to have a well-rounded education.

At some point you should also learn Prolog and Haskell to have a well-rounded education.

I'm not sure knowing Prolog is actually useful, and I speak as someone who has been teaching Prolog as part of an undergraduate AI course for the last few years, and who learned it way back when Marseilles Prolog didn't even support negative numbers and I had to write my own code just to do proper arithmetic. (I'm not responsible for the course design, I'm just one of the few people in the department who knows Prolog.)

Functional languages, imperative languages, object-oriented languages, compiled languages, interpreted languages: yes. Even some acquaintance with assembler and the techniques that are used to execute all the other languages, just so you know what the machine is really doing. But Prolog remains a tiny, specialised niche, and I'm inclined to agree with what Paul Graham says of it: it's a great language for writing append, but after that it's all downhill.

I mean learning Prolog in the way it would be taught in a "Programming Languages" course, not as an attempt at facilitating AI. Two angles are important here: (1) programming paradigm features: learning the concept of late-bound / dataflow / "logical" variables. http://en.wikipedia.org/wiki/Oz_(programming_language) is an OK substitute. (2) logic, which is also something to be taught in a "Programming Languages" context, not (only) in AI context. With Prolog, this means learning about SLD-resolution and perhaps making some broader forays from there. But one could also explore connections between functional programming and intuitionistic logics.

If you've learned the basics, the next step is to exercise the basics on small but increasing challenges; so that you can mentally decompose large challenges like GitHub projects into attackable pieces. A year ago, I would have suggested the Euler challanges, but today I'd recommend the Matasano Crypto challenge. Why? 'cause chicks dig hackers. Also, security engineering-type thinking is very compatible with lw-style rationality. It's no coincidence that Wei Dai is a top contributor both here, and in real-world cryptography circles.

Consider volunteering in an academic lab that does computational research- such as bioinformatics, or computer science research. This will get you practical programming skills, but also other useful skills and knowledge related to the specific research being done.

I'd consider interactive graphics. Nothing else has such instant feedback; it's very obvious if something is working or not and you can easily figure out what's wrong. Using Javascript and Canvas in a web browsing you can get up and running with 2D interactive graphics very quickly and you just have to hit refresh to see the changes you make (I don't know what Python offers in this area). I think it's a great way to learn various programming abstractions too. By working at a low level, you're not forced to use abstractions, but you can see why they're useful once you start writing more complicated programs and also develop an appreciation of their limitations. If you go straight into a framework, you go in at the deep end and have to learn somebody else's way of doing things without really understanding why they're doing it.

Build something you need. What you don't know, you'll learn in the process.

[-][anonymous]00

Learning two languages at once can help you generalize. You may as well learn JavaScript, as you'll have to do it eventually. You might try Haskell. I don't know if it's a good language to learn on, but it might be a fun experiment--a functional language this early in your programming career,but then again it might be a little too confusing.

[This comment is no longer endorsed by its author]Reply