http://www.perlmonks.org?node_id=450535

One of the greatest things about hanging in PM is to occasionally hear merlyn and other esteemed monks scream "Never, never, never". From today's post and some recent posts I found a few:
  1. Never, never, never use a symbolic reference (Dynamically Building Variable Names)
  2. Never, never, never use $1 without checking the matches first (Re: WWW::Mechanize follow meta refreshes
Are there others? Of course, equally on the other side: Always, always, always.

Replies are listed 'Best First'.
Re: Never, never, never
by theorbtwo (Prior) on Apr 22, 2005 at 19:17 UTC

    johnnywang, there's an old saying, quoted in somebody's .signature, to the effect of "examine what is being said, not who is speaking".

    Additionally, never say never again.

    Exporter uses symbolic references in order to allow you to specify the names of subs you wish to import and export. You pretty well have to use them there, and in AUTOLOAD subs that create new subroutines at runtime.

    You can use $1 without checking that you match first if you really do want the strange scoping behavior -- that is, that you want the $1 from the most recently succeeded match.

    Of course, I wouldn't do either of those things without comments, but that doesn't mean that they aren't occassionally useful things to do.


    Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

      I agree.

      In my experience, symbolic references should be used (when you can) in preference to eval STRING - basically, when you're generating code (esp. converting closures to "regular" subroutines etc.) In those cases they're generally easier to use and less error prone than eval "".

      Eval string is still useful too - but you need to be wary of scoping issues and typo's, which can be difficult in generated code. The only thing I regulary use it for is eval "use $some_module";

      Actually, you can hit the symbol table directly, so you never need to use symbolic references per se. Of course, as long as you're aware that you're going into the symbol table, and it's the Right Thing To Do, there's no reason not to use the sym refs.

      Caution: Contents may have been coded under pressure.

        Eh, there's a moral equivlency there. $Package::{'bar'} is a symref just as much as ${'$bar'}, even if one violates use strict 'refs'; and the other does not, I'd say. (But I think there's a good argument the other direction as well.)


        Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Re: Never, never, never
by jhourcle (Prior) on Apr 23, 2005 at 16:54 UTC

    A couple more for you (with merlyn's clarification), based on what I've learned over the years:

    • Never use programs from Matt's Script Archive? (technically, this goes into the whole 'never run something without understanding what it's doing' category)
    • Never assume that a file/socket/db handle/whatever opened successfully
    • Never write your own CGI parsing routines without a really good reason to avoid CGI or CGI::Lite
    • Never use the single argument form of exec or system
    • Never test for taint by looking for known bad characters. (instead, look if there are any characters that aren't known to be good).
    • Never pass input to exec or system without first checking for taint.
    • Never assume that e-mail happens immediately, or reliably.
    • Never trust a Sicilian when death is on the line
    • Never waste time optimizing your code before you know where the real bottlenecks are. (see Optimization: Your Worst Enemy and Premature Opmization)
    • Never assume that what you're writing is going to be short lived (unless you delete it immediately after writing it).
    • Never forget the importance of descriptive, unambiguous variable, function, and package names, or the importance of comments and documentation

    I'll probably have more to add later....

      - Never assume any knowledge whatsoever on the side of the user, which leads to: always, always, always check user input before processing, in whatever form it may take.

      - Never assume a subroutine/command has processed a call succesfully when said subroutine/command goes through the trouble of reporting whether or not it did and in that light, always endeavour to write subroutines that have clear and concise error reporting as well as a return value that reports if the command was executed succesfully.

      Those are mostly rules I try to stick to myself, but a lotta folks I know feel the same way about it.

      Remember rule one...
Re: Never, never, never
by mstone (Deacon) on Apr 24, 2005 at 01:47 UTC

    There's an old german proverb:

    Follow the traditions until you know what they're for. Then do whatever you want.

    That broadly applies to your question. Rules like "never do X," and "always do Y" are the condensed version of some larger, more complicated piece of wisdom. But those rules don't actually teach you the wisdom. Take "never use symbolic refs" for instance. It's easy enough to follow that rule, but what do we learn from doing so?

    Not much.

    If we dig into what the rule is for, we discover concepts like data localization and scope management, which offer much more insight about programming than simply avoiding symbolic references. Learning to think about those issues makes us better programmers, where just following the rule only keeps us from getting stuck in one well known tarpit.

    Always/never rules are no substitute for actual programming wisdom. They're just the rare cases where some principle works so very much of the time that few people will call bullshit if you state them in extreme terms. But never (yes, I'm aware of the reference) just accept always/never rules as doctrine. Dig into them, and find out what they're really saying. Learn the principles, then learn the limits of those principles. Once you know how the principles work, you won't need the simple little always/never rule any more.

    As an aside, I've noticed a reduction in the number of people saying, "use CGI.pm or die!" here in the monastery since people actually started trying to read it. And version 2.98 (which happens to be on my current machine) is a lot cleaner than previous versions.

Re: Never, never, never
by chromatic (Archbishop) on Apr 22, 2005 at 21:45 UTC
      Here's a demonstration of why indirect object notation is dangerous: Try running this program. Now rename Prunt as Print and watch Perl do something unexpected.

      The explanation is that print $fh makes Perl look for Print in the current package before looking in $fh's package, whereas $fh->Print looks only in $fh's class and any base classes.

      On another subject completely, this demo program violates another 'always, always, always' rule that people often mention: always pass the class name as the first argument of a constructor and bless the new object into the package supplied to you rather than the current package. I think that's unnecessary. Any derived package can call your constructor and then rebless the new object into itself.

      IMHO, one of several problems that make OOP unnecessarily difficult in Perl 5 is that a constructor can't easily and efficiently tell whether it was invoked as pkg->new or pkg::new (in other words, whether the package name was passed as the first arguemnt or not, and therefore where in @_ the 'real' arguments begin). Most people use the former, but the latter is more efficient because it passes one argument fewer. Perl 6 fixes this problem, along with so many others.

      Markus

      "Never disable buffering without a good reason", eh? I'm actually of the opposite opinion, and I turn it off out of habit. I think this is a case where the default is wrong: turning buffering on should be regarded as a performance hack.

      The trouble is that a lot of beginning perl scripts are mixtures of back-ticks and perl output -- an early use for me was an attempt at adding some readable column descriptions to the output of a unix command-line utility. What happens with buffering turned on is that you get the output from these two sources intermixed in an almost random fashion. And the reason this is happening is not at all obvious, in fact I would argue it's nearly impossible to figure out -- even if it occurs to you to read the docs for the special variables, there's nothing about the writeup for "$|" that would leap out at you (do I want my "pipes to be piping hot?").

      So this is a hard one... if the default were different, perl might have an undeserved reputation for slow output, but as it is there's a nasty little gotcha in there. I tend to shut off $| for all my command line scripts... though of course you probably *shouldn't* do that in something like a CGI script.

        I see a lot of programs where people disable buffering when they only print to standard output with newlines (or standard error) and never call external programs. (I've also seen a lot of programs disable buffering when they never printed to that filehandle!) Out of the last few hundred pieces of code I've seen, perhaps 5% needed to disable buffering.

Re: Never, never, never
by BrowserUk (Patriarch) on Apr 22, 2005 at 22:24 UTC

    When you take your driving test(uk), they emphasis the importance of never crossing your hands on the steering wheel, and will fail you if you do.

    But if you watch any of those "Police chase" TV programs with the in-car footage, watch the drivers hands.

    If crossing your hands or arms were absolutely verbotten, then the Schumacher brothers, and all their compatriates in F1, and every other form of motor sport, would be in jail.

    All rules have caveats. Knowing how and when to apply the rules is a part of the trick. Having systems flexibile enough to allow for the caveats is another. Perl's strength is that it recognises the need for caveats and allows for them. without necessarially making them too easy to use.

    The most heartening thing about what I see in the Perl 6 development, is the continuation of that permissive, practical approach to the design.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco.
    Rule 1 has a caveat! -- Who broke the cabal?
Re: Never, never, never
by cog (Parson) on Apr 22, 2005 at 19:04 UTC
    Does a "Don't you ever, ever, EVER run obfuscated code you don't understand" (Have a nice day) apply?
Re: Never, never, never
by b10m (Vicar) on Apr 22, 2005 at 19:12 UTC

    Mentioned in every node (if not, it should): Always use strict;

    --
    b10m

    All code is usually tested, but rarely trusted.
Re: Never, never, never
by bofh_of_oz (Hermit) on Apr 22, 2005 at 20:39 UTC
    I would say: never never never do something strange and/or unusual in (with) Perl unless you're sure what you are doing (even if you just want to have fun)

    As for "always", here is one I learned the hard way:
    Always, always, always comment your code so that if you have to read it in three years, you would still understand what it is supposed to do...

    -------------------------------------------
    An idea is not responsible for the people who believe in it...
Re: Never, never, never
by johnnywang (Priest) on Apr 22, 2005 at 19:58 UTC
    I guess I should have worded my post as "never, never, never for the rest of us". Most of us would read this type of "never, never, never" advice the same way as "don't play with fire", with the understanding that some people have to, but most of us don't need to, and for good reason.
Re: Never, never, never
by tlm (Prior) on Apr 22, 2005 at 21:48 UTC

    You'll be interested to know that TheDamian is working on a book on best practices for Perl. I'm looking forward to that one.

    the lowliest monk

Re: Never, never, never
by FitTrend (Pilgrim) on Apr 22, 2005 at 19:31 UTC

    What I find interesting about this node is that "never, never, never" is purely the opinion of a programmer. I agree that some methods are not optimal, but isn't perl designed to allow you the freedom to write code the way the programmer understands it?

    If it accomplishes your goal, its easy to maintain, and it doesn't crush your server or cause other problems, then do it.

      Relativism only goes so far. There are many things you can do in Perl that are nearly always wrong, and telling people not to do them is a community service. TMTOWTDI is not a license to write terrible code.
      Largely I agree with you, perl is the embodiment of TMTOWTDI; but there are some security related 'never,never,never's that are good standard coding practices. One example would be never to eval unchecked user input.

        On the other hand, that is exactly the point of a REPL (Read Evaluate Print Loop), like as perl -de1.

        There is a time and a place for everything -- but times when you should eval unchecked user input are fairly rare rel to the number of times that it looks like it might be a good idea.

        For example, interactive agents of mine often have an "evaluate this" command... but only if they are single-user, or first check if it is me.


        Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Re: Never, never, never
by zentara (Archbishop) on Apr 23, 2005 at 11:12 UTC
    Start using "goto" and see how many reprimands you get. They will have to wrestle my goto from my cold dead hands. :-)

    I'm not really a human, but I play one on earth. flash japh
      ahhhhh, the good old goto. that was slapped out of me by my uncle when he saw me using it in gwbasic as a 10 year old. never ever used it again since then...

      Remember rule one...
Re: Never, never, never
by demerphq (Chancellor) on Apr 23, 2005 at 16:39 UTC

    I do my best to never, never, never, say "never, never, never". I prefer to say things like "you should only use stuff like that if you know why it is that people say you shouldn't use stufflike that." :-)

    For instance you should only use prototypes if you understand why its usually bad to use prototypes.

    ---
    demerphq

      I do my best to never, never, never, say "never, never, never".

      I try that too, but I always, always, always seem to fail :-)

Re: Never, never, never
by northwind (Hermit) on Apr 23, 2005 at 17:32 UTC
      Hum... I wonder who would win the "Never never never" trophy... :-)

        Well, I've got a score of 2 "never, never, never"s in one piece of code.  I'm sure another acolyte to PM could beat that score though...

Re: Never, never, never
by adrianh (Chancellor) on Apr 23, 2005 at 17:13 UTC

    Never, never, never write production code without writing tests.

      And never, never, never do your changes in the production server directly.