[comp.lang.c] Do NOT teach programming in abstract terms. Was: Can Novices Jump Directly in C?

s64421@zeus.usq.EDU.AU (house ron) (02/13/91)

scs@adam.mit.edu (Steve Summit) writes:

>However, it is not (I hope) necessary to think in lowest-level,
>hardware terms to learn and use C effectively.  Were this in fact
>necessary, C would be quite a failure as an HLL.  It is true that
>most experts can and do think in hardware terms when programming
>in C, whether they have to or not, and this way of thinking is
>unfortunately often reflected in their teaching and writing.

I don't think you mean this.  "Lowest-level" hardware terms would
include descriptions of the voltage levels in the adders etc.

>My biggest complaint with most introductory C textbooks I've seen
>is that they unabashedly explain everything in hardware terms,
>referring to "machine addresses" and "word sizes."  Frequently,

On the contrary.  Too many textbooks and instructors in the more
esoteric universities deliberately teach programming in an etherial
style which bears no relation to the actual world.  Thank heavens
C books avoid this.  In fact, and this is my main point, IT IS
VERY MUCH HARDER TO START WITH THE ABSTRACT AND MOVE TO THE CONCRETE
THAN TO START WITH THE CONCRETE AND MOVE TO THE ABSTRACT.  That is,
teach by examples!  THEN show the principles behind them.  See later.

>they provide exercises which suggest that students write
>deliberately nonportable, machine-dependent programs, either to
>show why they don't work, or to discover parameters (word size,
>endianness, etc.) of the student's machine.  This has got to be
>bewildering to the beginner.

Yes, this is bad.  "Hardware" and "Non-portable" are NOT synonyms!

>Getting back to whether or not you need to think about the
>hardware in order to understand C, here's a frequent question
>which is often answered in low-level, hardware terms:

>     Q:	I had the declaration char a[5] in one source file, and
>	in another I declared extern char *a.  Why didn't it work?

>Curious people are often dissatisfied with a blanket answer like

>     A:	The declaration extern char *a simply does not match the
>	actual definition.  The type "pointer-to-type-T" is not
>	the same as "array-of-type-T."  Use extern char a[].

>They want to know WHY.  We have to explain that, given

[explanation mentioning pointers deleted.]

>As usual, a picture is worth a thousand words (they're just hard
>to draw well in ASCII):

>	   +---+---+---+---+---+
>	a: | h | e | l | l | o |
>	   +---+---+---+---+---+

>	   +-----+     +---+---+---+---+---+
>	p: |  *======> | w | o | r | l | d |
>	   +-----+     +---+---+---+---+---+

>We can see right away that both a[3] and p[3] are 'l', but that
>you get there differently.

>I don't claim to have invented this label, box, and pointer
>notation; it's used often.  (As I recall, there's a nice pic
>picture much like this in chapter 5 of K&R2.)

>Now, a lot of you are probably saying "wait a minute, he said he
>was going to explain it without resorting to hardware terms, and
>he turned right around and explained it in hardware terms."
>Though I was careful to use words like "location" and "place"
>instead of "address" and "memory," I have to admit that the
>discussion is still pretty low level.  Notice, however, that I
>didn't muddy the water by saying "suppose location `a' is address
>0x1234," and I avoided saying exactly how big that box that holds
>a pointer is.  I think anyone who has ever used a pocket
>calculator has some notion of a "register," namely a little box
>that can hold values; and no matter what computer language you're
>learning, you're bound to think about "values" being stored in
>"variables" that have "names."

