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

This could easily be a book review (in fact, it is), but it falls readily under the category "meditation" as I'm going to discuss the impact of bad books.


You can get an idea of the "quality" of the book "PERL in easy steps" by reading the blurb from the publisher's Website:

"PERL in easy steps" instructs the reader how to write Common Gateway Interface (CGI) scripts in the popular Practical Extraction & Reporting Language (PERL). These allow the exchange of data between a web browser and a web server both on Windows platforms and on Unix-based platforms, such as Linux. The book contains exciting chapters on the major features of the PERL language and there are complete example scripts that illustrate each aspect of PERL.

While that hints at the quality of this work, here are a few choice items from the book (copyright 2004!)

  • "for" is for C-style loops and "foreach" is for iterating over arrays.
  • Slices? They've been renamed "subarrays" (though the word "slice" is correctly used in other parts of the book).
  • Matt's Script Archive is one of the top three recommended PERL (sic) resources.
  • What's "strict"?
  • Who cares if open FH, $file succceeded?
  • CGI.pm? Nah! This book includes its own lightweight and buggy form parser.
  • I found no mention of security (including taint mode).
  • Standard web form counter errors (race condition).
  • Incorrect use of "flock" (race condition).
  • It's real fun reading <a href="http://localhost/cgi-bin/hello.pl">Click</a>
  • Why are we explaining "pack" to new programmers?

