What if I went to a Java school Joel?

Way back in 2005, I read an essay by Joel Spolsky titled The Perils of JavaSchools. When I read the essay the first time, I suspected Joel was right about Java trivializing several aspects of the traditional Computer Science education, but I didn’t really care. At the time I was just starting my second quarter of college in the CS program at the University of California at Irvine which definitely falls under the “Java school” classification. At that point I had only ever really programmed in Java and I liked it a lot. Joel was right, but I was happy with my relative Java proficiency at a Java School so I largely indifferent.

Fast forward to the present. Last week, I borrowed Joel’s new book “More Joel on Software” from Michael Arrington which contains the “Perils of JavaSchools” essay. Reading the essay again I was blown away. What a difference a few years of CS education makes! This time instead of just feeling that Joel is right, I know he is right. Learning Computer Science completely in Java instead of C with a healthy dose of functional languages like Scheme is two different worlds.1

All CS degrees are not created equal

Is the value of my CS education less than that of the traditional CS education Joel reminisced about? All other things being equal, I would say absolutely say “Yes”. I can not help but agree with Joel when he says that an all Java education can never be of the same caliber as the CS programs that preceded the Java “revolution”. People like Guido van Rossum, Paul Graham, Steve Yegge, Linus Torvalds and many other great hackers all received their degrees before the notion of a Java school existed. And as Joel puts it, they all went “stark, raving mad trying to pack things into bits”. The bit level is considered foreign territory for students at Java schools; a place we dare to venture only once or twice and will quickly return to the safety of the Java virtual machine.

Joel’s essay is best summarized by this paragraph:

You used to start out in college with a course in data structures, with linked lists and hash tables and whatnot, with extensive use of pointers. These courses were often used as weedout courses: they were so hard that anyone that couldn’t handle the mental challenge of a CS degree would give up, which was a good thing, because if you thought pointers are hard, wait until you try and prove things about fixed point theory.

I have never even heard of fixed point theory!

Finally we come to my dilemma. I have one year left at my Java school and I desperately want to avoid mediocrity. Since adopting Ruby as my primary programming language last summer, I have experienced several small victories. Ruby is a very powerful language which is gradually breaking me away from the ridged programming practices I picked up from programming in Java for 3 years. Ruby has introduced me to things like metaprogramming, reflection, DSL’s, anonymous methods, and several aspects of functional programming. All are things that I never would have been able to fathom had I stayed inside my Java bubble. I will say that CS students at Irvine take a Programming Languages class which introduces unfamiliar languages like Haskell. Unfortunately, the class doesn’t make up much ground. Like all classes it is only 10 weeks long and students only get a brief look at the various languages they are introduced to. To top it off most of the projects are still done with Java.

Ruby is not the Answer to Life, the Universe, and Everything

Ruby is great but its not going to teach me any of the low level knowledge I am lacking. I can program in Ruby for another decade and still not achieve a full understanding pointers. The only thing I can do to understand why while (*s++ = *t++); copies a string, is to actually program in C.

Why I am not learning C now

Learning C is something that you generally need to be forced into. In today’s world you are not going to able to write very much software if you are coding the entire thing in C from top to bottom. It is a very anti “Get Things Done” programming language. In addition, there are very few things that actually need to be written in C. Operating systems and compilers are the two big areas where use of C is nearly always required. Both are territory that I am not interested in venturing into at this point. The most common use for C among software developers is to optimize slow chunks of code by rewriting them in C. However, everything I write does not need to “scale” so while I always do my best to not write inefficient code, I can not be bothered to rewrite any of it in C when it is “fast enough” already.

What I am going to do about it

This is a problem that I have not thought of a solution for. I can not bring myself to sacrifice productivity in order to use C. At first I thought I would learn Objective-C which is based on C in order to create Cocoa applications for Mac OS X. That solution is flawed however. Just like Joel says learning C++ is not a substitute for learning C, the same is true for Objective-C. My best chance is if something in my school work for next year comes up that requires the use of C. If it does happen it will be an elective; the chance of a required course using C at Irvine is very slim. I am just one person, what I am experiencing is true for Computer Science students across the county at Java schools. We are collectively being handed a disadvantageous education and in the long run it will have a direct impact on the level of software engineering that is being done in the United States. For instance, I would guess that a graduate from a Java school is far less likely to ever contribute to the Linux kernel, GCC, or a similar project. This is of great consequence because we need innovation at the lowest level of software in order to continue innovating at the top.

Obviously, if American Universities are going to keep up, they need to switch back to the “middle ages” of Computer Science and resume using C in the classroom. For those of us that are already in the system, or recently graduated, individual crusades are required to attain the level of understanding that is obligatory for Computer Science graduates. For myself, this will likely include working through the exercises in Structure and Interpretation of Computer Programs and the accompanying lectures. I am still looking for a good, practical way to learn C. Just reading Kernighan and Ritchie is not going to be sufficient. There is a big distinction between learning to program and learning a language. I need to learn to program—for real this time.

  1. Read “The Perils of JavaSchools” for an explanation of why they are different. 