I just love these nice simple pictures!  I use them all the time
while teaching programming.  BUT do you know that the majority of
students DO NOT KNOW WHAT THE ARROWS MEAN??  It is obvious to them,
whether you teach 'hardware' or not, that computers cannot contain
arrows!  Unless you explain clearly that the arrow is a NUMBER,
namely an address (just like a street address - that's not machiney!),
and show EXAMPLES of these addresses, over and over for a few weeks,
the average student is totally lost by these arrows in these nice
clean high level pictures!  It's a fact.  I've taught enough beginners
to see this repeated ad nauseum until I finally caught on that what
looked clean and simple to me looked unbelievable to the students.
They just couldn't relate it to anything they knew about that box with
a screen sitting on the desk.

>The point is that yes, you have to think about locations, values,
>arrays, pointers, and the like; but no, you don't have to talk
>about "the hardware," that ints are 16 bits, that pointers are
>really addresses consisting of a segment and an offset, that when
>you add an int to an int * the compiler actually scales it by
>sizeof(int), or any of those other "explanations" which somehow
>only manage to make things more complicated and harder to
>explain.

Partly true - segments etc, you are right.  But it is a big disservice 
to our students to deny them the underlying concepts which make
sense of the abstract pictures.  See my main point above.  The people
who rave longest about teaching things abstractly often have the
best knowledge of the underlying picture, but they don't realise
how deeply their own capabilities are rooted in that knowledge.

I have taught a lot of Pascal, and I have come to the conclusion
that C is a better beginner's language, precisely because it is
harder to obscure what's really going on.  Pascal students make
great progress rapidly, but a long way down the track, you suddenly
realise that something is wrong.  (Perhaps when you get to recursion,
or linked data structures).  I have been forced to the view that
the average Pascal student learns to program by PATTERN MATCHING.
That is, given a problem, write a solution which resembles a solution
to a similar problem seen before, without any understanding of what
is actually going on.  Then tinker with it until it works.  Retain
changes which make the output more correct, undo ones which make it
worse.  This usually works, unless the basic paradigm of the solution
is wrong, and then the student fails the assignment.

Remember, all mainstream computers are fundamentally the same.  Just
as bus and taxi drivers have to know what happens when they put their
foot on the accelerator, so does a professional programmer have to
understand the CONCRETE behaviour of the language constructs.  All
this does NOT mean that programs should be badly structured, or non-
portable.

--
Regards,

Ron House.   (s64421@zeus.usq.edu.au)
(By post: Info Tech, U.C.S.Q. Toowoomba. Australia. 4350)

barrett@jhunix.HCF.JHU.EDU (Dan Barrett) (02/21/91)

In article <s64421.666449403@zeus> s64421@zeus.usq.EDU.AU (house ron) writes:
>This is my main point, IT IS VERY MUCH HARDER TO START WITH THE ABSTRACT AND
>MOVE TO THE CONCRETE THAN TO START WITH THE CONCRETE AND MOVE TO THE
>ABSTRACT.

	I assume you realize this is your opinion (not rigid fact), as these
kinds of educational issues are still not fully understood.  I'd say it
varies greatly with the student, the instructor, and the topic.

>That is, teach by examples!  THEN show the principles behind them.

	Some students love this and benefit from it.  Some absolutely hate
it and are totally confused until you show the principles.  It varies.  But
this is one valid approach.

>I just love these nice simple [pointer] pictures!  I use them all the time
>while teaching programming.  BUT do you know that the majority of
>students DO NOT KNOW WHAT THE ARROWS MEAN??

	This is a very good point.  I make it a habit to "demystify" these
picture in my lectures by using example addresses (actual numbers) like
"18243".

	My first lecture in Introduction To Computer Programming teaches
students what addresses are in an amusing fashion.  From then on, I can talk
about them any time I want to move from abstract to concrete (for example,
variable parameter passing in Pascal "hiding" the addresses of the arguments
from the programmer).

	IMHO, it is a valuable learning experience to write a linked list
program in which you use a 2xN array to represent the list, rather than
pointers.  (Column 1 is data, column 2 is the "pointer" (index) of the next
element in the list.)  (You know, the FORTRAN way. :-))  It teaches a lot
about addressing.

>I have taught a lot of Pascal, and I have come to the conclusion
>that C is a better beginner's language, precisely because it is
>harder to obscure what's really going on.

	For those very reasons, I don't like C as a beginner's language.  A
beginner has PLENTY of information to learn without having to deal with all
of C's subtleties right away.  Even simple C programs can have very
hard-to-find bugs.

	But I don't like Pascal as a first language either.  This is a
religious issue, so I won't say any more about it.

>I have been forced to the view that
>the average Pascal student learns to program by PATTERN MATCHING.

	Perhaps this phenomenon is not as widespread as you think.  I'm 
sure it depends on the quality of the instructor, the students, and the
homework assignments.  (I am NOT implying that you are a bad instructor.)

>That is, given a problem, write a solution which resembles a solution
>to a similar problem seen before, without any understanding of what
>is actually going on.  Then tinker with it until it works.

	Homework assignments can be designed to avoid this and test
conceptual knowledge.  It takes work, but can be done.  I speak from
experience.  (Side note:  these "pattern-matching" students don't do well in
my classes.)

	Summary:  I think people are going to flame you for the subject of
your posting ("Do NOT teach programming in abstract terms") because different
people have different opinions on the subject.  But, in fact, your article
itself was not truly anti-abstraction.  Instead, you seem to be arguing NOT
to OMIT the "concrete stuff".  This is a good point.

	IMHO, both abstraction and the "concrete stuff" are important to a
good understanding of programming.  If you don't teach abstraction at all,
some programming knowledge doesn't transfer well when you move to languages
with VERY different syntaxes and coding philosophies.  (Example:  C vs.
Prolog.)  In addition, abstraction can help your code to be more portable
and maintainable.  (Examples on request.)

	But teaching only abstraction can obscure some real issues.  In
this, I agree with you.

                                                        Dan

 //////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
| Dan Barrett, Department of Computer Science      Johns Hopkins University |
| INTERNET:   barrett@cs.jhu.edu           |                                |
| COMPUSERVE: >internet:barrett@cs.jhu.edu | UUCP:   barrett@jhunix.UUCP    |
 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/////////////////////////////////////