(There's more in my use.perl journal.)

This is probably one of the worst Perl books I have ever had the misfortune to stumble across but after my harsh review of Perl and CGI for the World Wide Web, I realized that it's terribly unfair of me to be rude to folks who have put so much effort into writing a book. In fact, Elizabeth Castro did a decent job of improving the second edition of that book, so she clearly listens to feedback. However, in comparing the first edition of the Castro book and comparing it to "PERL in easy steps", Castro's book comes off looking fairly good.

The author, Mike McGrath, of "PERL in easy steps" presents a lot of factually incorrect information and anyone trying to learn Perl from this book may conclude that Perl is garbage. If this is their only exposure, I wouldn't blame them. Books like this are a huge disservice to the language and the community and I'm embarrassed to see that books this bad are still being produced.

Fortunately, most professional programmers have learned which publishers they can trust and which they cannot. Unfortunately, those who want to learn programming don't know this and inexpensive books which promise to be "easy" are some of the first they reach for. Perl winds up getting another new programmer who writes bad code and further hurts the reputation of the language.

The underlying problem with this book is not the simplicity of the code presented. It's the quality of the code. Needless to say, the quality is very, very poor. This raises an interesting question. If we say "baby Perl is OK", why are we so harsh on baby Perl?

Years ago I stopped studying the martial arts in large part because of the hypocrisy. Martial artists would claim that the arts are about learning that you don't need to fight but they would quickly follow this up with "my sifu can kick your sifu's ass". They often wouldn't even recognize the irony when it was pointed out to them. Unfortunately, this often applies to Perl programmers. "Baby Perl" is OK but we often savage it.

There's nothing wrong with "baby" Perl. There are plenty of things wrong with "bad" Perl, but how do we distinguish them? Is it lack of "strict"? No. Removing "use strict" from an otherwise solid program does not suddenly turn it into terrible code. Using functions instead of methods is not a "bad thing". But what makes "good" baby Perl instead of "bad" baby Perl? Frankly, I'm not sure. Surely it's not fair to castigate someone for not knowing as much Perl as we would like, but when does ignorance of a better technique mean their technique is bad? That's where I'm stumped.

Cheers,
Ovid

New address of my CGI Course.

Replies are listed 'Best First'.
Re: "Baby" Perl versus "Bad" Perl
by xdg (Monsignor) on Dec 04, 2005 at 15:11 UTC
    But what makes "good" baby Perl instead of "bad" baby Perl? Frankly, I'm not sure.

    A lot of responses so far focus on the "bad". Maybe this question above is one worth answering?

    My wife and I are not (yet) blessed with children, but in the last few years, many of our peers have had their first child and very roughly speaking, this is the kind of progression I've seen in how they talk to their children:

    • Before the child is speaking: lots of "baby-talk" -- funny tone of voice, some nonsense words, etc.
    • When the child can say a few words: less baby-talk and more short phrases with simple words, not always gramatically correct (verb tenses seem to get simplified)
    • As the child starts talking: Gramatically-correct English beginning with simple words and structure and gradually gaining complexity as the child's own vocabulary and skills improve.

    The other interesting thing is when/how corrections happen and it's usually not until the child is really speaking on their own and can comprehend the correction. Up until that point, the approach seems to be to model the desired behavior -- staying about one step ahead of the child in terms of the complexity and correctness.

    Ignoring books for the moment, consider the typical response on Perlmonks to a posted question with "baby" Perl. For example, a question about why an array doesn't get what is expected with a simple syntax error in the middle causing the problem:

    # lots of baby perl... @my_list = 1, 2, 3; # lots of baby perl...

    Not only will the error get pointed out many times over, there will usually be at least one response that more or less says (sometimes directly) "your code sucks" and points out a litany of bad/awkward practices, re-writes the code, points out that they should use a CPAN module instead, or reduces the whole thing down to an elegant one-liner.

    I don't think that necessarily helps people learn. Extending from the real "baby-talk" analogy, the degree of correctness and complexity really ought to be tuned to the level of the person posting. Admittedly, this is often hard to tell from a post. But I don't ++ a post if looks like someone is trying to show off by bashing an obvious beginner. (There's a good martial arts analogy there, too.)

    To me, good "baby" Perl is just simple Perl. It might do something in a longer way (e.g. loops vs map/grep). It might not always reflect best practices (e.g. checking for error on open). It might not utilize more advanced syntax/features (e.g. slices or regex).

    This is different than "foreign" Perl, which uses complicated concepts and approaches for other languages instead of more natural Perl expressions. The classic example is the C-style for counter. The longer version is harder to teach than the shorter version.

    for ( my $i = 1; $i <= 10; $i++ ) { ... } for ( 1 .. 10 ) { ... }

    One of the reasons that I think that Learning Perl is such a great book is that it actually teaches baby Perl -- or a progression through it. For example, strict doesn't come up until page 63 of 228 (not counting appendices) -- a lot of perfectly good "baby" Perl is shown without being pedantic about strict. As another example, files are opened first without checking for errors, and then error checking is added a couple pages later, but with this cumbersome approch (p.83):

    if( ! open LOG, ">>logfile) { die "Cannot create logfile: $!"; }

    Why not "or die"? Because more advanced control structures don't get introduced for another 52 pages and the idiomatic "open or die" isn't shown for another 17 pages after that. The book speaks in good baby Perl until the reader is ready for more advanced concepts.

    Ovid ended with this question:

    when does ignorance of a better technique mean their technique is bad?

    There is a difference between ignorance and error. Most of the examples about the book aren't examples of ignorance, they are examples of error. Or, perhaps its better said that they are examples of ignorance, but they show ignorance of correct technique, not better technique. Someone writing a book shouldn't be ignorant. Someone learning Perl usually is.

    As monks, we should recognize that ignorance of better technique is part of the learning process, and we should tune our responses to questions to help the questioner learn at a level they can absorb, not demonstrate our mastery of better techniques. These are not always the same thing.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      ++ What a great analogy, and an excellent write-up!!
      As monks, we should recognize that ignorance of better technique is part of the learning process, and we should tune our responses to questions to help the questioner learn at a level they can absorb, not demonstrate our mastery of better techniques. These are not always the same thing.

      Very well said!

      I can relate to this, because as Perl novice I often find that some responses to questions that I have asked have gone completely over my head. And I'll also admit that I sometimes fall victim to the trap of trying to be too "clever" in response to a posted question. (heh.. although at my level of competence - tying to look clever almost inevitably makes me look downright dumb)

      FWIW, that progression is considered to be a bad idea. Children learn by imitation. Making noises and speaking in nonsense words to them certainly does not help them, and may actively set them back. You should start out right at stage 3 of your progression: correct use of language with simple grammatical constructs and vocabulary.

      It’s no coincidence that this is also the way to help an immigrant learn the local langauge quickly: no pidgin, just speak a little slower so that they can follow.

      (In fact, experience with parents teaching their babies sign language provides evidence that babies have linguistic skills pretty much from day one, long before they learn to speak. See some first-hand experiences.)

      Makeshifts last the longest.

        ...no pidgin, just speak a little slower so that they can follow.

        Damn straight. Reminds me of a quote-

        ...speaking with that omission of syntax stupid people employ when talking to drunken people or foreigners.
Re: "Baby" Perl versus "Bad" Perl
by dragonchild (Archbishop) on Dec 03, 2005 at 23:09 UTC
    Let's say you have two children. One is 8 and the other is 3. They both exhibit the same kinds of behavior - drawing on walls, throwing tantrums, willful disobedience, and the like. Which is bad and which is the baby?

    On one level, both are behaving badly and, as such, shouldn't be taken to a restaurant. However, that kind of behavior is expected for the 3yr old and not expected for the 8yr old. Why? Because the 8yr old is expected to have matured and (mostly) grown out of that phase. And that is the difference between "baby Perl" and "bad Perl." If you are a newbie, then your Perl is baby Perl. If you are a supposed expert (as all authors are supposed to be), then your Perl is bad Perl. Neither would be allowed on my boxes in a million years, but one is expected behavior and the other is not.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      I don't think your criteria is very good. You seem to be saying that whether Perl code is "baby" or "bad" depends on the experience of the programmer. I don't think that's true. "Baby Perl" can be distinguished from "Bad Perl" without asking the developer how long he has been coding.

      I think that there are things that mark code as bad. Incorrect code is bad. Insecure code is bad. Code with significant performance problems is bad. Code that is difficult to maintain is bad.

      But there can be "baby" Perl (or any programming language) that exhibits none of those problems. It might be simplistic and lacking in idiomatic expression. It probably doesn't use any "advanced" language features. But none of that makes it bad.

      BTW, I'd much rather deal with a junior programmer who is writing "baby" Perl (good or bad) than any programmer writing bad but "advanced" code. ;-)

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: "Baby" Perl versus "Bad" Perl
by Your Mother (Archbishop) on Dec 04, 2005 at 02:13 UTC

    And to think I decided not to try to write a Perl book a couple of years ago because I was scared the code wouldn't be good enough. :)

    On the OT of martial arts. I was a guest student at a Goju school, my background is mostly Taekwondo. One of the senior students, who I outranked slightly, chatted me up, commenting how he found Taekwondo practitioners were the easiest to beat at tournaments. I said something like, "Oh. I see," and never said anything else about it to anyone. A couple days later the head instructor calls me into his office and says, "I heard you had a little trouble with ______. I completely apologize and it's been taken care of."

    There are good schools in all arts and they invariably have that kind of instructor; one who knows everything that's going on and won't tolerate disrespectful BS. You should go back if you can find a school like that.

      I agree too!

      'Hell is full of people with good intentions.'

      I guess that it all depends on the target that the writer is pointing to.

      If you read a book of someone that is teaching perl to crack certain machines and steal something. You would not be able to judge him as a good or bad perl evangelist, because:

      • 1) He has surely proved that his code works like he wants to. And his readers buy his book because they know what he did with perl.
      • 2) It is not supposed to be good code. It is not targeted to all the world.
      Like any other piece of comunication. It all depends on one's own common sense. Or at least, on the money invested by people that know nothing about programing :)

        It is not supposed to be good code. It is not targeted to all the world

        That's kind of like saying: "The Feces Cookbook" is a fine piece of writing because it's not targeted to all the world.

        We generally only tolerate this low quality of writing in journalism. Technical books of any sort are, and should be, held to a higher standard.

Re: "Baby" Perl versus "Bad" Perl
by jonadab (Parson) on Dec 04, 2005 at 18:46 UTC
    But what makes "good" baby Perl instead of "bad" baby Perl? Frankly, I'm not sure.

    It's a lot of little things. Baby Perl can legitmately get away with a lot of things. For instance...

    • Baby Perl may not make much use of references.
    • Baby Perl usually doesn't attempt to use the Perl5 object model at all, even when it would be a good way to solve the problem at hand.
    • Baby Perl does not make significant use of standard Perl idioms (e.g., the orchish manoeuver, the Schwartzian Transform), even when they are a perfect fit for the problem.
    • Baby Perl frequently misses good chances to use some of the nicer conveniences Perl provides, such as implicit $_, well-known (or even core) modules, list handling (especially map and grep), builtins that duplicate OS functionality but in a cross-platform way, and so on.
    • Baby Perl may read like a first-grade primer:
      There are many statements.
      They are short.
      They are simple.
      Each one is on its own line.
      
      $foo = $foo + 1; print "There are now "; print $foo; print " foo items, for a total of "; $total = $foo + $bar; print $total; print " items altogether.\n";
    • Baby Perl may leave out comments it should include, or include comments that are needless, especially ones that duplicate the language documentation, e.g., telling what a builtin does. A more experienced programmer would leave these out and instead put in comments that explain at a higher level what the code is accomplishing or why.

    On the other hand, *bad* Perl isn't just simplistic; it's plain wrong. Some examples...

    • Bad Perl may try to use Perlish features but gets them wrong, e.g., attempting to use slices and messing it up.
    • Bad Perl tries to write at a level significantly beyond the programmer's competence in the language, by assuming things must be the same as in some other language the author had previous experience writing; instead of many short statements, now we may combine them in a way that changes the execution order incorrectly, provides something the wrong context, or some similar mistake.
    • Bad Perl doesn't just miss chances to catch mistakes; it actively *avoids* them. For instance, while baby Perl may not always check return values where a more experienced programmer would, bad Perl may actually throw an eval { } around something that may die and then never check the result, relying on it to work lest the following code mess something up.
    • Bad Perl may contain comments that are actively misleading.

    If I had to summarize the difference, I think it has a lot to do with things that aren't specific to the Perl language. Baby Perl doesn't necessarily do things in the best or most Perlish way, but it does them in a way that works, as far as it goes. Really bad Perl does stuff that wouldn't be okay in any language, or that doesn't even work correctly.

      Baby Perl usually doesn't attempt to use the Perl5 object model at all, even when it would be a good way to solve the problem at hand.

      What's the Perl5 object model? I don't really think this applies in any case. OOP can be "baby" or "bad" in the same way that structured programming can be. Whether it is used to solve a problem has nothing to do with whether the code is good or bad, baby or fluent.

      They are short.
      They are simple.
      Each one is on its own line.
      

      Those three might just as well be a hallmark of good Perl.

      Baby Perl may leave out comments it should include, or include comments that are needless, especially ones that duplicate the language documentation, e.g., telling what a builtin does.

      Maybe "baby" is the reason but "bad" is the result.

      -sauoq
      "My two cents aren't worth a dime.";
      
        OOP can be "baby" or "bad" in the same way that structured programming can be.

        Hence the qualification, even when it would be a good way to solve the problem at hand. Some problems do naturally lend themselves to OO, although of course most don't. It's not something you need to learn in your first couple of years of programming in Perl, but eventually you pick it up and add it to your tool belt.

        [short, simple sentences] might just as well be a hallmark of good Perl.

        Are you seriously arguing that the example I gave of what I was talking about constitutes good code, or are you just trolling?

        Regarding simplistic comments:

        Maybe "baby" is the reason but "bad" is the result.

        I guess that depends on who's most likely to need the comments, the baby programmer himself, or someone else. Bear in mind, for someone new to a language, comments that remind what even a simple, built-in feature does can be useful. A more experienced programmer just *knows*, of course, and you wouldn't want to see such comments in important code -- but important code should be maintained by experienced programmers in any case. I don't think it's bad, when learning a language, to use comments as a reminder to oneself of language features. I do think you want to grow out of that as you gain more knowledge of the language, of course.

Re: "Baby" Perl versus "Bad" Perl
by itub (Priest) on Dec 03, 2005 at 23:19 UTC
    "for" is for C-style loops and "foreach" is for iterating over arrays.

    I'm confused--what's wrong with that? That's the convention used in the perldocs, isn't it? (I personally always type "for" out of laziness, but I don't complain if someone prefers to type "foreach" to iterate over an array).

      There's nothing wrong with using that as a convention. However, there is no behavioral difference between "for" and "foreach". Teaching that they aren't the same thing is wrong.

      Cheers,
      Ovid

      New address of my CGI Course.

Re: "Baby" Perl versus "Bad" Perl
by Your Mother (Archbishop) on Dec 04, 2005 at 07:57 UTC

    I couldn't resist a few alterations.

    • "for" is for C-style loops and "foreach" is for iterating over arrays.
    • "for" is for piece-rate work and "foreach" is for contractors who charge by the hour.
    • Slices? They've been renamed "subarrays" (though the word "slice" is correctly used in other parts of the book).
    • Slices? Greek? Pad Thai?
    • Matt's Script Archive is one of the top three recommended PERL (sic) resources.
    • Matt's Script Archive, AKA Satan's Scriptorium, top recommended site for increasing SPAM traffic.
    • Who cares if open FH, $file succceeded?
    • Not me! I don't even care if fork() while 1 works! DO NOT RUN THAT!!!
    • Why are we explaining "pack" to new programmers?
    • Silly! So they'll understand what they hear from their manager after they write their first script; i.e.: "Pack your bags."
Re: "Baby" Perl versus "Bad" Perl
by Anonymous Monk on Dec 05, 2005 at 19:31 UTC
    Well, "Baby" Perl is perl that's written with simple (excessively simple) constructs. It's flaws are created largely out of ignorance.

    "Bad" Perl is perl that is flawed in other ways; such as using fundamentally flawed algorithms; advanced coding techniques used for obfuscation purposes in production code; parsers and lexers built into the code to handle a configuration file that holds only constants; and so forth.

    In other words, truely bad Perl is perl that would remain bad even if refactored, or translated into a completely different language.

    "Baby Perl" is just inexperience with Perl idioms; which isn't always a bad thing. I often try to avoid using complicated features of perl when simple features will do the job; the less I have to *think* about the code to make sure that my clever tricks really work; the easier the code is to maintain. I'd rather have three lines I can read than one I can't; but obviously excessively verbose code imposes it's own inherent complexity, so there's a balance to be struck. I try to code to the level of the person who I anticipate will maintain the code. In some respect, my Perl resembles "Baby Perl" by design. I only use features that a novice might misunderstand when it would make the code awkward not to do so, and whenever I do something "clever", I know I'll pay for it later. Six months from now, I'll probably have to explain what I did to a confused maintainer, and while comments help, I'll still have a mini-training excercise on my hands. I do like teaching, but my company is losing money when I give out free training like that, because my time and my co-worker's time could be spent elsewhere more profitably.

    So, to recap: "Baby Perl" arises out of ignorance, and is solveable. "Bad Perl" arises out of incompetance or malice, and is not. Having dealt with too much bad Perl lately (6,000 line loops with eight levels of indentation, formatted inconsistantly with typically only 2 column indentation is... bad practice. Exporting local package variables into every single namespace instead of using a global variable in the first place is ... bad design. Making your fundamental data structures tied hashes with a rat's nest of internal function calls, with wierd side effects is... bad design. Localizing various sections of a data structure to modify the impact of key function calls is bad design. Putting your date/time handling code into a custom Perl-XS module that's (a) buggy, and (b) incompatible with the perl version in production is bad practice, given the tonnes of date handling routines on CPAN.

    Failing to "use strict" because you don't know it's there in a ten line perl script is not so bad. Failing to use strict because you're too lazy to use it in a 10,000 line perl project is bad.

    Just my $0.02

    --
    Ytrew Q. Uiop

    P.S.: On martial arts: I disagree with your premise that Martial artists would claim that the arts are about learning that you don't need to fight. Martial arts teach awareness of how you need to fight; including what degree of force is required or appropriate to a given situation. If a little child attacks an adult, we don't try to kill it; we just stop the attack, and scold the child.

    If an adult attacks a martial arts master with a credible threat, the adult will find that the master will defend him/herself using such violence as is appropriate to the situation. The only difference between "ordinary people" and "enlightened" martial arts masters is that a martial arts master has less risk of being hurt by a given attack due to superior skill; and can risk being more lenient while remaining safe.

    If the martial arts master was a true pacificfist, (s)he wouldn't have needed to learn how to kill and maim in the first place, before advocating "peace". Remember that the word "martial" means "warlike", and that "martial arts" were the killing tactics used on the battlefields in Asia. Traditions on how to kill with a sword, spear, staff, or with one's bare hands are very insightful, but they were never peaceful in origin or intent. It's easy to romanticize a violent tradition (like "knights in shining armour"), but a history of violence remains violent.

      I really like everything you have to say with one major exception.

      It is both possible and common for bad Perl to arise out of fixable incompetence. In which case you fix the cause of the incompetence, and you stop seeing so much bad Perl. For instance the person programming may not have a programming background, and so has never learned the value of good variable names, when to use functions, and so on. Or the person has just been exposed to a whole lot of neat things and wants to use them all at once. A little more experience and this enthusiasm likely will get tempered to more manageable levels. And so on.

      I am not saying that every producer of bad code is educable. But enough are that it is worth at least making the attempt.

        It is both possible and common for bad Perl to arise out of fixable incompetence. In which case you fix the cause of the incompetence, and you stop seeing so much bad Perl.

        Hmm... how does "fixable incompetence" differ from simple ignorance? Incomptentence, to me, implies an inability or outright refusal to learn competent behaviour.

        For instance the person programming may not have a programming background, and so has never learned the value of good variable names, when to use functions, and so on.

        In which case, the incompetence lies as much with HR as with the so called "progammer". Only hire people who can do the job you require of them; if you need to train them on the job, budget the time and resources for it!

        Or the person has just been exposed to a whole lot of neat things and wants to use them all at once. A little more experience and this enthusiasm likely will get tempered to more manageable levels.

        A professional does what is good for his client, not just what's fun for himself. This lesson should be learned long before reaching the workplace, IMHO. Refusing to learn it does smack of incompetence, to me.

        --
        Ytrew

Re: "Baby" Perl versus "Bad" Perl
by tphyahoo (Vicar) on Dec 05, 2005 at 09:13 UTC
    Maybe...

    Baby perl doesn't use shortcuts. EG, doesn't use references, and if it does use them it uses them verbosely: ${$ref} not $$ref. Doesn't use methods, just subs. Doesn't use the "pronouns", eg $_, @_. Or better put, uses them a little bit, but quickly sets them to vars so that the baby doesn't have to look at something that looks like punctuation.

    for with a test instead of grep. for instead of map.

    On the other hand, basic things, like avoiding overuse of global variables, should be observed even by a "baby."

    And I disagree that use strict shouldn't be expected of babies. If you see your baby crawling towards a glowing fireplace with a goofy smile on his face, you would stop him and yell at him not to do that again, no? Same thing.

      If you see your baby crawling towards a glowing fireplace with a goofy smile on his face, you would stop him and yell at him not to do that again, no?

      "The burnt hand teaches best" :-)

Re: "Baby" Perl versus "Bad" Perl
by Anonymous Monk on Dec 06, 2005 at 20:17 UTC

    This article has prompted me to look back at some of the stuff I wrote four years ago as a "baby". What strikes me about my baby code is:

    1) Many of the comments were for my benefit as a "baby".
    2) I did indeed use lots of simple statements.
    3) I did avoid the use of the perlish symbols, $! and so on, and used "use English" and English names instead.
    4) I wrote alot of subroutines that implemented funtionality in other languages and systems that I was comfortable using and knew well, rather than learn the perl or unix way of doing things. This was a matter of expedience. I had to get the job done quickly and this helped. In retrospect the code looks just awful and could be improved.
    5) I did use "use strict;" and -w

    I'd say that it's fair to castigate someone for doing things badly if it's apparent that they have no desire to do things well and to learn, but give the "babies" a break as they are mostly just trying to grow up.

Advantages of "Baby" Perl
by fraktalisman (Hermit) on Dec 29, 2005 at 11:15 UTC

    "baby perl" can have certain advantages, like

    • unexperienced programmers writing "baby perl" instead of trying to code something which goes above their level of understanding, thus avoiding a wide range of potential errors
    • coworkers with only rudimental understanding of perl can better understand the code in case they have to make little changes later
    • the same goes for the unexperienced programmer when reviewing or debugging the code
    fraktalisman keeps rolling
      The problem is, in my experience the coders won't find the obvious, easier, cleaner or efficient (in any mystical meaning of the word) way but that one *they* understand. I work with some people who aren't that much into Perl as I am, and they use only those syntactic sugars of Perl which they know from PHP. Maybe they find it more readable, but you should see what some people produce when trying to avoid using map, grep and such alike :)

      Ordinary morality is for ordinary people. -- Aleister Crowley