my $name1 = '';
my $name2 = '';
my $address1 = '';
my $address2 = '';
...
While that's technically a valid program (the computer doesn't care), it's probably not a well-abstracted or well-encapsulated program, and it's likely ignoring modern Perl idioms.
One of the greatest advantages of lexical scoping with enforced variable declarations -- an advantage Perl has over Ruby and Python, for example -- is that you can see the scope of a variable by looking for its declaration. If you keep your scopes small -- if you encapsulate behavior into discrete pieces -- you reduce the possibility that essential information will leak out of those scopes into surrounding code. You minimize the coupling between distinct units of behavior.
Try explaining that to a novice.
To my mind, the greatest discovery in programming is the procedure. Attaching a name to a discrete unit of behavior lets you break down a big problem into smaller problems. Lisp and Forth hackers talk about this all the time. So do functional programmers. It's true.
Try explaining that to a novice, too.
If we really believed that maintainability is the primary concern of code, and efficiency and reuse and optimization were second-order concerns, we'd explain subroutines as "a way to attach a name to a discrete unit of behavior" instead of "common code you call more than once." They're both largely true definitions, but explaining the former first confers a huge advantage in my mind. Get novices in the habit of breaking problems down into separate, named steps and perhaps they'll write better code.
I think it's almost impossible to acquire good design sense until you have a lot of experience with programs of various sizes and levels of complexity. Novices lack that. You can indoctrinate them, but then you get Java-culture.
The question of how to explain procedures is tougher for me. My gut feeling is that the "way to attach a name to a discrete unit of behavior" explanation fails at explaining. "Common code" is clear, of obvious value, and a nice nod toward "Don't Repeat Yourself".
The recipe analogy, which you didn't mention, might be even nicer. (In The Joy of Cooking, the recipes sometimes call one another, just like subroutines—though alas not recursively!)
This much is true. I don't think this technique is neglected in formal CS courses, but maybe it gets second billing these days to concepts like encapsulation and polymorphism, which is moderately tragic. It's called problem decomposition, and, yeah, it's a good idea.
"Giant Steps",
Talking about "common code" is a bit missing the point. You don't want to just abstract out common code (that's hard anyway); you want to divide up your code in smaller discrete steps.
- ask