64 thoughts on “What if I went to a Java school Joel?

  1. Allen

    Man. Why would you write a compiler in C? Even if you’re compiling to C or a lower-level language, most of compilation is about AST traversal – something that having nice high-level data structures helps with, and having access to low-level bit-bashing doesn’t help with. I’m working on a programming language implementation (http://launchpad.net/ecru), and the only part that isn’t in C at the moment is the compiler.

  2. Jeff

    Computer Science:A Programmer’s Perspective by Randal Bryant and David O’Halloran is a fantastic book about low level computer systems in general. It won’t teach you basic C, I think I’d still say reading K+R and writing some basic data structures in C would help there, but the real gap of what you know versus what others do is in the low level stuff, including machine representation, computer architecture(caching, ISAs, etc), Operating Systems, etc.

  3. DeeplySexy

    “People like Guido van Rossum, Paul Graham, Steve Yegge, Linus Torvalds and many other great hackers” steve yegge? for real? in the same list with rossum? the central idea of the article is correct but (as always) i could do without the joel and yegge ass sucking.

  4. Mark

    I recommend either trying a graphics demo like a raytracer or a network application like an FTP server. These are projects you can finish quickly, and C is an excellent language for them.

  5. Tom Finnigan

    Take a class where performance is crucial, or where you need low-level access to the bits.

    In my program, networking, operating systems, or graphics fit the bill.

    Networking, we implemented a TCP/IP stack. Operating systems, we implemented FAT. Graphics, we did ray tracing with glossy reflections (and other probabilistic effects) and huge scenes.

  6. anonymous

    you know, computer science isn’t all about programming languages and programming.

  7. Sergey Solyanik

    Ruby is not going to help you attain a lot of what you are missing in Java. Yes, it’s a more modern high level language, but it’s still a high level language.

    My advice would be to get a hobby. Find yourself a project outside school that is fun to do and requires low-level programming.

    In the interviews I always ask people whether they have learned their first computer language at school and whether they have personal projects outside school or work. Having negative answer to the first question and a positive answer to the second is a huge bonus because it shows motivation…

  8. Nathan

    Also having attended Irvine for 3 years now, I have a very similar perspective with the one difference being that I had an excellent computer science department in high school. In the three years at high school CS department, we spent time on C in nearly every course. At the time, I hated it and always complained about using such an old language. That was silly of me. The knowledge about pointers, memory access, low-level data structures, and much more was very valuable. The scary thing is that these issues have never come up in the program at Irvine. (Although, I am “informatics” which may have had an effect).

  9. Ed

    Take a microcontroller project class.

    Or since you like Ruby, try to extend the Ruby interpreter.

  10. SDC

    Man I’m glad I just bypassed CS altogether and got a Physics degree. And I was there BEFORE the Java schools…

  11. damien hunter

    I’d make friends with a few electrical engineering types and try helping them program their microcontrollers. Most of the ones I’ve seen can be programmed in C (as opposed to a native instruction set).

  12. Shiro

    One way to learn C and low-level stuff without lots of overhead: Pick small CPU kit like PIC controller board from Fry’s and make some trivial gadgets. Most of such kits come with C as a development language. And you can directly touch the bits and control hardware, skipping all the fuss about OS and middleware layers.

    Some of the comments above suggest network programming, and I recommend it, too. For practical purposes, network programming itself is much easier with Ruby or Java but lots of interesting bits are hidden. Stevens’ “Unix Network Programming” comes with working C code exsamples and excellent to get a look of “under the hood” stuff.

    For graphics, I feel the developers have shifted to C++, and you have to learn huge set of APIs nowadays to write something interesting. You will learn a lot, but unless you want to fully dive into the graphics stuff, you may reserve it for future.

  13. randy

    “Computer Science:A Programmer’s Perspective by Randal Bryant and David O’Halloran is a fantastic book about low level computer systems in general. It won’t teach you basic C, I think I’d still say reading K+R and writing some basic data structures in C would help there, but the real gap of what you know versus what others do is in the low level stuff, including machine representation, computer architecture(caching, ISAs, etc), Operating Systems, etc.”

    I’ll second this comment. Currently a Grad Student at DePaul University in Chicago and this book was covered over two courses that are required. It’s correct that you will NOT learn C from that book. To get the most from that book you should already know C, and use the book to gain an understanding of how it interacts with and is represented at the hardware level. Additionally, the course material is excellent and several projects focus on assembler and disassembly of Linux binaries. I believe the course material is published online, but can’t recall.

  14. Jonas Gorauskas

    Here is a thought about learning C: Learn it in small bite size chunks by working on small yet interesting/relevant projects. For example, pickup a copy of Linux Device Drivers from O’Reilly and start working through the book. You probably have an old NIC laying around and you can use the knowledge you get from the book to write a driver for it. You can also use VMWare or other virtualization software to minimize impact of mistakes and the compile, test, execute cycle. Just my 2 cents.

  15. Geo Atreides

    You could learn C by trying to translate libpurple, from gAIM/Pidgin, to, let’s say, ActionScript. That way we could write our own messengers in flash, for example. G.

  16. Neo

    Operating systems and compilers are the two big areas where use of C is nearly always required.

    This is not true. Perhaps, it is because of the “Java School” syndrome or it could be that you haven’t yet had the aha moment yet.

    Here is a compiler written in Python that compiles C code:


    The operating system for this computer was written in Lisp:


    Hopefully these fine examples help you to see that your generalization is not accurate.

  17. Michael Ramirez

    Programming is all about abstraction. The greater the abstraction the more productive the language (Doing More with Less). HLL are just abstractions of Assembly (machine code) but in order to use HLL to their full potential you must have a good understanding of what they are abstracting. Learn x86 Assembler. Only then will you understand pointers, OOP, memory management, etc. I just graduated with a B.S. in Computer Science. I have 8 years experience and have developed in C/C++,PHP,Perl,Python,Coldfusion,C#,VB and Actionscript 3 but I still lack the fundamental understanding of programming. I have alot to learn and I think x86 is the answer for me.

  18. George McBay

    Learn C!

    If your school doesn’t give you an elective that uses it, make up your own hobby project and write that in C. I recommend writing a small game, perhaps a clone of an existing retro game you love (so you can focus on the programming and not the game design). Either write it on a embedded platform like the Nintendo DS (if you look around you can find unofficial dev kit software and hardware that allows you to code for it) or write it for the PC against SDL’s C API (so you don’t have to worry about window management specifics).

  19. John UIUC

    At University of Illinois at Urbana Champaign, I can remember only one class which allowed JAVA. Just about everything we learned was either in Scheme, C++,C, or SmallTalk for those lucky enough to take Ralph Johnson’s Design Patterns class.

    Also, we still took that “weed out” datastructures class that made you cry because you needed to re-learn every insertion and deletion algorithm for red-black trees

  20. gk

    You do realize there are several ICS classes taught in C? For example, ICS 145 (embedded systems) uses nothing but C. Maybe it’s just because I’m not retarded, but I found transitioning from Java to C to be pretty easy.

  21. bingo

    Wait…isn’t this a sarcastic article? “I can not bring myself to sacrifice productivity in order to use C.”

    He’s making fun of C, right?

  22. James

    Uhhh, the only places that use Ruby and Java are various flavours of web-apps. Nothing mission critical, performance oriented or safety-critical is ever written in anything like that.

    Ada, C and Lisp for programming. SQL for Databases. UML for Business Analysis.

    That’ll turn you into at least half a professional from a tools point of view.

  23. JS

    Your section “Why I’m not Learning C Now” speaks volumes about the problem. If you’re unwilling to motivate yourself to learn the low-level languages you need to understand to be a competent programmer, then you will remain incompetent. It’s that simple. Your attitude about writing things that “don’t need to scale” suggests you have a fine career ahead of you as a code monkey writing business application code until they outsource your job.

  24. johnny

    the thing is, this argument has been going on since long before java – really since the beginning of humanity i imagine. i remember my mathematician uncle criticizing the use of calculators because slide-rules required a great deal more knowledge and ability.

    the same ‘end of the world’ proclamations accompany every leap in abstraction. yes, programming in machine language and assembly may be ‘harder’, and may weed people out. yes libraries and virtual machines and frameworks make things ‘easier’ and create dependencies.

    but they also allow you to leverage a lot of existing knowledge and build much more complex things far faster. imagine if you had to mine and smelt ore when what you really wanted was to drive a car.

    those who wish to learn the foundations of things will still do so, but specialization and abstraction are part of progress – in computer science, programming, and everything else.

  25. Patrick

    I also second Computers Systems: A Programmer’s Perspective. It’s currently a requirement for our Operating Systems course.

    Rob: Very interesting post and I think you’ve inspired me to write a response as I too read Joel’s article in 2005 and just reread it two weeks ago… I hope I will be allowed the privilege of a reader or two when I post my response.

    Understanding that, for you, practicing C will not come up unless you’re forced to in the form of a school related project or course, the going will be tough without motivation in some way. Nevertheless, I highly encourage going to my site in the Resources section’s Computing I category to look at the problems we had to do in our introductory computing science course. If that day comes where you are feeling motivated, read or reread K & R, maybe pick up Applications Programming in ANSI C, by Johnsonbaugh(our Computing I requirement text) and work through that whole book… it’s got a really great scientific and engineering emphasis centered around C. Then, work through the problems in my Resources section(Computing I) and when you’re finished, you will have a better feeling of what learning C is like at the freshman level, hopefully giving you more confidence in the low level world. When you want to take data structures, my Computing II course can be recommended but I personally found it dry, specifically because of the text that was used.

    Learning C can be looked at like learning Lisp or Scheme. They’re both fundamental languages that today have a tough time being implemented by corporations; businesses want profits quickly, which are delivered by productivity. But both languages teach you about something that is particularly difficult to grasp in other more modern languages and those concepts can help you become a better programmer(Graham). Shoot, but you know of Graham, so take what he says to heart and force yourself to learn C, or Scheme as a personal project – that is if you really are feeling that you need what those languages teach in your repertoire.

    Best of luck to you along your crusade.

  26. Chad

    I graduated from UCI in 02. It was all done in C and c++ during my tenure. We had to learn Scheme and Prolog. I remember the honor students getting to use Java and envying them. But since they have switched everything over to Java I am glad I went through the old program. :)

    I find that of all the pointers and linked lists that I learned about back in school, I have used none of them for the most part in my professional career. Now maybe that is cause I am working in the corporate environment part of an IT group rather than making software for a living, but my bills are still getting paid nicely.

  27. creaothceann

    Start at Assembler, then proceed to Turbo Pascal (same level as C, much saner syntax, unfortunately without built-in preprocessor).

  28. Ron H

    It wasn’t until I took circuits that I really understood what was going on at the lowest level. Programming in assembly was a real eye-opener. I call it my digital satori.

    I think Joel recommends C in order to induce that state. Me, I’m not that smart. I had to be bludgeoned with assembler before it sunk in.

  29. Geoff

    You must have chosen a very different track of coursework than I did. I graduated from UC Irvine in 2005 with a degree in ICS. I took classes in compiler design and operating systems, both of which were in C. I took computer engineering classes that used MIPS and x86 assembly. My intro to computer science class was taught in Scheme (it was the honors track, though). I took multiple algorithm and data structures classes, most of which just used a formalized pseudocode. I would not consider myself a weak programmer in the least, as I am able to understand exactly what goes on at the byte level, even though I get paid to write Java web apps at my day job. If you don’t expect your professors to spoon-feed you everything, you can be proficient in anything you like (as you mentioned that you are trying to do, commendably), but I wouldn’t be so quick to blame Java for a curriculum’s lack of rigor. Java is a very productive and powerful language, and there’s nothing inherently wrong with it.

  30. fran

    You worry way too much about this. At my CS program, way back 18 years ago, we used Pascal for all the 100 level courses. The faculty refused to switch to anything industry was using because, as the head of the department said, “we expect you to learn new languages at the drop of a hat” and they didn’t teach anything else. We had one language survey course that covered Ada, Smalltalk and Prolog, but that was it. We had courses where you had to write drivers in assembly, or unix programs in C, and other courses where you chose the language you did your work in. I knew some fellow students who thought that the university should be teaching us a popular language, but the faculty thought that they should be teaching us how to learn languages. I agree with the faculty, and I’ve never used Pascal professionally.

    So, who cares what language you use in school, you’re going to have to keep your mind nimble and learn lots of languages in your career, and probably invent some yourself. Don’t get hung up on it. It takes about 10 years in any field to really understand the field no matter how good you are, so don’t worry too much. A number of times I’ve taken jobs where I started learning the language right before starting the job and the people who hired me knew it, too. The first job where I used java was when java was just getting noticed, java programmers were rare and all the hires at that startup learned it on the job.

    I’ve written a lot of java code since then and find that java is really not that bad. It is trendy to bash java these days, but having a really mature tool set around a language allows you to do a lot of complicated things that you can’t even contemplate in a ‘minor’ language. Is java limiting? Sure, all languages are to some extent, but java has a lot of good aspects too. Java isn’t going away any time soon, so having some java experience is not a bad thing.

    As for Joel, well he says some smart things and he says some dumb things, I’d take it with a grain of salt. Half of the java hackers I know are ex-lisp AI guys, whip smart and deep, and they all think Joel is quite amusing.

    If I were designing a CS program for programmers going into the field, I’d want to increase the focus on creative thinking and problem solving, understanding the business aspects of the profession, and debugging and scalability issues. I realty don’t care about languages too much, if you can’t handle changing languages you aren’t going to last long as a programmer.

  31. Rob Olson

    Thanks everyone for the comments. I’ll be responding to many of them after I get off work.

    I want to stress that this is not merely about “getting a job”. That has never been an issue. This is about becoming a great programmer, or at least reaching my full potential.

  32. E

    Most people who are proficient at C (and low level programming, bits, etc.) have worked in environments that lacked scaffolding. That is, either early on (when you had smaller or nonexistent software stacks) or lower level (e.g. OS operating systems or tools) where there just isn’t that much support — you have to roll your own.

    So the key is to find something to work on that doesn’t have that scaffolding, or where the scaffolding has to be chucked.

    Nowadays, any kind of internal operating system work would fit into that category (drivers are the easiest pont of entry, but some people start at schedulers and filesystems, some mess with very low level networking stuff).

    Working on software for prototype hardware would be similar — and has the advantage of being much wider scope and also giving you experience in hardware hacking. (Robotics, maybe hack some kind of portable device, a coffeemaker that plays music, whatever you want.)

    My personal experience, like a lot of the others you see, comes from the 80’s personal computer era — where every machine (that one could afford) was essentially an embedded device with a hardware manual and a little bit of embedded software support… If you were interested in the machines and what they could do, you inevitably had to deal with the bits.

  33. Alan

    The Joel article just made me feel all smug and superior over the poor Java school weenies. Your post makes me realize just how lucky I was to get into this game when I did.

    Like yourself I do not find any daily need for bit-twiddling, but been there, done that, decades ago, and what I got from it is the foundations for the set of languages and tools I currently use.

    What is taught in “The Java Schools” now could very easily turn out to be the foundation for the dialects and tools we’ll use next decade.

    But if you haven’t heard of fixed point theory I doubt it :-)

  34. oldschool

    Everybody thinks they know what ‘real’ programmers need to know – it’s usually whatever they where forced to learn.

    When I hear someone going down this road I usually just write them off as a blowhard unless they have some empirical evidence to support their position – which they never do.

  35. dan

    I would say that a good project to help you learn c is to program your own version of the make utility in c. I come from a java background, and had to recently learn c. This was a great small project that helped me learn c. Making your own version of make will help learn makefiles, malloc/free, datastructures(you should implement your own as a good exercise), system calls, and also some recursion. It really encompasses alot.

  36. Anonymous

    I realize I’m posting as anonymous, and that I’m way down the list here, so I probably won’t get read. That said, here is a little to help you. C is not only for compilers and Kernels. C++ is not scarey, and you can write C code in a C++ world. I do it all the time. C++ is not inefficent, and does not need to be so far abastracted as to become an insufficent C.

    Graphics Applications need to be very fast, so they are written in C/C++. Shaders used to be written in a pseudo assembly, but now are written in a higher level system like C/C++. Soft and Hard Realtime systems, Pseudo-Realtime sytems all generally use C/C++/Assembly. Databases, back ends, etc, all need to be fast and are generally written in C/C++. Embedded systems, yup, C/C++/Assembly. Its not limited to a few small categories like you want to believe.

    Bottom line is Pretty much, if it isn’t web enabled, its likely C/C++. If it is web enabled, its likely there is still a C/C++ backend driving it.

    Now, many a C/C++ programmer may flame me here, but only if they suck. If you want to truely understand C/C++, pointer fiddling, casting, structures, memory packing, stack frames, and all the goodies that make for a truely good C/C++ programmer, you absolutly positivily need to take Assembly. Yes Assembly. Its painfull, its torturous, but you’ll actually understand what it is your C/C++ code is doing. What actually happens when you caste a pointer. (Nothing! its a compiler construct only, nothing changes in memory!) None of the “Magic” that C++ provides you will seem like magic any more. You’ll appreciate the genious behind Java, but understand the performance limitations. You’ll learn more about writing efficient C/C++ code than you ever wanted, but did need. You may even find you are truely insane, and enjoy the punishment of assembly. I do not, however, reccomend you take an assembly programming course first. Learn C/C++. Get comfortable, even if you must accept that some thinggs happen by magic, or you have no clue why something might be usefull. Only then should you take the assembly course. Once you take the course, you’ll appreciate this. My professor was teaching us some math tricks in binary. Ineveitably, one of the C/C++ only programmers says something to the effect of, man, if only this data was in binary instead of hex! He did understand the humor of the statement, and had a better understanding of what goes on under the hood of C/C++ then.

    Even now in my job I come across many C programmers who never took assembly, and still have no idea why a properly packed structure can just be written to a network and come out on the other side. Most feel the need to do something irritating like make a byte array, caste the first address to an int (like *(int)arr=value, write data; caste the 5th address in as a double (like *((double)&arr[4])=doublevalue, write some data; string copy data into the 13th address for 10 bytes (i.e. strncpy(&arr[12], “this is too long to fit in 10 bytes”, 9); arr[21]=’\0′; ) And yes, I wrote that all in the ugliest possible syntax I could think of. No guarantees on it compiling, its not my style of writing. Personally, if I were going to use that method, which is sometime, but only sometimes necessary, I’d zero out the array to make sure all string operations will have a terminator somewhere, even if something goes wrong, use pointer arithmatic inside caste statements, etc. I’d prefer to write a structure, since properly packed (i.e. #pragma pack push(1) ) its the same thing, only without all the casting being necessary. So much cleaner! But so many C programmers don’t realize how memory is organized, and don’t realize its the same thing.

    I’m not saying assembly is the only way to learn this stuff, experience, teachers, mentors, etc can all lead you to the same knowlege. An assembly class will just get you much closer to that, and better yet, while you are still in college!

    Good luck!

  37. Austin

    I went to a university that had a pretty strong emphasis on Java (although I certainly had good exposure to other languages). Now I work in the defense industry. Java is pretty popular with project managers because the talent is easy to find, the code turns out to be more secure and have fewer bugs, and a lot of the newest stuff that the customers want have some sort incorporation with Java.

    It turns out that learning Java wasn’t a bad investment in my time. Still, I really wish I could have done more work with C while in college (especially large projects).

  38. Blake Watters

    For what its worth, here is my experience. I began programming at 12 on a Mac IIci with a pirated copy of Symantec-C++. I learned C by reading as many books as possible and pounding my head against the wall until I was finally able to get stuff done. Then I learned the Mac OS X Toolbox API, which led me into learning about Pascal and eventually m68k assembler. Then I switched to UNIX by installing OpenBSD and went to work learning POSIX API’s. Joined open source projects, all that sort of stuff.

    Fast forward to my high school years and I’m on Linux, doing systems administration, and taking AP CS classes in 9th and 10th grade, where I first encountered Java. And I crushed the Java classes. The greatest difference between my class mates and I was that I had a sense of low level systems and an understanding of how to design and maintain real applications.

    For college, I attended UNC-CH for about a year and a half, taking CS classes. UNC is very much a Java school and I was bored out of my mind and living right next to a start-up hot bed in the triangle. I dropped out and have never looked back. Over the last five years I have done PHP, Objective-C/Cocoa, and now Ruby professionally.

    Now I am heading a team at a start-up and have a huge stack of lessons from the last 4 years. None of them were learnable in the academic arena. The hardest thing when you get into the real world is balancing business dynamics with quality standards — knowing how to make smart compromises to deliver what the business needs, as it is needed. The social factors are not to be underestimated. Interacting with people of differing skill levels and knowing how to delegate appropriately are very hard lessons to learn. You will fuck stuff up. It will hurt.

    There’s a big divide between being a quality programmer and a quality developer. Its all about the team and you as a member/leader of the team. C and low level programming will help you think and write better code. But you may want to also start thinking about the larger world and how you are going to fit into it.

  39. Brooks Moses

    Here, let me tell you a story about how I learned programming languages, without a CS degree at all.

    We’ll start about the middle of my grad school years, when I was doing computational fluid dynamics programming in Fortran 77. Now, Fortran 77 isn’t a bad language, it’s just a limited one, but for learning the basic ideas of procedural programming it works. And I learned a number of things about how to organize large programs and comment them to be readable and so forth from doing that, a lot of which came from working on other people’s programs.

    So, from there, I decided to try learning C++. I picked a problem that seemed to be appropriate to it, bought a manual on it, and started programming. A month later, I had a reasonable basic grasp on the language.

    Somewhere in there I also learned Fortran 95, which turns out to be a quite interesting language, and has a lot of modern stuff in it. That I learned by translating my Fortran 77 code into Fortran 95, and also by lots of reading on the comp.lang.fortran newsgroup, and paying attention when people posted code samples and other people said what they should modify to do better.

    The story I particularly wanted to tell, though, is how I learned C. I already knew the syntax from C++ (and from having, once upon an earlier time, having had a few weeks of classes in it), so I could read it pretty well, and … well, I could write Fortran 77, so I could create a basic procedural program.

    And, meanwhile, I’d been following the GFortran project, which was building a Fortran 95 front end for the GCC compiler. I wanted to be helpful, so I’d started with the documentation (which is, IMO, a really good place to start on that sort of project — as a newbie, you have better perspective on what needs to be documented, and it’s a good way to learn things), and then got annoyed by an unclear error message and had a look at the part of the code that produced the error.

    Now, it’s hard to write code from scratch in a language that you don’t know, and produce something that’s very good. But it’s pretty easy to take some existing code and see what it does and do pattern-matching to make it do something slightly different. And that’s what fixing the error-message problems required.

    So, I did that, and posted my patch to the relevant GCC mailing list, and it got reviewed, and people said, “This is wrong” and “Why didn’t you do this?” and I fixed stuff and thereby learned a bit more.

    Repeat a bit, over the course of a couple of years, and I ended up becoming one of the maintainers of the GFortran codebase for a while, and now I have a job working in a field that’s a lot closer to that than to computational fluid dynamics.

    So, that’s how I’d recommend learning C. Pick one of the GNU toolchain projects like GCC or GDB that’s written in C (which most of the old ones are, just for historical reasons), pick a part of it that interests you, and subscribe to the mailing lists and listen to what people say in code reviews. And find some documentation that needs work, and edit that. Ask people for recommendations for bugs to try to fix as a “starter project”. And learn by doing.

    If you do that, you’ll not only learn C, but also some things about how compilers (or debuggers) work, how to get large projects to work together, how source control repositories work, how to read complicated existing codebases and fix things in them without rewriting them, and lots and lots about how to navigate the interpersonal parts of programming projects. And all of that will be really useful knowledge in the future.

  40. Jason

    You should check out cs241 webpage at university of waterloo, its the first course in cs foundation sequence and we have already built a compiler from a c-derivative language into mips assembly…

    Perhaps you should think about going into grad school?

  41. Brian

    I’m currently an undergrad CS/EE student at a soso university (not quite Java-school, but no Stanford, CMU, or MIT). And yeah it’s a huge eye opener discovering this stuff.

    This summer I’m interning for Cisco Systems doing network security. Working on embedded operating system in C, it’s very very similar to kernel hacking. At times it seems like bit packing, especially on the protocol side of things, but there is real value in C that I probably wouldn’t have learned unless forced to use it, study an OS written in it, and read thousands upon thousands of lines of C code…

  42. steve

    I think you were on the right track, and that you should go ahead and learn Objective-C. It won’t teach you C, but it will put you next door.

    You will be able to use the Ruby/Smalltalk style of programming for Objective-C, while making little detours into C for performance.

    When you’re up to speed, and that will take you some time as Cocoa is very large, then the jump to C will be smaller and in a more productive and visible environment.

    You will also learn a great deal from studying Cocoa, as it is a very well architectured library that is strongly based on dynamic abilities.

  43. Cameron Kerr

    I teach a paper in network programming in C, and have done so for at least 5 years now. The university where I teach this could rightly be called a Java school, and I have often been asked why we teach this paper in C and not Java. My response these days is centered mostly around the premise that it helps you to understand the internal workings of a system (especially from a performance point of view), and the whole ‘Leaky Abstractions’ which I’m sure you must have read from Joel.

    My students don’t really know C, so the programming is very simple (merely translation of small chunks of pseudocode for the start) and mostly reading a reasonably large pieces of (hopefully) model C code, and using it to discuss design issues: such as performance impact of memory copying and system calls; data input and parsing; abstraction layering and architecture design. Despite not knowing C much when they came into the course, and that this (rather significant re-write this year) is just the fourth week of semester, the response so far has been quite positive.

    There are a number of very good (others have said ‘fundamental’ ) languages to learn and C is but one of them, representing the lower levels of abstraction, but to learn it most effectively, to be able to take what you have learned in C and use those lessons in other languages, you need to not only write something in it, but you need to be able to analyse and really think about what is happening at the machine level.

    It is this analysis, that generally comes through multiple iterations of a design and implementation exercise, that tends to help you develop a mental model of black-boxes when they leak. Benchmarking your code can also be instructive, even if your code appears algorithmically efficient, investigating your available compiler optimisations can be an enlightening experience (like a 280% speedup when compiled with -O3 rather than -O0 in gcc). Learning about keywords such as ‘inline’, ‘const’ and also ‘register’ can be very useful to developing a true understanding of how our code is understood by the lower layers of our abstractions.

    Not to be understated, it is also very useful to understand the numerous ways in which C could be better as a language. Learn from other paradigms, such as functional language; I could that learning even a small by of Haskell or Scheme (via SICP, an excellent resource) improved not only my C, but also even my shell-scripts. (the pipe ‘|’ is an awesome programming construct, I want to use something like it in C).

    In summary:

    1) read reasonably large pieces of good, readable, clean code (avoid highly portable code — forests and trees and all that). The Linux kernel’s linked list library will be a good read for the way it macro’ises a for loop in various ways.

    2) design and write a library to do something non-trivial; design and implement it multiple ways and compare the performance, something like a buffered reader backed from a file-descriptor (such as a network socket) will be very instructive. Think about how many memory copies and system calls are involved in each design, what are the tradeoffs you have made with regard to complexity, flexibility, security and performance?

    3) gain an understanding of performance/correctness enhancing language features available in C such as ‘inline’, ‘const’ and even ‘restrict’. Benchmark and compare performance. Compare the performance against a similar thing done honestly in other languages/libraries (including for example C’s stdio library).

    4) look at other languages. What language features/idioms/control structures might be useful in C? From my perspective, being interested in network programming, I have learned from Erlang (its notion of ‘behaviors’ is very appealing). From Scheme you can gain a real appreciation of why a good (ie. not C’s pre-processor) hygienic macro system can be very expressive for creating new control structures to express your problem domain.

    5) if you want to look at using C for microcontrollers, I can recommend Atmel’s AVR range, which has been designed for C. GCC supports their range of µC very nicely and Spark Fun Electronics has a very nice Getting Started in Embedded series of articles from the breadboard up (of course, there are other options).

    Hope this helps set you on your path. e-mail me if you have any questions.

  44. Steven Talcott Smith

    I haven’t used straight C or even modified a C program in at least 10 years but as far as I can remember it wasn’t much different. Instead of HTML documentation, you had man pages for the library functions you could call. You could edit your programs in vi. I seem to remember doing a lot of “man ioctl” “man open”. I was never very good at memory management but I am re-learning limited memory management now on the iPhone in Obj-C. Use the K&R book and force yourself to write something in C for the command line — something you’d write a 10 line ruby script to do. You should try to learn a new language or two every year anyway.

    Like a lot of people my age, (34) I learned to shove bits around in assembly on the early PCs. Once you have the concepts and a modicum of experience, unless you just LOVE twiddling bits and getting (relatively) nothing done, it is a relief to work in higher level languages like Ruby, etc., and you should not feel inadequate about it. I was excited when Java came along and I am even more enthusiastic today. Focus on working at the highest level possible where you can create the most value possible and hone your craft to perfection.

    The simplicity of the older hardware and chips certainly made low level work more fun. Today it just seems silly to write in C for a PC-level system. If you want to do something fun with low level languages like C … follow the advice of others here and do an embedded or micro-controller project of some kind.

  45. Philippe

    I think a great thing would be to go through SICP and to code the two last exercices en C.

  46. James

    Surely it is odd that you disregard your Java education for points that equate to it being too high level, and then leave it for a higher level language? :S

  47. khanna

    although the default language at UCI is java. I wouldn’t say it is a java school. In my experience the professors of most classes were flexible and allowed for assignments to be completed in c/c++/java some even let students use prolog/lisp/python. It really depends on the professor. I used C/C++ for most of my assignments when I was an undergrad at Irvine.

    If you want low level try advanced operating systems project course.

  48. joe

    Please dont put that fat f**k Steve Yegge in the same sentence as other people who have actually produced something useful. Steve Yegge is well known for producing hugely long-winded and tedious blog posts, presumably written on his employer’s time.

  49. Jason Kikel

    I think what Joel was getting at was not that people should write everything in c, but that they should REALLY understand how it works. Most people say that they understand these concepts because they took a class in school, but find out that that doesn’t really cut it when you are dealing with tough bugs out in the field where a customer only gets a memory error, a win32 stack trace, and a crash dump. I’m speaking for the windows programmer, but the scenario translates just as well into other OSs too.

  50. Rob Olson

    I included Steve Yegge in the list because, while he hasn’t invented a widely popular language or operating system, he has done a lot of programming in his career, including some really cool things with Mozilla Rhino.

    Perhaps just as important as programmming, he has done a fantastic job writing about programming. Which is something we all enjoy reading about. It’s the same reason Joel Spolsky is widely recognized in the industry.

    In the end, Yegge is far greater programmer than most of us can ever hope to be, thus we are not in a position to say that he should not be included in that list.

  51. Richard Hassinger

    I don’t think there is an issue with “java schools” as Java is very conducive to learning deep concepts. For instance, I recently took two sequential graduate courses in compiler design that compiled high-level code into optimized i386 instructions. The compiler was entirely in Java. This went side-by-side with gnutella-like peer-to-peer file sharing system written in C.

    Perhaps a more significant problem is that you’re going to UC-Irvine. Perhaps you should think of transferring to a more widely regarded school.

  52. nickfox


    But in the meantime, I went out and bought an AVR butterfly microprocessor from mouser.com for $20.


    Then I went and bought John Morton’s book on programming AVRs in assembly language. Short, easy and fun. FUN.


    Next, I will work through a C book on AVR:


    And finally to tie it all together, I am becoming one with this website:


    Learning AVRs and assembler and C on those devices has been one of the most educational and fun things I have ever done. It just added life to my programming (I’ve been coding for 11 years).

    But don’t take my advice…. JUST LEARN JAVA ONLY so that at the next software contract I go for I can wipe you off the map. :o)

    have a nice day, Nick

  53. tom

    A few things:

    First off, every time I read about Joel’s gospels, I wonder… who is this guy? The CEO of a small company. Have you heard of their software? Have you heard of anyone using it? Have you seen it? Their one product seems far to simple to require intense knowledge of pointers – in fact the only real programming hurdle they claim to have jumped is building a VBScript to PHP compiler. Repeat that: a VBScript to PHP compiler. Huh? A bad to worse compiler.

    Next: God did not invent the C language. There’s an odd idea that C is the natural language of computers, and that’s entirely incorrect. The speed that C affords and its specific implementation of pointers was the work of a few developers thirty or forty years ago.

    Next: “Learning C is something that you generally need to be forced into.”

    I’m a college student, at a 1/4 java school, and let me say this: almost all college courses provide an unnatural and ineffective system of learning CS. If you think that you will learn CS via courses primarily, that’s a bummer.

  54. GrokCode

    Have you thought of taking a summer class at a school that isn’t a Java school? UC Berkeley lets anyone enroll in the summer sessions – I’m sure there are other universities that do the same thing. Cal does use Java quite a bit as well, but there are a good number of classes that use Scheme, C, Verilog, Common Lisp, etc. Also a few classes allow the students to pick between C and Java. Anyway the classes at Cal don’t teach languages anyway. They teach concepts, and to do that the prof will pick the language that is the best vehicle for learning the concept. You will never find more than 2-3 days of a semester long class that covers syntax of a particular language – this is something a CS major should be able to pick up on their own.

    Well sorry for going on about Cal, but it is a great CS school.

  55. Rob Olson

    @bingo: In the “How To Become A Hacker” guide, Eric Raymond wrote, “the more you can avoid programming in C the more productive you will be.”

    I wasn’t making fun of C. That is just a factor of using a low level language.

  56. Sam

    E and tom do a good job of laying out some important sentiments. I learned to program in C by hacking Linux software and the Linux kernel; I grew most as a geek in hacking the kernel and writing graphics software. (I love efficient memory management.) When I came to UCI, I was shocked that we would be using Java.

    But Joel isn’t really arguing anything. His essay is whining about the good ol’ days—he actually ends with “Feh”—and making some poorly founded assertions about what computer science is and precisely how smart you should be before you’re allowed to graduate. Though he has many good ones, I’d be careful about putting much faith in that particular essay. I’m not convinced, at least.

    Really, what Joel wants is for all his applicants to be smart, especially smart in a way he can interpret. He’s getting old, after all.

    I’d argue that the way we’re fragmenting CS at UCI is the right way to go. There needs to be a degree, I think, that gives you what you need to know to scribble hyper-optimized Bayesian magic in the Linux kernel with your left hand. Maybe that should be your degree. But there is also value is not teaching students C, and instead expecting them to learn things like the various design disciplines. The latter can make Twitter, and the former can make sure Twitter’s infrastructure can handle the load. (Ahem.)

    Besides, in Informatics, UCI starts with Scheme (recursion-only) and some assembly. We do the Java in CS-2. All is not lost.

  57. Pingback: The Case For Replacing Java With Python In Education | Thinking Digitally

  58. somebody

    I’ve been programming for nearly 15 years and a good half of it is low-level programming. Not only C, but also 16bit, 32bit, 64 bit assembly both with Intel/Motorola and AT&T syntax, various compilers such as TASM/MASM/inline assembly in Pascal/fasm/yasm, and others.

    I began programming on DOS in BASIC. My second language was Pascal and the third assembly (16 bit at that time). That lasted for many years until I switched to Delphi (win32 RAD with Object Pascal), and I’ve continued through many languages, OSes, and envrionments…until I also got to Java.

    Years from that, I hit Java at the University which would classify as Java-school and here are my 2 cents:

    In most cases I agree with teaching Java instead of C, data structures with double linked lists, circular linked lists, dynamically allocated hash maps, macro preprocessor, bit operations, assembly, processor registers, segmentation, stack, and other issues.

    Why is it good? Because the modern market demands mostly high-level enterprise applications, n-tier transactional systems, business ERP, CMS, e-commerce, web services, RIA, and similar.

    Only a very small percentage of job positions consist of highly specialized offers for C / assembly experts. Typically the job of low-level experts is to program semiconductors, controllers, drivers, kernel extensions, analyze malware, etc.

    I can do both low-level and high-level, personally I enjoy low-level much more, and I say Java is an excellent choice for most Computer Science graduates. C/C++/assembly are suitable only for a very low number of students and if you had to master them to get your degree, my guess it that 95% of CS students would fail.

    Java is good because it teaches state-of-the-art engineering practices. The achieved scale and robustness of Java systems broadly surpasses everything else built up to the date. This is only possible with a disciplined, rigorous implementation as known in other engineering disciplines.

    Low-level code, whether in C or elsewhere, is almost exclusively a mess which nobody but the author can understand. It’s nice that the code can be extremely optimized, development done using the V model, real-time systems, etc. BUT the elements of engineering are almost always missing.

    To conclude, low-level programming is about dirty hacks, horrible code, endless head-aches, crashes, missing mutexes and spinlocks, corrupted memory, memory leaks, NDAs, poor documentation, inability to see the whole picture, and could often be associated with mental health issues over the time, i.e. depersonalization. You will never stay on the surface, but always dive deep in the blue ocean.

    Whereas with Java, you learn sound engineering practices, strictly follow stated rules, import packages, assemble components, think mostly component-wise without much detail, and soon you are done. Easy, highly-demanded, well-paid, risk-free.

    Joel doesn’t understand because he hasn’t mastered both low-level and high-level :)

  59. Mark

    I am currently a grad student TA at a JavaSchool (yes in 2013), and I am often frustrated by what my students don’t know, so I’ve been reading articles like yours to see what others’ opinions are on the matter.

    My general feeling is that the problem with JavaSchools is not that they teach Java, but that they teach nearly exclusively in Java.

    The problem seems to stem from the fact some universities have just gotten lazy, and rather than spending extra time and headaches teaching multiple languages, they decide that it’s fine to teach everything in one intro language.

    Every CS grad should know a minimum of 3 types of languages. The ones I’d suggest are most important are C, an OOP language like Java/C++, and a dynamic language like Python. Functional languages are becoming more and more important, so I would add a functional language as an optional 4th type — maybe I’d say “mandatory” in the next 5 years.

    Note that I used to meet MIT grads who only knew Scheme, which is just as bad as only knowing Java. Probably worse!

    I knew C long before I started college. It’s one of my favorite languages, but I would never exclusively teach C to CS majors. I’ve met non-CS engineers who only ever learned C in college, and although they could do pointer arithmetic, none of them were very good programmers.

    When I took the AP Computer Science exam in high school, it was taught in C++. I think there’s only a very short period of time that the AP exam was done in C++, and I was lucky (or unlucky) enough to be part of that group.

    When I hit college, the first-year intro classes taught Java. I fully understand the reasoning behind that.

    I would not consider my school a JavaSchool though, because it required students to know other languages like C++ and C in later courses. This was often a burden on the instructors (and TAs) who would need to spend extra time outside of class helping students who only knew Java learn C and C++.

    I kind of think that the real JavaSchools are full of lazy profs who don’t want students cramming their office hours with questions about pointers. It’s much easier to tell a student that they should have learned something the previous year than to teach them something new.

    So in my mind, a JavaSchool is a lazy school (like the one I am a grad student at unfortunately). There are also some schools that have very good reputations (because of their research) but are very lazy when it comes to teaching.

    But should Java be the intro language to begin with? That’s a much harder question to answer, because the intro language will largely shape a CS student’s impression of CS.

    Java is a good language for teaching object-oriented practices. Is it the best language? Probably not. But it’s the best popular language for that (well, not counting C#). C++ is also OOP, but it’s not a good language to introduce OOP. Some would argue that C++ is not a good language for OOP period.

    I was reasonably proficient in C++ before college (probably enough so that I could have skipped the intro classes if I wanted to) but I decided to take them since I didn’t know Java.

    I was glad I did because Java teaches very important abstraction and software engineering principles, like the difference between specifications and implementations. C++ blurs this distinction. And with C you have even less — just header files and macros.

    Java can be used to teach you how to properly refactor code.

    I’m not saying that every intro Java course does that properly. I have some doubts that my JavaSchool does that effectively. When I was in college, I supplemented my course with James Gosling’s book, and that really helped me understand the purpose of Java.

    Refactoring code in C is extremely difficult, sometimes impossible, and that’s why you end up with overly complicated Makefiles and macros for every decent-sized C project I’ve seen. C++ is not much better, despite all the theoretical advantages it has (templates, etc.) No one I’ve seen uses C++ in a way that makes their code easy to refactor (it’s possible that I mainly look at bad C++ code of course).

    You learn Java to learn how to refactor code. That is the ONLY good reason to learn Java, in my opinion. But it’s an important reason, and a justifiable one for making Java an intro language.

    Teaching CS students how to refactor code is more important than teaching them what goes bump in the night underneath the hood of their system and how pointers works. Of course, a good CS program will teach students both. Lazy ones won’t.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>