What Is Computer Science?

Some guy took a crack at answering that question. Or more accurately, he claimed to take a crack at it; he never actually got around to answering it. It occurred to me the questioner does have a point, though.

What is computer science, anyhow?

The first problem you have in answering this question is that the confusion is "real", that is, since you really will get different answers from different people, exactly what constitutes "computer science" at a given university or college will vary. That's unfortunate and unavoidable.

I think the second basic problem is that there is a lot of overlap in the curricula, and if you don't first factor that out, it's easy to get confused by it and start mushing things together.

The Disciplines

I'm going to talk about Computer Engineering, Computer Science, and Software Engineering. Few if any schools have separate programs for all three so in practice you'll find these intermingled freely.

Computer Engineering is about the hardware of computers, starting at the transistor level and working up to complete hardware devices. In addition to the focused engineering curriculum, you'll probably study enough physics to have a basic understanding of how those work, and you'll study enough calculus to understand signal processing, including a healthy amount of your newest friend, the square root of negative one.

Computer Science is the study of the properties of abstract computation, and the theoretical capabilities of abstract machines. Theoretically, computer science could have been done long before any hardware could have been built to support it, and in fact there have been cases where the math/science has run far ahead of engineering. It often needs to be filtered through Software Engineering to be "useful", but we'd be lost without these theoretical backings.

Software Engineering is the study of how best to assemble programs in a manner that is cost-effective, low on bugs, and in accordance with the requirements of the customer. Of the three, this is the "programmer" that most people think of, although a full Software Engineer will also have studied certain engineering practices, and will have to learn how to deal with customers and clients as well.

Herein lies the major problem of defining "Computer Science" in the sense of what shows up in University: Almost nobody really offers a Software Engineering program. As near as I can tell, there is often a single "Software Engineering" course that will generally teach very outdated and heavyweight methodologies, quickly mumble something about requirements elicitation, and move on. What you get in practice is a sort of smudged degree with a little bit of everything in it.

As a result, if you read the above list and want to be a "Software Engineer", the way you do that in practice at a University right now is to take the Computer Science track and teach yourself the other Software Engineering stuff on the side from books and programming projects of your own. If you really want to do this well, it's actually a very rough road to travel as you're basically double-majoring; you really need to enjoy programming for this to work. That would be another post, which I'll try to assemble if there's an interest, but this one is getting long enough.

For reference, this is my point of view; I came from a computer science course with limited engineering school components, and significant self-taught and work-taught software engineering and programming. I have heard tell of some official "software engineering" courses, but I can't speak to those as I've never been involved with one, although if I had to guess, I'd guess they're still mostly Computer Science, just with a few more not-very-good Software Engineering classes thrown in. Software Engineering is fairly hard to learn in a school environment, I think you can only really learn by doing.

The Core Curriculum

Each discipline may need these for different reasons and have slightly different emphases, but they all need them:

  • Discrete Mathematics: Including the study of basic boolean algebra, set theory, and possibly some simple graph theory. If you're cut out to be a real success in any of these programs, you really ought to find this part very easy, at least conceptually. (It's OK to be a bit bothered by some of the larger problems; I don't think anybody ever manually resolves these expressions anyhow. But if your mind is blown by the idea of the empty set, you might be better off in another major.)
  • Basic Data Structures and Complexity: This will introduce you to the array, linked list, hash table, a collection of trees, and hopefully graph structures. If you're going to be in CompSci or CompEng, you should walk out of this with enough understanding that you feel like you could composite these structures as needed, not just slavishly use what you were taught and nothing more. This is also where you will be introduced to computational complexity, as you discuss the costs of various operations across these various structures.
  • Basic Computer Internals: This covers the basic operation of computers at a low level, at least discussing assembler (hopefully you code in it a little), caching, memory speed hierarchy (more important every year), and other things. This may involve programming in C, very simple C++, or assembler. This should focus on real architectures (albeit simplified ones), not theoretical ones.

Again, I reiterate that while each discipline has its own spin on why those are needed, the need is shared by all three. For instance, Computer Engineering needs to understand the internals of the computer so they can implement it, where as computer scientists need the basic programming skills to implement their algorithms on real machines.

Computer Engineering

You should take this with a grain of salt, since this is the curriculum I'm least familiar with in practice, and I'll accept comments on this with gusto.

A Computer Engineer will continue on from the base to study the low-level aspects of a computer, from the point of view of implementing things like "interrupts" in the hardware. You'll learn a lot of physics the other two disciplines don't need. (Many times, one of the consequences of the "smudging" of these courses in practice is that the other two disciplines will also be forced to learn these physics, and they often have a hard time understanding why, though more knowledge is never a bad thing...)

You'll spend some time implementing hardware devices, both in simulation and hopefully at least once in real circuitry. You'll hopefully be exposed to at least one of the major domain-specific languages used to create these devices, and I would also hope you'd have some exposure to testing practices.

You'll probably also cover certain wire protocols and the implementation thereof. (One of the places where I suffered the most from the discipline smudging was in my Networks class, where we spent weeks talking about level triggered vs. edge triggered and certain error-resistant encodings on the wire and a whole lot of other things that as a programmer, I just wasn't that interested in.)

