Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It is hard to answer this because a lot of the trite answers are indeed false. A computer science student may be more able to tell you whether an algorithm is O(n^3) or O(2^n), but the normal (and experienced) programmer will be able to tell you either is "slow" and fix it just as quickly.

But there is a style of thinking that can come out of a study of computer science that can be very difficult to obtain on your own, and enable you to build larger and better systems than all but the very, very, very best of self-taught programmers, and while it's hard to put that difference into words, it's mostly the study of maintaining invariants in the code from both a theoretical and a practical standpoint. Or, if you prefer, a way of thinking that helps create and enforce a mathematically-strong form of conceptual purity in your code.

Those who don't have this background, and I very much include people who took the courses but just sort of skated through without absorbing anything, will often have problems with any API I create that requires certain constraints, such as being careful at what point they access local information vs. remote information. Their use of the APIs will be sloppy and hacky, because they don't really understand how they work or what they are for. The constraints I am thinking of are purely technical, a particular server/client split, so when I say you can not do X it is not merely me being an academic prick, it is because it is actually impossible to do X because at the time your code runs you are literally in the wrong place. Explaining this fact is easy, but explaining how the system conceptually wraps around this constraint and works the way it does is a challenge.

And APIs designed by such people, while they may get the job done, tend to be very brute force (for lack of a better term) and to lack any sort of firm foundation, such that the moment a requirement even slightly changes we have to make massive (and often hacky) changes to them.

Unfortunately, it is impossible to provide examples in the scope of a single post, because all small examples will not show the issue. It's a larger pattern of issues that tend to start interacting with each other, which is where the real problems emerge.

It is also the case that a proper path chosen through a computer science program will take you through some eminently practical theory that will make you a vastly more powerful programmer, and is very hard to pick up on your own. By far the biggest example of this is compiler theory. If you are currently in college and still have the opportunity to take your local compiler course, take it. I don't write very many "compilers", but I have now written quite a few "interpreters" and it has enabled me to complete projects that could not have been completed any other way. Getting a formal grounding in signal processing is also a good idea, that one can be hard to pick up later and has surprisingly useful intuitions for a lot of high-speed networking tasks. A formal grounding in networking can be good, though a lot of courses unfortunately seem to just march through TCP and the OSI model, which you could relatively easily just read about.

