Why choose Oberon?
The choice of programming language(s) to be used in our first course on Procedural Programming seems to be the subject of some variety of opinion. As I see it, the options are as follows:
1. Teach design and correctness of programs using a 'neutral notation', and give rules for translating this notation into a real programming language. Advocates of this option would favour Dijkstra's language of guarded commands as the neutral notation; possibilities for the real programming language might include C/C++, Oberon and Java.
2. Teach the theoretical part of the course using the same industrial-strength programming language as for the practical part. This language might be C/C++ or Java.
3. This option is like Option 2, but uses a specially-designed teaching language like Oberon or Modula--2.
Actually, I can see disadvantages in all three of these options.
Against Option 1, I would want to say that teaching two programming languages is going to be unnecessarily distracting and occupy time that would better be spent on something else. Also, having separate notations for theory and practice can only reinforce the notion (to which even our best undergraduates subscribe) that the ideas about program design that we teach have little to do with real programming, being useful only for clever proofs about academic examples.
Some proponents of this view suggest that you should program 'into' a programming language, not 'in' it. They even have a special word for the boring task of translating their programs before they can be compiled: it's called 'downcoding'. This is a position that could only seriously be held by someone who's never written or maintained a sizeable program – and certainly someone who doesn't believe that software tools can help with program design.
Against Option 2, I would object that most real programming languages are not very suitable for a first course in programming, because the important ideas tend to be obscured by odd syntax or peculiar semantics. In C, for example, the whole notion of typedef names is a mess – and those of us who have developed substantial programs in C have taught ourselves a way of using them that works, without our having to think each time of how it works. That's far from ideal in a first language. Other objections are that reference parameters have to be simulated in C by using pointers (again in a stylised way), and that C does not have the possibility of array bound checks. And C's notation for assignment and equality is annoying too, in a small way. I could go on, but will pause only to say that C++ shares all the disadvantages of C from this point of view.
Java would be a better choice, but there are weaknesses here too. Object-oriented programming needs a quite a bit of sophistication to appreciate, so it's better avoided in a first programming course. Java, on the other hand, forces us to use objects because of its internally consistent world-view (which incidentally is its biggest advantage over C++). For example, there are no record types in Java that are not actually classes, and there are no arrays or records for which storage is not allocated dynamically. It's annoying too that Java provides no way to express any parameter mode except call by value. Except, of course, that most values in Java are references. If we want to explain in a simple way the correspondence between high-level programs and machine language, Java is too sophisticated a place to start.
So that leaves us with Option 3: that of using a 'teaching language' that is designed specially for use on programming courses. My only objection to this is a weaker form of my main objection to Option 1: that it gives an impression that what we say about designing programs cannot be applied in practical situations with real, industrial languages. But of the three options, I think it is the best; the objection is easily overcome by respecting our students enough to explain the reasons for choosing a simplified language, then using it to develop programs in the course that are really useful.
My preference has therefore been for Option 3, using the same programming language – Oberon – to teach about program design and to do the practicals, but to include some information in lectures about how to apply the ideas if you're forced to use a less appealing language like C. Using a home-grown implementation of Oberon has its own advantages: we can ensure that the quality of error messages from the compiler suits a teaching environment, we can use the compiler as an object of study in later courses about programming language implementation, and we send the subliminal message that the techniques taught in our courses can be used to make programs that work.
This is really best of both worlds: there's no need to think in two languages in order to do program development, but on the other hand some link with industrial practice is there. If you have to use a bad programming language for other reasons, then of course you should protect your sanity by programming 'into' it, rather than immersing yourself 'in' it. But isn't it better, given the freedom, to choose a language where such measures are not needed?