The Software Engineering part is done badly because the slope is too abrupt and ends too quickly. The Java-based curriculum invariably ends up teaching OOP concepts within weeks (if not to start with) to someone with no concept of program flow, variables and functions. From my experience as a TA, I'd say 90% of students who haven't programmed before end up utterly confused about the order of execution of the various bits of code in a simple Java program with 3-4 classes.
The few people who survive this abrupt slope with an intact desire to learn more CompSci find that the slope ends too quickly. There is no further discussion of issues that are crucial for industrial Software Engineering: debugging techniques, version control, code repositories. Instead, the sophomore abruptly has to choose between a rock and a hard place: either a course in C, leading to an honours thesis in Systems; or some math-y courses leading to Theory.
The C course is a frustrating experience, requiring the student to un-learn a lot of the concepts learned in the Java intro courses and to learn instead to tread carefully on a landscape suddenly filled with inexplicable bugs. But this is actually the more accessible course, as the theory courses require a mathematical ability that the majority of potential CS majors simply don't have (or even had any inkling that it was required).
I think any intro course should begin with an explanation of very simple architecture concepts (program counter, memory, hard disk) and spend a good amount of time drilling the basic concepts (variables, loops, function parameters, function return values) and basic debugging techniques. In the second half of the semester, while the students work on a large project to practice these skills, spend the lectures to give them a broad survey of the major: architecture, algorithms, programming languages, OS, theory of computation.
This perfectly mirrors my experience.
College is also set up for majors to be chosen without any understanding of those particular areas of study in high-school.
So, yes, your intro class should be for kids with no former compsci exposure, just like every other major your college offers. You then allow AP compsci students to waive some of the intro classes.
Of course, the real question is why should the kid pay money to hear this guy when, if the kid already has an interest and some knowledge of CS, learn with MIT open courseware and iTunes University?
Do you think CS professors are the best at presenting/explaining the material? I believe it depends on the professor.
Music is much more difficult than compsci. In addition to the mental, you have to hear/listen, and possess excellent muscle coordination.
I think his point is that no other major starts from scratch. The standard first-year math course is calculus, which builds on algebra, geometry, and trigonometry. First-year English and history classes are very much like high school English and history classes. First year classes in most subjects actually provide a misleading degree of continuity, with second or third year classes suddenly taking a college-level turn: proving theorems, writing seminar papers, etc.
To make an analogy with math, imagine if a student's prior exposure to math was just basic arithmetic to calculate change, scale recipes, and figure out how many weeks until their birthday. Then they go to college and take an "intro" course that covers all of high school algebra, geometry, and trigonometry. They're floundering because of the pace of the class, and they look around and see that about 20% of the kids are utterly bored and itching to get to trigonometry, because they already learned algebra and geometry in their spare time in high school.
That's the situation college CS programs find themselves in. How in the world do you take someone with no prior exposure to one of the fundamental skills of the field and, in four years, turn them into someone to whom it would be appropriate to give a college degree in computer science? Programmer isn't just a neat and useful skill. It's the skill by which computer science is traditionally explored and learned -- we don't know any other way except mathematical theory -- and it's the skill to which computer science knowledge must be wedded for a computer science graduate to make themselves useful. (Not every computer science graduate needs to be a programmer, but they all need to program, unless they also have a degree in another field or plan on going to graduate school.)
You don't, unless they have the passion, drive and natural aptitude. The author makes very apt comparison to music and expresses that there's really no way out of the conundrum in that field, but wants to find one for CS. Just like music, if you want a university-level program where anyone can come in and succeed in a limited amount of time, you have to rely on high school curriculum to provide the foundations.
The problem is perception. Given a standard high-school curriculum, it's obvious that a student won't succeed in a university-level music program without becoming specialized in high school, but it seems like students should have the foundational knowledge to succeed in a university-level computer science program. Unfortunately, it's just simply not true.
The author says this in the comments:
I don’t want to effectively require students to choose early in high school whether or not they want to study Computer Science in college. While computing skills are clearly beneficial for everybody, I hesitate to make the claim that computing courses are more worthy of limited curriculum time than other disciplines such as foreign language.
Unlike the author, I don't hesitate to make that claim at all. People often lament that students graduate high school knowing basic history, algebra, physics, biology and the like, but don't understand how a credit card works, what happens when they push the gas pedal in their car, or most importantly, simply how to think logically and critically. Shifting part of the mathematics curriculum to focus on logical thinking, regardless of whether it's presented using programming or not, would go a long way towards enabling success in fields like computer science, and would make graduating high school students more well-rounded to boot.
I agree with you about teaching programming in high school and lower grades. Programming would be much more beneficial for most kids than advanced algebra, trigonometry, and calculus. Average people today need to understand their computers, their taxes, their employers' benefits policies, and other logical and algorithmic systems much more than they need to understand radio waves, flow rates in pipes, or falling objects. The standard curriculum should include some programming at the expense of sequences and series, trigonometric identities, possibly any math beyond geometry, basic algebra, and using a calculator's sine and cosine functions to compute the sides of a triangle.
(Actually, I would be hesitant to suggest such a thing because many college-bound kids need as much math as is currently offered and more. If a kid is going to take freshman calculus in college anyway, you might as well teach him some programming in high school instead of pushing all the way through a math class he's going to retake in college. On the other hand, every high school needs to offer a complete calculus course for kids who will be able to ace the Advanced Placement test and skip calculus in college. There are so many ways for educational reform to go wrong, and I have so little faith in the people who would carry it out, that sometimes I'm glad the system is unlikely to change significantly any time soon.)
That's not true (at my university, anyway). You can skip the first two semesters of the CS curriculum with a 5 on the AP CS AB exam.
I personally chose not to use most of my AP credit to give myself a relatively easy first year during which I instead developed lifestyle/social skills. One of the best decisions I ever made.
1. The commenters seem to imply that java is probably not the most appropriate language for cs1, where syntax considerations often overpower practical concerns.
2. Bright students that 'get it' are not the baseline, they're the exception. It's the other, intro level students that the class/recitation/curriculum should be catered towards.
3. Many (if not all) fields of study 'get hard' in college (i.e. physics, pure math, etc). The problem in this case is one of students being improperly tracked (i.e. curriculum failure).
4. Intro CS courses vary wildly in expectations and ideology. This set of courses seems to focus on 'practical' considerations that are probably better suited to a separate 'software design' course. It's possible that this 'survey' is actually too broad and not focused enough.
5. The music analogy is cute, but fails to consider that intro cs courses typically only succeed (and attempt) in getting students expressive (i.e. jibbering toddler) rather than elegantly fluent. This is why many post-cs1 students generally can solve problems using their new toolkit, but often solve them naively (it's like a toddler that says the wackiest things)
6. Confusing "programming ability" with "computer science" is problematic overall, i don't know that anyone would want to spend four semesters "programming" but i've know a bunch of people that enjoy the theory=>pracitce :: state machines => regular expression 1-2 punch. You can do quite a bit of fascinating cs in a logic/philosophy class as well as in a complexity theory class without ever touching a computer. I know, heresy, but it's true.
I think finally, the issue here is confusing "computer science" with "software engineering." I think java's a great language for software engineering, it's got all the stuff builtin to teach those concepts, but as a language for sketching, i'd probably use python.
And this is a hard question to be confronted with in any case: what are you teaching and why are you teaching it? Neither of those seem to be fully addressed in the author's description of cs1/2.
If you follow the analogy, the best programming languages for CS101 will first, minimize the amount of technique required to accomplish simple tasks. Java is out, "hello world" already introduces the concept of classes, static methods and access specifiers. Ruby, python, and plenty of other dynamic languages look a lot better, "hello world" is a single statement/expression. Second, the layout of the keys should be intuitive, consistency and simplicity in syntax/semantics is often cited as one of lisp's strong points with regard to it's suitability as a teaching language. If you want to play a scale, you just need to hit the keys in order.
To get competent in programming seems to take about two years. To teach computer science/software engineering concepts in any form of depth (besides a simple, 'yo, here's X, here are 5 datapoints about X for the test', requires knowing something about programming. That means that to seriously teach data structures, algorithms, software engineering, computer organization/architecture, programming languages, all carries with it the pre-req of years of work.
So students have massive issues!
I believe that it is indubitable that the best way forward is to have an optional programming track added to high school education. But we've all heard the high school programing-teacher horror stories. Add to that the idiocies perpetrated in the name of 'students must know computers' (Oh, look, Little Bobby Can Use Word). So that's probably not realistic.
What might be realistic is sketching out a college curriculum that uses a step function in terms of winnowing out students. E.g., the spring courses are hard, the fall courses are easy. That would help move things along better. Yet, the fundamental issue is that a 4-year college degree seems to be insufficient to prepare students from knowing zilch to being hireable, without some pretty heavy investment on the student's part.
Outside of software and music, I have never heard of this scenario for any college degree. I hope that I am wrong, that these two majors are not unusual.
CS 2 should not be dealing with inheritance, polymorphism, or object-oriented design. These subjects are advanced not because they are difficult, but because they are useful abstractions that help solve large-scale organizational problems that students have never faced. They are important aspects of programming discipline but are useless if you don't understand the underlying tools to begin with.
Instead of trying to teach design and high-level abstractions in CS 2, the focus should be on how systems actually work. You should be removing layers of abstraction rather than adding them. Programmers make computers work using compilers(and interpreters), operating systems, and networks. So begin teaching students the fundamental knowledge needed to use those tools effectively.
Students need to understand syntax. Teach regular expressions and context-free grammars. There is no need to go as deep as theory of computation or languages or compiler design, but students should be able to recognize how a language's specification matches their own code, so they can correct errors from principle rather than by trial-and-error.)
Students need to understand how to use libraries. They should understand how they can obtain and use new ones in their own code.
Students need to understand how to use the interpreters and compilers that translate their programs into machine code. They should know how to build and configure several different development environments given a standard windows, linux, or mac box.
Students should know the basics of memory and IO. There doesn't need to be a dogmatic focus on optimizing for performance (there will be plenty of that later I am sure), but the constraints need to be as clear as possible.
Consider teaching OSI layers or the HTTP protocol rather than inheritance.
Data structures and basic functional abstractions are important fundamentals, too. If they aren't covered in CS 1, it makes sense to prioritize them in CS 2.
A programmer who doesn't know object-oriented design and polymorphism might write ugly code. A programmer who doesn't understand his target environment is going to write broken code. A programmer who doesn't know how to use his compiler isn't going to write any code. If the goal is preparing a student to be an effective computer scientist, the first step is imparting fundamental tools of the trade.
My first programming course took us from assignment 0 where we copy-and-pasted code to make sure we could use the compiler to a 450 line program that required us to answer queries on a simple data-set that was a directory of people. My second course was focused around an extension of the previous semester's project. The data-set became more complicated, we added a GUI, and we had to be able to write intermediate results out to a file, and read them back in. We were introduced to pointers and dynamic memory, and we got our first taste of data structures by implementing a linked list and having to sort it. The final program was 4,000 lines. Near the end, we were introduced to the basics of OO design - no inheritance or polymorphism, but we were supposed to take our data structures and associated functions and organize them into classes. In that way, we were able to see that some OO programming was just a more organized way of doing what we were already doing.
The emphasis of the second course was introducing us to data structures, basic algorithmic analysis, and making us program a lot. Not just in time, but also having a large program. Full OO came in the third course.
That's very probable. I'm in the middle of organizing my thoughts on this, based on my memories of introductory CS 14 years ago and what I've learned since then.
By far the biggest difficulty I had with my CS program was that they left it up to me to learn any "real" language on my own. The only language covered during the first two semesters was Pascal. C was never covered, except as an optional one credit class (which was combined with Unix and shell scripting). Assembly was covered, and if you took theory of languages you learned lisp. That was it.
All the painful idiosyncrasies of C and Java, rather than bogging me down in my first year, bogged me down when I was supposed to be writing operating systems and learning algorithms. Despite having a solid understanding of all the concepts: loops, recursion, lists, queues, functions, etc, having been using them since high school, I had a ton of trouble just getting them to work in C or Java (This was Java as it was in 1999 or so).
I remember submitting assignments in Java that used one single gigantic method in a single class because I got sick of spending time trying to figure out why the abstractions I was trying to create weren't working like I expected. I knew the object oriented concepts and aced all the tests, but had trouble when it came to actually writing code in anything but Pascal or BASIC. (or Matlab, actually, but that wasn't part of CSci)
I was a TA for CS 101 and 102 for a couple of years. I think I taught almost no one to program. The result (in terms of actual programming) would've been the same, had I just given everyone software and books and said, "have at it!"
As it was, I was just putting people through the motions of being in a college course.
I'd like to suggest that maybe we should consider two completely different things. Just as there is a huge different between someone who can play a musical instrument, and someone who is well versed in musical theory, there is also a huge difference between a _programmer_ and a _computer_ _scientist_.
You can learn how paging in a virtual memory system works, and how a garbage collector works, without necessarily being able to code up a program that plays "twenty questions". And similarly, someone be able to code up all sorts of interesting programs, without necessarily understanding "big O" notation. Their programs might not be the most efficient in the world, but it's certainly possible to do all sort of programming without being exposed to the formalism that comes from taking CS classes --- that's what most high school students who taught themselves how to write Basic, or Pascal or C programs generally have done.
If you decouple the two, then you could imagine having a series of classes which are "programming labs", for which you could test out of the first 1 or 2, and which would be mostly about the skill of programming, and different series of classes that are about _computer_ _science_, and which don't necessarily require that much programming expertise.
Sure, you can learn how paging in a virtual memory system works by reading wikipedia, but a computer scientist should really be able to write one of their own if they had to.
Not just being snarky here. I think even theorists have an implementor somewhere underneath.
I'm not sure I can make sense of that question.
No one can know everything, but if your specialty is, for example, virtual memory paging algorithms you should be able to write programs that implement and comprehend those algorithms, even if it's not production-quality code. If you are on the more practical side you should be able to read and hack on the existing code, even if it's not the central focus of your job.
I'm sure it's possible to find people who can be considered computer scientists but don't code very well or at all. But those people are rare exceptions, and aren't evidence that programming isn't an important tool in computer science.
There is a place for academia and mathematic approaches, and there is a place for real world experience and technical abilities. Ultimately someone who is good at being programmer does need a leavening of academic background, and someone who is a successful academic needs to know something about real computers instead of the academic over-simplified illusory world that contain friction-less pulleys and massless ropes.
I really don't think Knuth of all people can be held up as an impractical egghead. Compared to many other academics, he has always maintained a view towards real computers.
A good video sort of on this subject that I recommend is this one:
In addition, at my university I feel like the majority of students who are in the upper level classes with me (CS majors past their second year) got credit for the intro courses in high school. The way I interpret this is, it is a lot more likely for students to continue study CS past the first year if they take high school CS, which is a longer slower moving intro CS course.
I think the intro courses need to be much easier. They are discouraging too many smart students!
Now we get to the part where I sound like an asshole:
I'm not convinced that there is a good argument for teaching the "normal" students. In math, we don't go out of our way to attract people that don't like or aren't good at math. In fact, they usually come to us and say "I'm terrible at math" or "I hate math" and we politely help them with the calculus they need to pass to graduate and send them on their way. Math seems to have accepted its position as a "higher discipline" and while there are those that lament its inaccessibility to the layman, they don't lament that there are so few laymen in class---they just want to be able to show pretty girls at the bar pictures of the beautiful structures they play with all day.
So why can't CS just accept that some people just "don't get" the discipline? It is really hard, you have have a really amazingly large amount of domain knowledge, going all the way up from the metal to the OS and libraries, plus you have to know all this discrete math, understand algorithms of many flavors from many sub-disciplines, and recall it all at once so you can make tradeoffs. A good deal of the theory comes damn close to the math people are so open about being terrible at.
The way computer science works, you get students that love the math and can handle the programming, that stick with it long enough to excel with the programming too, and do great. Then, you get students that love the programming and can handle the math, same thing happens. But right now, you also get the students that hate the math and admit it, and hate the programming but don't feel like they can admit it, so they stick with it until they either drop to Information Science or something, or they graduate and become another one of those programmers that recruiters are always implicitly complaining about when they say "it's so hard to find good programmers".
In math, students who aren't excellent and passionate generally don't even try, or don't continue. That's because all they can do with a bachelor's in math is go to grad school, where they have to be good. In CS, it seems like we think we can send off crappy graduates and, well, if they can't go to grad school, at least they can get jobs programming. Well, wake up. Industry doesn't want them either. Better to help these kids realize they don't like the field and find something they do like, than let them continue busting their asses believing they'll get their dream job just for graduating.
This doesn't mean we should turn people away after the first semester. I like this model: let the kids that are really good skip the intro class(es), and make the intro classes intro classes. This means taking care to think about just how little background you can assume (in particular, assume no math skills, because otherwise they'd probably be math majors). Let this sequence take a year or so if necessary. Redesign the upper-division curriculum to both leave time for this extra intro stuff, and to take advantage of it: don't waste space with "upper-division" classes that are really just there for the crappy students to take so they can have something to do, because you won't have those students anymore. That way, you still be able to serve the average students, but they'll be nurtured at the right pace, making up for the lack of education in high school, until they're ready (or realize it's not for them), which seems to me like a much better model than "sink-or-swim CS 1".
In the new world order, we have 6.00, which is a "learn how to program" class which is not required for computer science majors (and which many non-6 majors take), and 6.01/6.02, which is the introductory sequence that everyone is required to take. The programming segments of these classes are still relatively trivial for someone with a reasonable amount of programming experience. (But I’ll also note the cover a very broad range of topics, and you’re bound to not know some of the other topics, e.g. EE)
To me, the beginning of 6.01 looks like a thorough review of most of the standard programming concepts using Python. I get the sense of "hey here's this tool, we're going to learn to use it. Try and keep up." Once Python and programming are covered, a whole bunch of programming-related engineering concepts are introduced. 6.02 looks to be primarily about networks and signaling and programming seems to be secondary.
There are no standards in education with regard to curriculum.
There is no shortage of cs students, and you need to filter them at some point anyway - might as well be with the intro to cs course.
When I was there, 1.00 was the "learn how to write programs" class, and it's a Civil Engineering class, not CS. 6.001 has been phased out in favor of 6.01 (unfortunately), and I'm sure as a result there's more "learn how to write programs" since they're using Python rather than Scheme.
There are other classes like 22.00 (also offered under many other numbers), "Introduction to Modeling and Simulation," but again they don't expect to be teaching you concepts like loops and conditionals.
On balance, I'd say most people come out of MIT knowing something about programming (even if it's just Matlab rather than a more general-purpose tool), and a decent portion of those learned it on their own.
Julliard can afford to be as competitive as it is because the input-output function is a strong bottleneck: You don't need many graduates (for every open violin position in European orchestras, there are roughly 800 graduates), there are plenty of kids who've been playing since the age of 6, so entry is competitive and standards are very high.
Programming? Very different situation. The market demands large numbers of CS grads, and (what the author so condescendingly calls) "natural programmers" are fairly rare. So standards suffer.
The right question is, what's the proper place to start?
On a similar note: The linked post is on how many new students don't understand the fundamentals in only one semester of programming. A counteranecdote is how many hard-science majors pick up programming far more easily than beginning CS students. I suppose the thought patterns for the one help in understanding the other.
First, set the bar high enough in universities/colleges that only people who have that magical natural programmer aptitude and lots of spare time programming experience can make it. Limit investing the precious university resources to that level and above only. This prevents academic CS education from being dragged down and dumbed down because they have to shovel nearly anyone who got accepted through the system.
Then, supplement those who wish to become the CS students but who lack the necessary mind and experience with training courses that begin from zero. These can be private courses or public education available in some other, non-academic institution. If it turns out that, given some experience, some of the trainees actually have the right aptitude then they can collect more experience and eventually apply to the university/college like the rest of the hackers.
If their pitch is to be believed, passing this course should provide enough programming competence to begin a CS curriculum.
This worked wonders for me, Python, I mean. I was one of those students who had no programming language knowledge prior to my CS1 class, which was based on the C programming language. I was not that bad at things like maths or physics, but I couldn't for the life of me understand how could one write "i++;" or "for(i=0;i < n; i++)", they didn't make any sense to me. I barely, barely passed CS1, but CS2 I failed like a pro. I didn't even try to pass it for a couple of semesters, until I learned Python (by myself) and then everything was smooth and easy. The professor actually congratulated me for my A grade.
I think some of the comments about simpler syntax (moving from Java to Python, for example) are in the right direction, but not far enough down the path. I think the fundamental problem is that of generalization. Someone may intuitively understand how to do a specific task themselves, but how do you take that idea and make it generic enough to be useful?
Programming is communication about how to solve a problem. So let’s skip the whole computer language implementation detail. Don’t start with computers. Start with problem solving. Make the implementation language a list of steps to be performed. Split off people into pairs – have them write down descriptions of how to solve some problem, and then have their partner act it out. You get to talk through parse/compiler errors instead of having to translate something that only really makes sense when you’ve seen it a couple hundred times.
Once people are comfortable with taking a problem and producing steps to solve it, picking up a syntax to say the things they’re already comfortable talking about seems like a much smaller step.
Long term, we’ve got to start doing this earlier. Grade school. Hell, preschool. Why should analytic problem solving be something you’ve got to wait to learn?
Other thoughts while I'm here:
We need to get over the math obsession. Yes, it's important. Yes, deep computer science has lots of math. But you don't teach someone to love music by first trying to get them to understand music theory. Let's cut out the parts that aren't essential. Let's take a lesson from unit testing culture - start with the smallest thing that will work. Big O isn't one of those things. Once people can come up with simple algorithms on their own (remember how great those first little wins felt?), it's a great opportunity to lead into complexity theory. But if you do it too early you'll just scare them off.
Maybe I'm in the minority, but I think everyone has the ability to learn basic programming and the analytic skills that go with it. It doesn't have to be hard. But we've got to start with baby steps.
By the end of your freshman year, you had taken:
CS1005 (which was basically learning C)
CS2005 (Object-oriented programming)
More importantly, when you were taking 2137, you had pretty much forgotten everything you learned in 2135 (as you're basically just perpetually cramming).
Perhaps there could be a special program in which a student spent 1 year intensively studying programming between high school and college. That might be able to bring motivated students into readiness.
I don't think there's any reason you can't teach an interested third grader to program.
The first is the "number of requirements" problem. At most colleges, there is some limit as to how many courses can be required for the major—a practical limit if not an explicit formally-imposed one. A lot has been forced downward into the standard two-course intro sequence, and this has "worked" because some of the students are either brilliant or have had good preparation in high school, where that "two-semester sequence" can be spread out over multiple years, and in many cases is preceded by one or more years of "pre-AP" computer science courses. But the downward migration of material has meant that what we now consider to be a standard computer science degree includes a lot of material, and if we add some sort of college equivalent to the pre-AP courses, we can either add them as explicit major requirements (that some students can place out of), which means removing material from the other end of the major, or leave them as bypassable prerequisites, implicit requirements that mostly serve to discourage students without a high school CS background from taking CS.
The second big problem is the staffing issue. As a practical matter, every course that might get added at the pre-CS1 level will be viewed as an "extra" that has to be staffed, and either takes away from staffing that could be provided to upper-level courses—earning the ire of at least some in the department—or else requires additional hires and thus administration approval. If it is played as "we need this as an additional prerequisite to CS1", it will find an administrative reaction of, "how did you get by for the last few decades, then?" If it is played as "we need this to get some students up to speed before taking CS1", it will find an administrative reaction of, "why are you proposing to teach remedial courses at the college level?" There is also likely to be an uphill battle to even fill the course, especially if you can't get the college to let it fulfill some general education requirement, and then you have the added problem of trying to justify offering a course that is chronically underenrolled.
Adding to the campus-politics tangle of the whole thing, CS is often viewed as too mathy and/or vocational training and therefore viewed with distrust by members of some other departments, making it even more difficult (in some cases) to argue for needed changes.
So, it's a hard problem. Good analysis, though.
 Which isn't actually anything like standard, actually, but we still talk about it as if it is. It's at least the case that formerly-advanced topics are now widely present in the first few courses.
Both my local university and junior college use C++ as the introductory language, which I believe makes the high learning curve even worse. (I cheated my way through the introductory course by teaching myself C and arguing that the programs compiled and ran in a C++ compiler, and taught myself C++ later when I was better grounded in the fundamentals.) If it were up to me, the introductory class would be half in Python to teach the fundamental concepts of 'if' and 'while', and half in straight C to teach the low-level concepts of compilation, data structures, and memory management, and the fact that you can implement the same algorithm in different languages. I would wait until a second course to introduce C++ and its inheritance, templates, and operator overloading.