What would you recommend to increase the quality of computer science education in university programs?
Thats a big question. Let me first narrow the scope of my answer to those who will eventually go into industry and take part in software development in some capacity. Let me also emphasize that Im not alone in wanting change and that work on improvements is going on all over academia.
This work takes many forms and goes in many different directions. It will take time before we know what really works, what is the right mix of subjects and techniques. Many, many people and organizations are trying to improve the CS programs. I certainly dont claim to have the one true answer, but to make my opinion just a little concrete let me describe what we do locally.
In Texas A&M Universitys Computer Science and Engineering department, we just revised our undergraduate program. In addition to the aim of general improvement of quality throughout, we aim to be more responsive to the needs of the many students who go to industry and to the needs of the industries they go to. The approach of working backwards from the desired end results was applied repeatedly. For example, a graduate should be ready for a first job and after the first two years a student should be ready for a first internship.
In addition to the classical and essential foundations of computer science, such as algorithms, data structures, and machine architecture, we include repeated exposure to practical topics and projects. Repetition is necessary because students forget and integration of theoretical and practical parts is needed to create a balanced view. Im very keen to fuse the theoretical base with practical skills. I see computer science as ideally an applied (engineering) discipline and see too many people disregarding either the theoretical or the practical parts.
We adopted my book/course as the introduction to programming/software for our freshmen. It was originally designed for Electrical and Computer Engineers and is not a classical CS 101 text. Similarly, we let the EE department teach the hardware subjects to the CS students. In the second year, we add two more languages to the students tool chest (currently Java and Haskell). You cannot be a professional in the IT field while being comfortable in only one language. Projects with a software development focus appear repeatedly. In addition to specialized courses, there is a project in the first year programming class, a programming studio in the second year, and a capstone project in the final year.
In the last two undergraduate years, students add a specialization (tracks) to a common core. Examples are Algorithms and theory, Systems, Software, and Information and intelligent systems.
Is there any way to teach the art of programming, as opposed to the craft? Is this aesthetic skill teachable?
Actually, I think the ultimate aim is to make programming more of an engineering discipline, more mathematical or scientific; craft and art are both needed, but there ought to be a scientifically based core on which people can base their craft and art. Software design and implementation is more than a craft; there is more math, science and engineering to know and apply than is customary for fields we call crafts. Incidentally, I find it appalling that you can become a programmer with less training than it takes to become a plumber.
I think aesthetics can be taught to many. Mostly it is a case of repeatedly showing students good examples and explaining why those examples are good. This takes time, years. I would like for programmers to present portfolios of their work, much in the way artist (including architects) have to. I dont think everyone is cut out to be a programmer, just as not everybody is cut out to be a musician. Thus, we should not claim that program aesthetics is teachable to everybody. Drawing from the experience of crafts and arts, we should consider instituting a system of apprenticeships.
Some critics of university CS programs, notably Dr. Dewar at NYU, say there's too much emphasis on Java in the classroom, that creating applications with pre-built Java libraries isn't rigorous enough. Do you agree?
Basically yes, and Joel Spolsky (Joel on Software) said it stronger still. I have had direct and specific requests for students who understand machines and systems; not Java from several major industrial players.
Im not sure how much of the problem is Java itself and how much is the emphasis on using libraries, though. The trouble is that Java has in many places been used to dumb down the curriculum while at the same time increasing the apparent level of delivered goods. It is good to be able to (quickly) build new things by calling libraries, but often thats not a skilled, challenging job. If thats all you have seen, you are completely lost when faced with a job for which a pre-packaged solution does not exist. This is just as bad as trying to build everything from scratch yourself. I think the problem is one of attitude, more than an issue of programming language.
Education should prepare people to face new challenges; thats what makes education different from training. In computing, that means knowing your basic algorithms, data structures, system issues, etc., and the languages needed to apply that knowledge. It also means having the high-level skills to analyze a system and to experiment with alternative solutions to problems. Going beyond the simple library-user level of programming is especially important when we consider the need to build new industries, rather than just improving older ones.
A specific critique of the Java-based approaches has been that not dealing directly with memory is harmful to students mastery of data structures and leads to programmers ignoring resource usage issues, which is damaging when a program needs to deal with large amounts of data relative to available memory size. Im not a fan of undisciplined pointer use and spaghetti data structures; I prefer data to be presented with rigorously specified interfaces (for starters, think STL).
However, I agree with this specific criticism to the extent that in my own teaching, I emphasize memory layout and size of objects. I also use pointers and iterators to express data structures and algorithms because that seems to express the fundamental ideas more directly. I think that the distinction between what points and what is pointed to (prominent in C and C++) is fundamental and important.