Registration time -- what courses should I take?
As one of the interns was heading off for his final year, we talked about what courses he is taking. There’s a general question of “what computer science courses best prepare you to be a professional programmer [at a place like Microsoft]”.
I admit to having strong views on this topic because I think that like all departments in universities, computer science has to teach the core of the discipline but is also trying to attract students, look like a hip cool department, differentiate itself from other CS departments, and also has a little bit of indulging in the whims of senior faculty. This means that within the scope of talking to your computer science department advisor and other folks in the department (students and faculty) you are getting a less-than-totally-objective point of view.
That said I think that it is important to understand that university is a time to explore and a time to test your own limits. So there is no right answer about what courses to take. Your future success will not depend on having taken a specific set of courses in those specific four years—after all learning is a lifelong experience, or put another way life is a long learning experience.
I always loved the way the Cornell catalog described a major since it reduced the stress in picking a major (I ended up picking two). Here is what it says now:
Majoring is an opportunity to study what you love most and do well - regardless of what you or others think might be "most practical." Whatever your major, through it you will hone your mind and imagination. You'll learn to think and write critically, skeptically, and imaginatively; you'll learn to recognize and address important questions; you'll learn to create and weigh evidence and make decisions about likely truth in the face of incomplete data; you'll confront basic questions about human life and mind; you'll develop your intellectual and aesthetic sensibilities. These skills will stand you in good stead in any career. You'll acquire them more thoroughly and usefully through studying a subject you care about.
The connection between major and career is mysterious. It is certainly not direct. Your major may have some relation to your first job, but not often to a whole career.
Finally, your major doesn't define your character or your life in any important way. It matters a lot what you stand for, whether you commit to a partner and who that partner is, whether you raise children, whether you work for a non-profit or for-profit organization, whether you live in a city or a rural part of the world, whether you work for a large organization or a small one, what you do with your leisure time. What you major in does not matter in any of those fundamentally defining ways.
So follow your mind and your heart in deciding on your major. It may be your last opportunity to indulge yourself so wonderfully.
The connection to your career is the interesting point. I can’t tell you how many folks I have talked with take one senior level project course and are convinced that they want their career to be based on that class (especially if they got a good grade). Computer software is a *huge* field so don’t get too fixated on your first experience, no matter how positive. As someone who works on Microsoft Office I can say that since I have yet to come across a course in university that is about writing a spreadsheet application or a presentation graphics tool (though I studied compilers and databases as an undergraduate and graduate). You might discover your life’s avocation in that class, but be open minded!
I am a strong believer in using four years to master the fundamentals of computer science (if that is your chosen major). For the most part, in the departments I have visited or looked at (and employees I have spoken with) the first 2 or 3 years of most CS coursework are about the same: basic programming (2 semesters), data structures, algorithmic theory, discrete structures, operating systems, computing theory. Some schools pull a couple of these topics together into a single course and others spread them out.
After that there are varying requirements by department. Usually the requirements for the major include one or more “big project course”. This post is really about some thoughts on choosing those electives because in many ways it is these electives that provide you with a depth of knowledge about a specific topic that can last your career or can just be a fun time your senior year. Computing is really a field that has a lot of change, but that change is based on a few core concepts that have remained pretty unchanged for at least 30 years. I think the courses that show you the depth of material that form the basis of those concepts are best.
Another characteristic to look for in courses is how the professor will spend the time—if you are taking a course that requires you to learn C programming (that you don’t know) and the first 2 weeks are spent with lectures on learning C, then avoid that class! The reason is that your first couple of years should have taught you the fundamentals that should make it easy to learn a new programming metaphor in short order and you should not use up the valuable class time studying syntax. As a first semester student, I remember the professor saying “We will teach you PL/CS, a variant of PL/1, at Cornell—you will never use this language anywhere else but do not worry. As a computer scientist you should not think about ‘programming in a language’ but realize you program into a language”. I really had no idea what that meant, but years later I took it to mean that I was supposed to learn about algorithms and how I express those algorithms is not really the long term knowledge. Sure enough over my time at Cornell I used PL/CS, C, Pascal, Fortran, IBM 360 Assembler, Objective-C, LISP, and then in graduate school I used SmallTalk, Modula, C++, and M – all a veritable graveyard of languages. The concepts I learned are what carried me through and I never spent time in a classroom learning a language (or an operating system). If you think that the course is teaching the language itself then it is likely more of a training class than a computer science course—that’s feedback for the prof!
I’m often asked if you need to know C++ to work at Microsoft, or conversely if you learned Java can you ever get a job at Microsoft. The answer is “if you know the fundamentals then it just doesn’t matter what you learned in college”. Over my time at Microsoft we have mostly used C++ and C# to write our code (with HTML and script of course) but college students interviewing/interning have gone from Pascal to C to C++ to Java (with some Scheme in there as a long running theme) for the intro courses. We don’t mind what you know and expect you to move between tools over many years of your career.
My favorite senior courses [I have a feeling this is a post that I will be adding to as I hear from you!] that prepare you for a career as a professional software developer are below. One thing to keep in mind is that you want to write the code that goes with these courses and not just read about them, so if that “practicum” is an optional part of the class then by all means enroll!
Compilers – any course where you write a compiler that does lexical analysis, parsing, translation, code generation is a great long term bet. Although there are great tools for developing languages and compilers, it seems that nearly every project developers a “little” language and has to deal with user input from a command line or text stream. The advent of XML is only making this all the more important an area. There is often a course of “programming languages” which is interesting, but generally just a survey or compare/contrast of languages like the list above. I do not think this is a very valuable course. Looking at the textbook used, generally the book should be one like Compilers or Crafting a Compiler and of course you should write a lot of the code.
Operating Systems – OS coursework is really fundamental to being able to understand what goes on when you write code. I think for the sake of all your future users you need to understand how virtual memory, disk I/O, process scheduling, and file systems work. These concepts have been very constant over a long period of time. Like programming languages it is not important that you learn a specific OS (like Windows) and this is certainly not a course in learning about the command line tools in an OS, but this is a course in learning about the science behind those core concepts. One of the core reasons an OS course is important is because if you ever want to write performant code you really need to understand how an OS works—a common example of this is that until you understand virtual memory and disks you probably think that more processor speed will help your program run faster! If you have a chance to bootstrap an OS from scratch or to write a big subsystem then go for it. A good textbook in this course is something like Modern Operating System Concepts or Operating System Concepts (two different books with similar names).
Databases – Databases are fundamental to just about any real world application. The specifics of databases that are core to understanding the technology are really about understanding how the relational database model works (aka “SQL”). This is a bit tricky because you can get into a course that is about teaching the ins and outs of the SELECT statement. Don’t worry about that as much as you learn about how the whole model or “algebra” works, about the role of queries and query processing, how performance is impacted by your data structure design, etc. If you have the chance in the course to write a SQL database yourself, not just use one, that is excellent. The book being used widely now is by Ramakrishnan.
Graphics – This is always a super popular course and probably the course most responsible for folks thinking “I want to do this forever”. It is easy to make this course fun and it definitely resonates with those who remain gamers throughout college. The techniques learned are really awesome and the lessons apply to a broad set of problems. Most students are amazed at how much calculus is involved in this class so be careful. This is probably on the fun side since the fundamentals of graphics are pretty unique and are not broadly applicable. But have fun. Computer Graphics is the classic book in like its 100th printing.
Networking – Of course the world is all about networking. There is a ton to learn around the fundamentals of computer networking starting from hardware through the communication and application layers. These courses are often structured to walk through the networking “stack”. Tannebaum’s book is a classic but there are many books that do this well. Of course this subject will be an in-depth study of TCP/IP and probably not dive into other systems which is ok. Again this is a course that can be theoretical (good) or a bit too practical (if you exam asks you what arp and ping do then it is more like an MCSE certification).
I will stop there and see what folks say. I will offer the following as well. If you have a chance to work in a group project then by all means do. Life is a group programming exercise so you will almost never work by yourself. But when doing so be sure to pull your weight *and* be sure that the group works as a group. It is too easy to divide up the work and then speak at the end of the semester or let one person do all the work (that’s the one we hire for development!) There is often a course in “software engineering” that is specifically about a group project. This can be fun, but I would encourage using the time on one of the above topics first and then take a pure software engineering class.
If you have a chance to participate in undergraduate research that involves writing code then go for it! It is an awesome experience. It is not a substitute for the above fundamentals but it is a great thing to do and unique to university. By the same token, courses that are graduate level or impress you with current papers and knowledge are fun, but be sure to take those *after* you get the fundamentals. You can’t learn about OS fundamentals while at the same time studying advanced parallel programming.
I realize there is some strong opinion here. But keep in mind there is no one path to success and certainly no one course that makes the whole difference. Let me know if this is interesting and what your thoughts are!
PS: Again, I used Amazon but use any bookseller of your choice and I have no commercial interest in any of these books.