The fastest way to obtain this basic understanding if you are a good programmer but lack the formal education is one of really, honestly working through SICP (and not just reading it), or becoming fluent in idiomatic Haskell, with special concentration any time someone talks about "enforcing invariants via types". (Personally, I believe Haskell has completely supplanted Lisp as "the language to learn to expand your mind even if you have no intention of using it", but be sure you stick with it for a bit. Learning how to string together a couple maps and a fold is not where the interesting stuff is, it's what the interesting stuff is made out of.) Also, break yourself of the subconscious idea that academic === useless. As someone who tends to straddle the border I will completely agree it isn't all useful, but it isn't by any means all useless either.

And just let me reiterate as my closing point that it is absolutely possible to go through even a very good Computer Science program and fail to absorb the useful lessons it has. Presumably these are the people claiming it's "useless". I have to admit I tend to not have a high opinion of people who managed to go through a solid program and come out with nothing. (There are also some complete wastes of programs, so YMMV.)



Very, very insightful post. Thank you! To add a little personal bit, I use Haskell daily in my research. I also do web programming on the side in Rails. After figuring out Haskell, and then learning idiomatic Haskell (along with monads, monoids, functors and friends) my way of writing Ruby became much different. I'm more cognizant of patterns in Ruby as they relate to Haskell (as they relate to formalisms in computation). For example, handling nils in Ruby can follow patterns of the Maybe monad in Haskell.

This isn't to say that Haskell is the only mind-expanding language out there, but it sure is good and it worked for me. I think it makes it especially easy in this regard over ML or Lisp in the "mind-expanding" game because it has so many formalized computational concepts that are first-class and upfront. That's not to say that you can't expand your mind in other languages, but Haskell can really help you out if you're willing to roll with the learning curve.


I would add that part of the reason I think Haskell has supplanted Lisp is that so many of the concepts of Lisp have been absorbed into mainstream languages that the distinctiveness is greatly reduced. Macros are still mindblowing, but much less so if you've used Ruby or Python or Perl than if you're a pure C programmer. In 20 years, I suspect modern Haskell will be "less mindblowing" for the same reason. It's not that Lisp has gotten less good or anything, it is that it has mostly won.


Macros are still mindblowing, but much less so if you've used Ruby or Python or Perl than if you're a pure C programmer.

I disagree with this statement. Python's introspection, first-class functions, magic methods, and duck-typing add a lot of the dynamism of Lisp, but every time you run up against something that needs to be a macro, it's a dead end. C has a rudimentary macro system that can get you a little past that point; for example, it's not too difficult to add a foreach construct to C that looks like this:

    queue *q = queue_new();
    queue_add(q, 1);
    /* ... */
    foreach (int i, q) {
        printf("%z\n", i);
    }
On a sidenote, it's kind of sad that a programming layer just above assembly language created 4 decades ago has better macro support than some of the most popular modern languages.


On a sidenote, it's kind of sad that a programming layer just above assembly language created 4 decades ago has better macro support than some of the most popular modern languages.

I disagree. In Python, you have much more advanced metaprogramming facilities, depending on what kind of effort you wish to go to. You have the normal introspection, magic methods and metaclasses as you mentioned (which, IMHO, are in themselves already much more powerful than what you can do with the C preprocessor). But you also have access to exec and eval which lets you do all kinds of crazy stuff that isn't possible with C macros. Using operator overloading and classes, you can even create a lot of new syntax which isn't possible in C[1].

Finally, if you are really determined, you can even hack semantics of existing Python constructs by instrumenting the bytecode. For example, I saw a hack which adds tail-call optimization to Python functions this way (iirc as a decorator).

[1] One example is python-pipeline: http://code.google.com/p/python-pipeline/


I havethat's usages. You are falling for he fallacy of believing that because you are a talented that only people with the same experience and knowledge can be talented. This mistake I see in the many the recruiting articles that make it to HN that boil down to "how to here someone go is exactly like myself".

I have worked with extremely intelligent CS graduates. When it comes to the really involved algorithmic work they leave me in the dust. However every programming job I've ever had has been focused on the other stuff like writing tests and building clean abstractions and maintainable code 99% of the time.

When it comes to this stuff CS grads are no better than any other programmer. In fact, new graduates are often worse because they've never had to build and maintain massive systems over any significant period of time.


Try the following thought experiment:

Person A spends four years getting a BS in CS at a top-tier school, learning about programming at least for a few hours a day on average, with the benefit of a well-considered curriculum and instruction by wizards.

Person B spends four years working full-time on something interesting at Google, which probably gives her more total hands-on-keyboard time, and also access to some minor wizards, although they may not care so much about teaching her.

Let's say that both of them also spend a bit of time on the side learning programming things not school- or work-related.

If both of them have an equal thirst for knowledge, I just don't see why person A is likely to become a better programmer, or why B would fail to pick up the style of thinking you described (which is common, in my experience, among good programmers.) I honestly think that you're mixing up the consequences of {smart, curious, motivated, spends a lot of time programming} and {took a CS degree}.


> Person A spends four years getting a BS in CS at a top-tier school, learning about programming at least for a few hours a day on average,

Real world might be different, but I don't think a CS degree should be teaching programming at least for a few hours a day. IMO that would be a total waste. There are bazillion of things to learn - database concepts, discrete maths, networks, ai&ml, digital electronics, some basic circuit theory, operating systems...There is programming involved in almost all of the courses, but the purpose isn't to learn about programming. When I am learning about MVCC, I am least concerned about learning programming, but the MVCC concept itself.


Sorry, I was just using that as a catch-all to describe learning "things which will probably help you be a better programmer in some way."


Often the best to prove you know these things, is program them.


What are the chances of actually getting a job at Google straight out of high school?


It would be pretty tough, although you can replace "Google" with "any roughly Google-quality set of coworkers and projects." But the original question was whether it's really "very difficult to obtain on your own" the sort of perspective and knowledge you get from taking a CS degree. I doubt that, and I think that most people who are similarly smart and spend a few years working hard with other smart people will pick up many of the same skills.


I work with two people who did.


I would love to read an expanded version of this, how may I interest you to write it? :)


I've stabbed at it, but what came out had a circular dependency in it; the only way to understand the text that resulted was if you already understood the text. About half the stab attempt is at http://www.jerf.org/iri/blogbook/programming_wisdom , with another half just sitting on my hard drive (which is what has the stab at a discussion on exactly what I personally meant by conceptual purity), but until I figure out how to get past that circular dependency it's probably not going anywhere. And I suspect what I'm trying to do there is simply not possible.

Oh, and this expands my Haskell point: http://www.jerf.org/iri/post/2908




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: