demerphq specifically asked me to comment on this thread, which is the only reason I'm wading into what is really a philosophical debate.

In Object Oriented Perl I show a few examples of (what I consider to be) reasonable uses of the ref($class)||$class idiom (e.g .section 4.2.1 and section 12.3.5).

Of course, this does not consistitute "cargo cult" programming because I (presumably) deliberately chose to use the technique and (presumably) know why I'm doing so.

And I guess that's the point: that there's nothing wrong with using just about any technique -- if you know what you're doing and why it's the appropriate thing to do.

For example(s):

I rarely use strict in my modules.

I often use a roll-my-own export mechanism, rather than Exporter.

My code brims over with symbolic references and typeglobbing.

I almost never write comments.

I'm not averse to using a well-placed goto
(or twenty -- e.g. Switch.pm).

I often provide multiple interfaces to a module.

Am I cargo cult programmer? I doubt it. After all:

I rarely use strict in my modules...because I rarely make the kinds of mistakes that use strict catches and (more importantly) because I know to turn it on when confronted with an otherwise-mysterious bug.

I often use a roll-my-own export mechanism, rather than Exporter...because I find it much easier that way to get exactly the behaviour I need.

My code brims over with symbolic references and typeglobbing...because that's the kind of under-the-surface program manipulation that my ideas often require.

I almost never write comments...because, if the code itself isn't enough of a comment, then I know I probably need to rewrite it.

I'm not averse to using a well-placed goto...because it's occasionally the very best solution to
a complex control flow problem.

I often provide multiple interfaces to a module...because I know that different people like to think -- and code -- differently, and that "intuitiveness" means eleven different things to ten different people.

In other words, someone who is competent with a wide range of programming tools may consciously choose amongst them, without any regard to prevailing fashion or received wisdom. They're actually the opposite of a cargo cultist, even if the visible symptoms are identical.

What about someone else who doesn't use strict, who rolls their own exports, references symbolically, fails to comment, indulges in the occasional goto, and who multiples interfaces without necessity? Are they a cargo cult programmer?
Maybe so. Or maybe not. It isn't what you do...it's why you do it.

Rules are not sacred. They're merely social mechanisms, provided to protect the inexperienced, and to streamline things for the experienced-but-working-to-an-impossible-deadline. Cargo cults are just sets of rules with sociological bases, rather than logical ones. They're all about programming the way Granddad used to program, not because I understand why Granddad did things that way, but just because Granddad did things that way...and it never did him any harm!

Is that an acceptable way to operate? Well it wouldn't be for me, but it might well be for you, or for her, or for them. And if it makes your/her/their code harder to maintain, perhaps that's a small price to pay for the valuable lesson that hardship has to offer. And perhaps it's a price the majority are happy to pay in exchange for the emotional comfort of doing things in the familar way.

Is merlyn right to disparage such coding practices? Almost certainly, since that's what he's being paid to do. Does that condemnation translate to a universal proscription? Almost certainly not (nor do I think merlyn thinks it does).

The trouble is, by just looking at the code (absent the coder) there's no way to tell whether one is seeing the results of superstition or satori. But that's the essential issue.

As the Jargon File illustrates in its Zen-like appendix:

A novice was trying to fix a broken Lisp machine by turning the power off and on.

Knight, seeing what the student was doing, spoke sternly: "You cannot fix a machine by just power-cycling it with no
understanding of what is going wrong."

First of all I agree with you on the importance of making your own mind up. I have made similar points in the past, and on several occasions managed to irritate people by refusing to accept the received wisdom. But I think I learn better for it.

That said, there are a few points about your own behaviour that I would like to point out.

I use strict fairly religiously. While you may not make the mistakes it catches, it catches a good fraction of my typos. Also I note that while you don't use strict, you get most of the benefits (and more!) from the test suites you write. Contrary to appearances, you do attempt sanity and caution.

Roll your own import or not, decisions, decisions. I have written my own imports before, and most of the time I don't. The rule of thumb that I use is, "If what I want is achievable from the basic Exporter, I use that just so that my semantics will match that. If they are totally different, then I won't. Consistency is good. If I am going to be inconsistent, I have to have an opposing good reason." Generally speaking the more "interesting" the code is, the more likely it is to need custom semantics. The vast majority of code does not.

I doubt that many knowledgable people would disagree with the uses of typeglobs and symbolic references that I have seen you use. However when you write more routine programs, I suspect you use fewer typeglobs and symbolic references.

I think the key-word about goto is well-placed. Few people know how to place them, and I would prefer to tell people never to use them than to have them try to figure out how to use them well. (An incidental note. Your goto in Switch also uncovered interesting bugs in the development release of Perl...)

Polymorphism is the one issue I disagree with you on. Sure, 5 people may find 20 ways of thinking about the same problem. But if they are going to work closely together, it is important that they manage to agree on one or two ways of cooperating. Furthermore many of what I consider the worst design mistakes in good modules are attempts to overload functions with every possible behaviour. Take, for instance, CGI's param method. As I pointed out at Re (tilly) 2: form parsing, the overloading is extreme enough that even good programmers will make mistakes and omissions due to forgetting parts of the interface and therefore passing through data that may be misinterpreted as metadata.

Yes, people find different things intuitive. Yes, people have a native capacity to handle ambiguity. Yes, as long as you stay within the limits of what people can handle, using that native ability is good. Perl has done this very well. But people's intuition is generally flexible enough to learn how your code works, and people ability to handle ambiguity does seem to have a hard upper limit. OK, possibly you don't have an upper limit. But I do, and you manage to exceed it on a fairly regular basis...

Which brings me to my biggest single comment. The average business has a huge concern known as, "What do we do if ___ gets hit by a bus tomorrow?" This is irritating for any decent programmer, we don't want to feel replacable. (Though a tip for bystanders, make yourself replacable and they are freer to put you into new, more interesting, roles.) Well you are not currently coding for a company that can ask that question, but for the sake of Perl, I hope you look both ways before you cross the street...

...when you write more routine programs, I suspect you use fewer typeglobs and symbolic references.

Probably so. Though I suspect that, even in those cases, I'm more partial to typeglobbing a closure than most folks would be.

If you count documentation as commenting...then you do indeed have verbose comments.

Hmmm. Not sure that counts in the sense I meant. I rarely document how the code works.

Polymorphism is the one issue I disagree with you on.

Well, thank goodness we differ somewhere! I think the point is that, unlike a member of a project coding team, I write code that (I hope) will be used by thousands of people around the world. That promotes TMTOWTDI to a prime design criterion and makes
it essential to provide a range of interfaces that cater to a vast diversity of coding prejudices styles.

for the sake of Perl, I hope you look both ways before you cross the street...

Yes. I do try to keep myself available to support what I've contributed. ;-)

Though, as my count of CPAN modules climbs towards the 30's (by the end of this year), it's becoming increasing difficult to maintain them all in a timely fashion. ;-(

And things will probably get even worse next year. YAS is about to announce a funding drive to extend my Year For Perl into 2002 (and to sponsor another one or two Perl Serfs as well!) But, with so many Perl people hurting financially in the tech downturn, I'm concerned that indentured servants are a luxury the Perl community can no longer afford.

So many people were so very generous in funding the work I've done this year, and I hope they felt that their contributions were well spent. But even if they do, that doesn't mean they'll still be in a position to extend that generosity this time round. Corporate donations may take up some of the short-fall, but I'm readying myself to have to cut back on my Perl work, in order to earn a living in 2002.

Of course, I may be completely mistaken about that, and we'll raise the money as easily as we did last year. I hope that's the case. But even then, things will still get worse: I'll continue to churn out new modules at about the same rate, and therefore have to dice my maintenance timeslices even more thinly. ;-)

My idea was simply to roll together use warnings and use strict into one easy to type pragma. When I brought it up on C.L.P.M people also mentioned that it maybe should include other options, like perhaps taint and diagnostics.

Maybe its a silly idea, but I alwas thought it would be cool to have the words 'use caution;' at the top of a program. :-)

mmm. Not sure that counts in the sense I meant. I rarely document how the code works.

I've started to write code that I don't document, in terms of how the code works. When I started to do that, I was uncomfortable, because I was breaking a Rule. Then, I realized it's because the only people who would understand the algorithms and subversions of Perl that I was doing were the very same people who understand why the Rule was broken.

To understand how to use goto, you need to understand why
not to use it. And the best place to start with that is by
reading Go To Statement
Considered Harmful. If you read the classic paper that
started the debate, you will find that the fundamental
objection to goto is that it leads to control structures
that are hard for people to model.

Therefore it follows that the only kind of goto which you
should want to use is a goto which helps the program fit
into control structures that people can understand. If,
of course, there are alternate commands which can redirect
flow you should want to use them instead. They document
intent more clearly. But it is occasionally true that the
best way to do things is a goto.

Knuth offered a number of examples in a paper I have not
found online. However based on a variety of comments I have
seen about it, it seems that the majority of his cases are
addressed with having multiple exits from functions, and
with Perl's loop control statements. In languages with
single function exits and without loop control statements,
you can reasonably reach for them with a goto. In Perl,
as noted in perlsyn, you would be far better off reaching
for loop control statements instead. Be warned, even so
you will find that there is a debate on the advisability of
internal loop exits. My position on this is shaped by
Loop
Exits and Structured Programming: Reopening the Debate.

Another example mentioned in the original paper is exception
programming. I have seen
goto used this way in both VB and Perl. Trust me. Doing
your exception programming with die/eval or some other
specific exception handler is far preferable to using goto
for this purpose. But that is a use you will occasionally
run into.

Given those extra control structures, it is rare to want
a goto in Perl. You have stated one, subverting the
stack. Eg to fool Exporter's caller. Or trying to
get tail-recursion to work. A second would be if you were
trying to create your own control structure. For instance
that was the problem that TheDamian faced in
Switch. His control of flow problem didn't fit
with any loop control statements, it almost did but not
quite. So he used an amazing goto to get what he wanted.
Another example might be that you could use gotos to make
state transitions for a finite state machine. (Hopefully
the ugliness would be hidden behind some code
autogeneration.) The goto is not problematic because it
enables you to work within a good structure for the rest of
the program.

I have not personally ever felt the desire to (other than
in deliberate experimentation) use a goto in Perl for
anything other than subverting the stack. However I remain
aware that I could, and I would do it without
hesitation if I thought the situation warranted it. I also
doubt I will ever encounter such a situation, but I think I
could likely spot it if I did...

They're actually the opposite of a cargo cultist, even if the visible symptoms are identical. ... It isn't what you do...it's why you do it. ... "What" is not important. Only "why" is important.
I'll take the antithesis to that. If I'm given a body of code to incorporate into something else, or to extend because the requirements changed, or otherwise to maintain, and I see a "mess" that is fragile and hard to change, than the original author was either very smart or had a large monkey multiplier factor. Do I care which? NO! I only see the result, that the code is hard to maintain.

In anything other than your own throw-away program, the "visible symptoms" is the only part that matters. Everything else is just cold dead history.

The "symptoms" that TheDamian talked about are checklists of specific programming practices people are told to avoid. If you know what you are doing and why, you can use most of them but avoid the problems which make it simpler to tell people not to use them. The resulting code can be both good and maintainable, but will cause people who only know the checklists to freak out because it violates their checklists. TheDamian is infamous for writing code like that.

It is like swimming. If you have had any swimming lessons, one of the first things they drill into you is to not get anywhere near a drowning person in the water because you will die. The reason is that a drowning person is several times stronger than normal, and their only desire is to climb on top of you and stand on your head. You simply are not a good enough swimmer to handle that treatment. Nobody is.

Yet lifeguards go after drowning people in the water all the time. Isn't that stupid? No, because lifeguards know the danger perfectly well and understand how to avoid it. (Always approach from behind, stay in place holding the person's head up until they are calm, the instant you get into trouble - dive!)

Yes, it is dangerous. Yes, it is what everyone is told from day one not to do. But if you know what you are doing, it sometimes is exactly what needs to happen.