Given the smudging of the disciplines, the remaining time is probably filled in with cross-disciplinary study from Computer Science. Believe me, as simple as the previous few paragraphs sound, that's plenty for a four-year degree to cover.

Software Engineering

As I said previously, Software Engineering is something you really don't learn in school. I had a "Software Engineering" course, and at this point, several years of experience later, I can safely say that I disagree with nearly 100% of what I was taught in that course.

Software Engineers are primarily concerned with serving customers in a cost-effective manner with high-quality code. Software engineers are the primary target of the Programming Wisdom online book I'm writing, which still won't cover the whole of Software Engineering but I believe will cover a portion currently filled only in a very fragmentary way by a series of online essays scattered over numerous websites.

The best way to learn Software Engineering is by doing it. Get involved with an Open Source project and seek out people writing about software engineering online. If you're interested, you'll find them.

Perhaps someday we'll be able to have an official curriculum for Software Engineering, but it's going to be a while yet before we stabilize on a true best practice that can be taught, as discussed in the aforementioned book.

While the only way to learn is by doing, it should be pointed out that there are significant chunks of Computer Science that are still very useful and practical in your hands. Computer Science develops many useful algorithms you can implement, can often identify "underlying problems" that you would never understand without it, and just generally has a lot of valuable things to say. It's true that you can learn how to program without any understanding of Computer Science, but I can assure you that I can tell when a programmer doesn't understand it; it's hard to verbalize how, but it shows in the code. To be an excellent programmer absolutely requires a good understanding of computer science. No exceptions. If you don't understand compilers or databases or complexity measures or error correction or a whole host of other things that fall under the Computer Science rubric, then your code will most definitely suffer for it, in ways you'll never even know because you can't even see the problems properly.

There's also some cross-disciplinary topics of interest that would fit here if they fit anywhere, although universities typically don't do more then mention these things, like User Interaction/Usability (collaboration with Psychology). Also, every user has their own needs and you will frequently find yourself learning about their domain; for instance, while I'm nowhere near a real accountant I know more about accounting than most people. Dilettantes make for good software engineers.

Computer Science

Computer science is the study of computation itself, and then the study of trying to achieve certain practical goals with computation. Computer Science is technically a branch of mathematics, and as such it can be done entirely without real computers, although the value of that varies from sub-discipline to sub-discipline.

There is a continuum from abstract to practical in this discipline, even after I have separated out Software Engineering. On the abstract end, you have people that differ from mathematicians only in which building they work, on the other you have theorists who have to actually implement their work to learn more.

On the abstract side in school, you will learn about:

  • Computability: You will learn about several models of computation, their limitations and capabilities, and why we still sometimes use the "simpler" machines. You will learn about the famous Turing machine, which is useless as a real programming model and you will learn why it is the most powerful computer that can possibly exist (and why that is no contradiction). You will then learn that this machine still has limits, how carefully we can define these limits, and how often we encounter them. Goedel's incompleteness theorum will probably make a cameo appearance. If you have a poetic soul, this will all blow your freaking mind. No joke.
  • More Discrete Math: Actually, I can't guarantee this, but you should learn more than I described above. You really need to cover the basics of graph structures, and you should end up learning more about data structures than the Computer Engineers really need.

On the more concrete side, there's a whole slew of things that vary in practicality, but all have significant mathematical components to them. This isn't even close to a complete list: AI, Machine Learning, Database theory, Compilers (if at all possible, don't miss this one! very practical), networking, several cross-disciplinary topics like Scientific Computing (working with floating point numbers is surprisingly tricky), signal processing and computer multimedia, programming languages, and within each of those, several subdisciplines. What makes this Computer Science and not Software Engineering is that often implementation will be of secondary importance in this context.

If you haven't already taken the courses, you might still read those as practical, and it's true that the programming and the computer science heavily inform each other and there are "Software Engineering" incarnations of many of those things. But Computer Science is more concerned with the math; for instance, "databases" is not about SQL per se, but rather about Relational Algebra. Making a practical implementation might still be "Computer Science", but it's often not the primary concern. For some more examples of computer science, see Markov Chain.

Probably the primary reason that implementation is secondary is that the mathematical properties that Computer Science is frequently interested in show up best in abstract models that can't be truly realized in the real world. The aforementioned "Turing machine", for instance, contains an infinite memory store, which nothing in the real world does, yet many results depend on this.

That's what computer science is; it's the study of what computers can and cannot do, with a focus on theory and proving things about that theory, and only a reduced focus on implementation. If you want to build the awesome Artificial Intelligence that eventually exterminates the human race, you'll want to be in Computer Science, because the primary problem stopper on that right now is that we don't know how, even in theory. If your interests lie in creating the next social website hit, you'll want to be in Software Engineering. (But there lies a great example of where Software Engineering needs to be informed by Computer Science, as the study of how large reputation networks behave is a Computer Science concern.)

Ultimately, the real question is not "Will I become a Software Engineer or a Computer Scientist?", but "What is the balance that will best help me attain my goals?", because you can't really be effective at either without knowing a bit of both.

(Obviously this is a rich topic and given the differences between programs, probably there is no one person in the world who can really give The Final Answer on this topic, so comments gratefully accepted. Points made may get fed back into the post.)