Edsger W. Dijkstra wrote an influential paper back in 1988 called On the cruelty of really teaching computing science, which advocated an approach strongly grounded in the study of formal systems.
While I would be the first to admit that I am not fit to carry the late Dr.’s punch cards, I would say that if he really wanted to see cruelty, he might have tried his hand at the undergraduate course I taught this semester: C/C++ Programming in a UNIX Environment. This class was cruelty personified.
How long did it take you to learn C++? Do you think you could squeeze that into a single undergraduate semester, giving it only the 20% of your attention span that is due?
Now throw into the mix the requirement that you have to learn C as well.
And to keep things interesting, all your work has to be done on a UNIX or Linux machine. You’ve used Windows since you were 8, and think that cat is a four-legged pet and grep is some sort of gastrointestinal complaint.
Yep, you are in trouble.
Tricky Assignments
The good news in all this was the I didn’t make any of Andrew Koenig’s egregious errors when teaching the computer programming class. The bad news is that every homework assignment I created looked to my students like two impassable mountain ranges instead of one: an incomprehensible C++ problem to be implemented on an inscrutable O/S, using an IDE that was decidedly not Visual Studio.
Just as an example, for a recent assignment, I had the class warm up with a pure C++ implementation of mergesort, reading a string of words from standard input and writing the sorted list to standard output. Using all the facilities at hand in the C++ standard library meant that the mergesort implementation was a breeze – about the only piece of the algorithm that required much thought was merging the two subcontainers after dividing and conquering.
After the warmup part of the assignment came the meatier portion: I asked the students to implement the mergesort algorithm by passing the subproblems to child processes. This meant they needed to solve a few very common problems encountered when programming on *IX:
-
Using fork() to create child processes
Managing the lifetime of parent and child processes
Managing unnamed pipes for communication between a parent and child process
Serializing and deserializing C++ containers so they can be transmitted through a de-objectifying pipe
Admittedly, this is not a perfect demonstration of a way to parcel a problem out multiple processes. In fact, if done using a straightforward implementation of the problem you can create a beautiful example of a fork bomb, bringing your system to its knees. But I thought it would be a good way to get the hang of working with child processes in a somewhat realistic way. (And this could actually be a good way to distribute a sorting process – if you only forked a limited number times at the top of the merge.)
By fooling around a bit with process names I was even able to do a poor man’s animation of the process using pstree.
![]() |
When I worked up the assignment, it seemed like a reasonable assignment to tackle over the course of a week. Alas, at the one week deadline, my inbox was empty.
Lessons Learned
This wasn’t the first assignment that turned out to be a semi-disaster. My Scrabble game board manager saw a similar fate, as did my Scrabble word generator assignment.
As part-time non-tenure track faculty, I don’t have a lot of say in curriculum development. But after going through this course, I will definitely be passing along a strong recommendation: if we are going to ask students to learn a new language using new tools with a new O/S, we need to modify the class structure so that at least half of the hours are spent in the lab.
When I worked through these problems in a lab environment, it was easy to provide the gentle nudge to help someone who was stuck trying to get Eclipse or NetBeans to do the expected, instead of whatever perverse path they were on. I could help with the C++ compiler errors, which over a decade after standardization are still a travesty. And I could help coax the debugger into providing usable information when looking at standard C++ objects – which the IDEs will do only grudgingly. In other words, help with the undocumented tips and tricks that experienced C++ programmers take for granted.
At the end of the semester, I do feel pretty good about the class’s mastery of C++ – they soaked up as much of this huge language as was humanly possible. UNIX/Linux expertise didn’t seem to get the same level of commitment – which is unfortunate but understandable. And I have to admit that C programming took a back seat to C++. There are lot of C++ haters out there, and I don’t really need to get them riled up, but once you master C++, there aren’t many times when it makes sense to back down to the much-less capable C language. Unless you’re getting paid by the hour. Or working for Linus.

