I've yet to find a good CompSci course that adequately prepares software engineers for the workplace. If you find one that has the following [although whether it could be called CompSci I'm doubtful, it's more like Real-World Software Design which is a very different beast].
Computer science is a more theoretical subject that has very real world implications, but is more useful in an academic light. Algorithm design for instance is fantastically helpful to software engineers, but isn't really directly helpful to the consumer. For instance, knowing how to build a quicksort algorithm, or understanding linked list traversal is not really so useful in today's software engineering environment - of course, understanding the theory is helpful for choosing the right tools for the job, don't get me wrong. As developers, many of us rely on the output of the computer science world to further our development tools, in fact, without them many developers would be left floundering, but put a computer science graduate in front of a user and get them to design a meaningful piece of software for them and the academic intellect is going to fall to pieces because the two speak completely different languages.
A much more useful course for software engineers would include as many [and possibly more] of the following components that I can think of off the top of my head:
- Programming Language - basic program flow, paradigms, syntax etc. This is mostly taught pretty well, so I won't stick on this one too much. Although it would be helpful if a few completely different classes of programming languages were taught - for instance, I learned C, Pascal and VB 3(? I don't remember the exact version). It would be way more helpful if programmers learned at least one functional language, one imperative language, one declarative language.
- Debugging - When writing nTier applications [which many/most real world applications are], it would be useful to be able to figure out where something is going wrong, right down to the protocol level if necessary. Analysis tools such as WireShark are useful for this.
- Communication Devices - XML, XQuery, XPath, XSL, XSD [as these seem to be used so extensively].
- Relational Database Design - This is taught reasonably well already.
- Relational Database Performance Tuning - Just designing the tables isn't enough, knowing when it's appropriate to index certain fields and when it's not is also important and doesn't seem to be covered in a lot of courses.
- Data Normalization This also seems to be taught reasonably well in a lot of cases. Although most students seem to come out into the real world spewing the theories they were taught - "thou shalt always use Boyce-Codd Normal Form" etc, without actually thinking about the implications of those theories. Sometimes in the real world we have very good reasons break the rules.
- Query Optimization - Writing basic queries often seems to be at the outer limits of graduates comfort zones, optimization should be taught. Also, tools like query profilers should be taught to help students debug performance issues with applications.
- Stored Procedures/Triggers - I've yet to come across a student that could write a stored procedure or trigger or use either one effectively. Selects/Joins/nested Selects seems to be the limit of what is taught when it comes to query design.
- Basic Algorithms - This is taught farely well in my experience, but a lot of students don't appear to have any idea how to decide which algorithms apply to which situations without being told "using such and such an algorithm, solve this problem". It would be useful if you could say, "solve this problem", and they're like, okay, I've got a fleet of algorithms that would be useful in this situation, this is the best because of x, y or z reason and here is how it can be applied to provide a solution.
- Recursion - I've yet to find an approach that can teach recursion, it seems that either you get it or you don't. One of these days I'll find a good metaphor that will make this understood by even the most basic programmer.
- Abstraction - This seems to be something that a lot of courses gloss over despite being one of the core tenets of OOP.
- Code Refactoring - Knowing when to refactor and almost as importantly, when not to.
- Code Reuse - It seems that a lot of courses are spitting out cut/paste monkeys - this is not what code reuse is supposed to mean!
- Source Control - I didn't learn about source control until my 3rd or 4th programming job, and I don't know a single software engineer personally that learned source control as part of their course... why is that?
- Backup and Restore - I've not heard of any courses that teaches this. How many beginner programmers have lost all their work because they just didn't think about backing it up? I know I have in the past - not recently though. It's not that I was ignorant of backing up but as the saying goes "it'll never happen to me". It will happen to you, and guaranteed it'll be right before you have to demo everything you just lost!
- File System Maintenance - Okay, some of the courses gloss over this briefly, but a lot do not.
- Writing good quality design specifications - This always seems to be provided as a brief of coursework, but the student is rarely asked to design this themselves. Writing a scope of work and understanding document templates seems to be far outside the scope of most software courses.
- User Documentation - Users don't think like you, handing them software that is "self explanatory" or "so simple an idiot can use it" will blow up in your face. There's a famous saying that "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the universe is winning". Write user documentation that an 8 year old can follow - it might seem painful to write it, but once it's done, and forever more, you will thank yourself.
- Technical Documentation - i.e. It would be useful if students could use Sandcastle, nDoc or any documentation tools.
- Test Planning - designing the tests and software that allows for testing. nUnit or similar would be a great tool to teach on software development courses. In fact, teaching any testing framework would be better than not teaching any... as seems to be the case.
- FAT/SAT/UAT Testing - It would be helpful to understand various testing scenarios in the real world such as sanity checks, factory acceptance tests and user acceptance testing. Sign off for your software is as critical as developing it. If you don't deliver what the client thought they were getting, you're not getting paid - no matter how brilliant your solution is on a technical front.
- Software Architecture - understanding the different components of real-world n-tier applications, advantages and drawbacks of using them.
- Interaction with users - Maybe this isn't really computer science, but learning how to talk to people that aren't often on your wavelength and don't think the same way you do, this goes with communication, but is really something developers need to be aware of.
- Common Sense - Ding, ding, ding, ding - there are a lot of programmers out there without an ounce of this! The courses are designed to prove that you can think for yourself, I don't understand why so many graduates come into the real world thinking that all they need to do is apply the rules they were taught blindly without thinking about reasons and implications. I'll repeat what I said earlier - in the real world we sometimes find very good reasons for breaking the rules. We don't follow them blindly, and we don't break them blindly either. Software development is an art, and like all arts we must know when we can and can't and as importantly when we should and should not break the rules. As a graduate, you've learned the rules, you've proven that. Now you need to do what the course was really trying to teach you - apply what you've learned to think for yourself.
- Listening - You'd be surprised how many times I see code written because the developer "thought they knew what the customer wanted" instead of actually listening to what the user is saying and understanding their actual needs.
- Understanding - Goes hand in hand with listening.
- Communication skills
- Talking to the technically inept - i.e. a large part of your user base
- Project Mediation - selling your ideas to those writing the cheques
- Prioritization - how to decide which features are more important than others.
- Budgeting - time estimation
- Time Management - how to get things done on time when everyone around you is impeding on your time and has no care for your deadlines. Just like when all your friends are wanting you to go to the pub for a pint or ten when you've got a piece of course work you haven't started yet due in by the end of the day tomorrow.
- Scope creep - when to say, no, that's not in the spec/budget.
And even if you did manage to learn all that in your course, I daresay you'd still learn more in three or four of months internship at a software development consultancy of a decent callibre than on the whole course. I learned more in my first 6 months after my bachelors degree than I did in my whole 3 year course. Admittedly I'd have fallen flat out my face without many of the things I learned on that course, but there was so much that was taught needlessly that could've been replaced with far more useful content.