36 users commented in " Cruelty Redefined: Undergraduates vs. C++ on Linux "
Follow-up comment rss or Leave a TrackbackI feel sorry for your students. Not only did you fail to understand the concepts that Koenig and Dijkstra wrote about, but you didn’t even care about your students to give them a quality of programming foundations. Not to mention that you’re bringing in language as a religion into your attitude.
On first glance, you seem to be a horrible foundations lecturer. Maybe you should ask your administration to give you higher level classes because you can’t relate to novice students.
What are people who have no previous experience in Unix doing in a computer science class? Perhaps they should’ve taken some preliminary course first?
I don’t know if you realize it sir, but here in this case, you are the douchebag. As an ex-TA, I can confidently say you have no experience teaching this sort of course and you have no business doing so, given the abysmal approach you take.
My suggestion: you don’t have time for the full complexity of C++, so concentrate on C and the essence of the Unix operatig system. issue all of them a copy of (1) Kernighan & Ritchie, the C Programming Language and (2) Kernighan and Pike, The Unix Programming Environment and give them as much lab time as possible. Painlessly euthanise anyone unable to build a desktop calculator by the end.
I am only half-joking here. Kernighan & Pike is a great introduction—stripped down to the essentials (because when they wrote it, only the essentials existed), focussed on using programming and your own cleverness to solve problems, not IDEs. It is also very thin compared to the average text book these days. People who can’t understand it probably are never going to be useful programmers.
For programs on the scale discussed in the book, the limitations of C compared with C++ do not matter. Assuming they have previously been programming in Java or C#, then discovering that work can be performed in C would itself be a useful lesson.
“…I had the class warm up with a pure C++ implementation of mergesort, reading a string of words from standard input and writing the sorted list to standard output…”
…and why? That draws unnecessary attention from real programming to a trifle like I/O. (When C first appeared, it boasted separating I/O from the programming model, among other things — remember?)
“After the warmup part of the assignment came the meatier portion: I asked the students to implement the mergesort algorithm by passing the subproblems to child processes”
So, now that the kids can barely program, they have to do process management?
Dude, it’s not C or C++, it’s this extra ultra-pragmatic crap you’ve thrown-in that killed your class, IMHO.
So much spite in a post wrapped around too much ego. Rather than give any specifics about how the class actually fared, whether they retain any of the “skills” you imparted more than a week after the class, or if you have any real world experience, you regale us with your personal glories at how you gave a room full of 19 year olds Stockholm Syndrome by way of a C++ compiler.
When I was an undergrad, we had an annual campus-wide poll for the professor who was the biggest jerk. You voted by donating change to a local charity in the cafeteria, one penny per vote. I’d have dumped my entire penny jar, followed by my entire bank account converted to copper into your bucket.
You are the poster boy for why kids are avoiding Comp Sci like the plague now and just opting for a few years of real world experience to get the bad taste of ivory tower academia out of their mouths.
IDEs are a crutch. If you learn to walk with a crutch you won’t be able walk properly without a lot of physical therapy. You need to learn all the nice things that the IDEs do for you. Then you can understand what is going on and make intelligent decisions.
The first languages I learned in college were Modula2 and Fortran in a DOS environment and I learned C on my own with my mac(yes I know it was an ide). I forget which c++ compiler was on the Sun machines but that is what you assignments needed to compile with. For quite awhile I used pico to code and switched to vi and still use vi to this day.
Of course I do more systems and networks in my career so maybe I did end up stunted. :)
Over the last few years I have been doing some projects with QT and I frequently find myself in a console running make or editing files because eclipses editor does not do a very good job of emulating vi and its console is a tiny little subwindow so you cant see much of the copious amount of errors that c++ compilers spit out.
I will admit though that version control and debugging in a gui are very nice. gdb does work well but its not quite as intuitive through a command line.
@huguley:
>IDEs are a crutch
I disagree. IDEs are a tool used in the process of programming. A tool no different than a text editor, a debugger, a profiler, etc.
A crutch is a tool that helps someone who is somehow impaired. I don’t think that an IDE is helping you get over an impairment.
In my class we of course went over the process of developing with just a text editor and a command line – but not becase IDEs are evil, just because sometimes these are the only tools you have at your disposal.
- Mark
@tranto:
>“…I had the class warm up with a pure C++
>implementation of mergesor
Actually, there was a very good reason why.
It became clear during the course of the class that about half the students were unclear on the concept of recursion. I was kind of surprised, because the prerequisites for the class should have covered this, but sometimes things don’t sink in.
So the first part of the assignment was a basic review of how divide-and-conquer strategies can often be implmented using recursion.
- Mark
@ab123:
>What are people who have no previous experience
>in Unix doing in a computer science class?
They are undergraduates, so they may not have a wide variety of experience. They need to get that exposure somewhere, and I guess the higher powers that define the curriculum decided this class was where it would be.
- Mark
@Damien:
I think the class would be much more manageable if we could just concentrate on C – but the class objectives call for C++. So yes, it is overly ambitious, but I can’t cut out half the material in order to cover the remainder in more depth.
- Mark
I’m not sure why your post garnered as much ill-will as it did, but having read Dijkstra’s paper many years ago and having some time to let it simmer, I have to take your side on this issue. Many of my computer science friends can’t write anything in C++ to save their life, and are so grossly dependent on their IDEs that the helpful messages the compiler usually gives get blown away by the effective equivalent of Clippy saying “Hey! It looks like you’re trying to write a program that reads e-mail. Do you want me to do most of it for you?”
Learning Unix and C++ is not difficult, unless you’re too lazy to actually try. Sadly, many of my former classmates were.
-S
PS. I graduated in ’08. College was relatively recent.
@S Rabin:
>I’m not sure why your post garnered as much ill-will as it
>did
Some topics are flash points. CS Education is one of them, C++ is another. Put them together in one article, and boom! :-)
>Learning Unix and C++ is not difficult, unless you’re too lazy to actually try.
What a ridiculous statement. I doubt that there is more than a handful of programmers in the world who REALLY understand C++. And you are suggesting that students could learn that AND C AND Unix in the course of a single class?
I have taught college courses, and am often appalled at the lack of initiative and resistance to hard work that many students display, but I do not expect them to forego sleep and everything else in their lives in order to obsess over my material.
Somewhere on the internet, someone is wrong!!!
@gramie:
“I doubt that there is more than a handful of programmers in the world who REALLY understand C++.”
What a ridiculous statement. And we’re supposed to believe you’re a teacher? Yeah, right.
“There are limits to what you can do in the child process. To be totally safe you should restrict yourself to only executing async-signal safe operations until such time as one of the exec functions is called. All APIs, including global data symbols, in any framework or library should be assumed to be unsafe after a fork() unless explicitly documented to be safe or async-signal safe. If you need to use these frameworks in the child process, you must exec. In this situation it is reasonable to exec yourself.”
But hey, I guess it’s better to incorrectly teach toy problems that are barely relevant to doing real work than to actually inform them about how these systems are built.
@mikeash:
Actually, for the mergesort problem, all operations performed in the child process are safe. The only operations performed are reading and writing data to/from a pipe.
- Mark
While you could implement a fork-safe mergesort, I’m going to guess that some STL or C++ strings were expected to be involved to manage the data in between receiving it from the children and sending it to the parents, and also guess that no mention was made of what “async-signal safe” even means, let alone its implications for what you can do post-fork.
I don’t think it’s intended but you’re comming across like this; the kids get their first driving lesson in a cart; start engine, stop engine. And in the second they have to win a rally in an english car with manual gear change.
As a student I’ve heard teachers more than once complain about their frustation that most of their student lacks the right “bagage” for their classes, is this the case here.
“There are lot of C++ haters out there, and I don’t really need to get them riled up, but once you master C++, there aren’t many times when it makes sense to back down to the much-less capable C language.”
Sure, given that only about 10 people in the world have ever “mastered C++”, I think that’s fair. The chances that one of these would be in any given college class is roughly 0.
For the other 99.99999% of programmers, we suffer through a little C++ in college because it’s required, and then never use it again. In the 10+ years since I graduated, I’ve used C several times but never C++. It’s right in the anti-sweet-spot: not as simple as C for glue, and not nearly high-level enough to be a productive HLL.
When I attended University our courses were devided into the following structure
C -> C++(elective) -> Unix System Programming.
Build a programming foundation then teach them system programming.
Out of the 50 or so students in my System Programming class not a single one failed. We implemented programs such as our own Shell(built on over the semester) to handle basic I/O, an FTP server/client, implement all kinds of unix system commands, work with logs through programming, etc…
The class was structured to constantly build on the things we learned instead of making wild assumptions about the things we should know.
I actually would have loved to get this class. At my university in Spain we learn C89 (not C++) writing a complete shell (and playing with mmap, stream redirection, forking, etc), and we work on Ubuntu on every single workstation since day 0. We usually code in gedit (some use vim/emacs/nano), compile in the command line and debug with gdb/valgrind. The point is pushing people out of their comfort zone so they actually learn stuff, and your assignments actually look pretty stimulating (provided you are flexible enough to provide a 3 weeks deadline after the 1-week deadline was proven a failure)
Besides, learning C++ without learning C is nosense (and this comes from someone who loves C++/Qt and works only in C++ currently). C++ is convoluted and difficult, C is plain easy. And you need to learn C while learning C++. Here we learn C and Java (and Python and OCaml and Pascal and Fortran etc), and don’t touch C++, and we have no problem applying concepts from both languages to learn C++ after we graduate.
My next course in the CS curriculum (I’m a student) teaches C, C++ AND Java in one class. I’m scares, hold me.
Had a class, that wasn’t about programming per se, but the things you might need to do independent of any language. 3 programming assignments the whole semester with about a week to do them.
Up until now the curriculum was centered around Java or C# at this school (there was a single C++ class but that was purely a intro to programming class.)
The assignments in this class however, required C or C++. No big deal, I’ve spent time learning to use these two languages my self, giving me that much more wiggle room.
What I didn’t expect was that the code would need to be run on a Linux machine (Or rather, over a secure shell to an instance of a console [I think]). No real guidance given or time to learn how to use make files, the compilers or any of that jazz. I had to more or less base it all on the terse example provided on a slide and hope for the best. Then several hours later, after a frustrating back and forth e-mail session with the professor and pleas for help to Google I managed to get it to work. Some how.
At least I’ve got a new summer project! Get to KNOW how it works on Linux.
Well, if cruelty is the yardstick to be used, why not:
- Write in x86 assembly, or any assembly language that you prefer, an interpreter and code generator compiler (non optimizing, for now) of a higher level language. Replace higher level language with Java, C#, Python, etc. With this you are forcing the students to learn 2 languages in one class, their syntax and semantics.
My undergrad curriculum was taught almost entirely in Java for most of the first two years. We were gradually introduced some *very* basic unix, but there was no class that had an emphasis on it. At the end of the second year, we got one class (quarter system) where we had to learn C, C++, a little bit of Objective-C and C#, Perl, and a little more basic unix. After that, we were expected to do everything in C or C++, including operating systems, networking, complex data structures, you name it. Whoever thought that kind of curriculum could work was a complete idiot. After two years of pure Java, a few weeks of cramming C++ into our heads did us no good. We were mostly left trying to figure out the language on the fly, while working on projects – and none of us *really* learned the language. Possibly the worst part is, we didn’t realize how lacking that curriculum had been. It’s only when I started working that I discovered how little I knew about C and C++. I think I’m still catching up…
It’s often best to throw your students into the deep end, where they will learn the most and overcome their anxieties out of necessity. That way, you can also see who will sink or swim and adjust your course to accomodate the particular weaknesses in the class.
Saying that, if none of your students were able to hand in the assignment (even a decent attempt at it), that says one of two things:
Either they lacked any experience at all with *nix systems (which would be a bit surprising and disappointing in this day and age), turning a minor hurdle into an impassable mountain…
…or the calibre of students in your class just isn’t that great, in which case, you have a lot of work ahead of you. And I wouldn’t be at all surprised if this were the case, given that 95% of my CS class could not code their way out of a DOS batch file, but a lot of them entered CS without really knowing what it was about and not really being interested in programming itself.
This sounds like a class I took my junior year in college c. 1995. We had to write a print spooler and it involved data structures and fork/exec. The language was in C. The prof was not a fan of C++. The O’Reilly book with the Lion on the cover was a life saver. If you can still find it that will give you everything you need to write fork and exec code, plus use semaphores and pipes. I wouldn’t attempt to introduce C++ along with *NIX system programming in the same class. There is so much to learn about C++ that is unique to C++. The syntax, the compiler error messages, STL. It’s going to take most of the semester before you even get to OOP concepts in C++. Back in the early ’90′s you had to have access to an expensive Sun/HP/IBM/SGI workstation to hack on UNIX. Today you can take an old laptop or desktop too slow to run Windows 7 and load a Linux distro, so I don’t get why these CS students are ignorant of Linux when they enter this class. They should at least know what cat and grep are, and they aren’t stuck with VI or emacs, like I was back then either.
As RazZziel I would love to attend this kind of class. I study CS at Graz University of Technology in Austria. In the first semester we learned C. The professor told everything he had to in only 6 lessons, so I basically had to learn everything by myself, since there is no way anyone could learn and understand all that stuff in only 6 lessons. After these 6 lessons we had the rest of the semester to complete two exercises, one of which had more than thousand lines of code, which was close to impossible to someone who wrote Hello World for the first time only two months ago.
We had to figure out by ourselves how to compile with gcc, check for memory leaks, etc.
In the second semester, we covered C++ in only eight lectures.
Maybe there is a little bit too much of everything for one lecture, but the tasks you give to your students don’t seem to be difficult at all.
“There are lot of C++ haters out there, and I don’t really need to get them riled up, but once you master C++, there aren’t many times when it makes sense to back down to the much-less capable C language.”
You clearly do mean to get them riled up. You’re patently wrong.
Good code doesn’t necessitate your ideal of OOP. That’s why you can write a great program in pure C — just like you can in plenty of languages other than Haskell. Sure, you can compile it with g++ and call it “C++”, but you don’t need classes for good code. “Much-less capable” has nothing to do with it.
@Arlen:
I don’t disagree with anything you say.
There is absolutely no doubt that C is a perfectly capable language, and it is suitable for a huge universe of programming tasks.
And further, the quality of the code produced in any of these projects is going to depend far more on the programmer than the language of choice.
And incidentally, my preference for C++ really has little to do with OOP. Just as an example, I really appreciate having the container classes (and I will throw in the string class). Having unordered_map and vector in your toolbox is very convenient.
No question that you can implement those same containers in C – but they work very well in C++, they come with the compiler, they are standardized, and they save me a lot of time.
- Mark
A question for you. Was it the curriculum that proposed teaching the appropriate use of Fork in a week or was that all from you?
Because one lesson I think you should take away from this is that multiprocessing is hard. I’ve heard of people who’ve spent lifetimes of not really getting it. I’ve personally witnessed people struggling for an entire semester to not get it. I’d expect a week of not getting it to be vastly more than the average result.
And spending a week “debugging” some randomly crashing program when you don’t really get why it’s failing isn’t a useful way to learn about C, C++ or Unix.
@Mark ” aren’t many times when it makes sense to back down to the much-less capable C language.” vs “There is absolutely no doubt that C is a perfectly capable language, and it is suitable for a huge universe of programming tasks.”
Which one of these statements is honest?
[...] the article here: Cruelty Redefined: Undergraduates vs. C++ on Linux Bookmark to: This entry was posted in Uncategorized and tagged class, expertise-didn, [...]
This has made my day. I wish all psoitgns were this good.
Leave A Reply
You can insert source code in your comment without fear of too much mangling by tagging it to use the iG:Syntax Hiliter plugin. A typical usage of this plugin will look like this:[c]
Note that tags are enclosed in square brackets, not angle brackets. Tags currently supported by this plugin are: as (ActionScript), asp, c, cpp, csharp, css, delphi, html, java, js, mysql, perl, python, ruby, smarty, sql, vb, vbnet, xml, code (Generic). If you post your comment and you aren't happy with the way it looks, I will do everything I can to edit it to your satisfaction.int main()
{
printf( "Hello, world!\n" );
return 1;
}
[/c]