Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Perverse Unreadable Code

by Anonymous Monk
on Apr 25, 2001 at 22:36 UTC ( [id://75563] : monkdiscuss . print w/replies, xml ) Need Help??

Being a new boy to Perl I find I come across plenty of code that is so compact it is on the whole unreadable and therefore un maintainable. I know some of the people on this site do this as a purely accademic exercise, but I have seen to many people doing this for real

Cramming lots of characters on 1 line does not mean things will compile better

I have also seen people doing horrors like putting if statements after the code to be excuted . WHY

Here another if(!$#var) .Yes Ok I know what it does but why do it ..

I don't want a headace everytime I read a piece of source code.

Perl is a high flexible language that seems open to abuse by those who thinks its clever to write unreadable code.

Perl is a great tool so why missuse it? For those who think themselves clever try reading this.


Edit by tye

Replies are listed 'Best First'.
Re: Perverse Unreadable Code
by tinman (Curate) on Apr 25, 2001 at 22:56 UTC

    Well, I think that your accusations are somewhat unfounded.. I have some sympathy to your point of view, especially if you're relatively new to Perl and shell script like languages... but here are some thoughts on this...

    Firstly, read perlstyle.. As in arhuman's sig, "Only Bad Coders code badly in Perl"... For the most part, I have found Perl to be a very concise and intuitively appealing language.. why I say this is because it has lots of constructs that are similar to natural language..and furthermore, you'll find the reference above gives an explanation for when "an if after the code" is appropriate....

    One of my coworkers *always* laughs when he sees "or die" and "carp" :o), but they accurately describe what the function is supposed to do, and that sounds like a good thing to me...

    Next, have you heard of the obfuscated C contest ? Look here for frightful examples of C code... its not just Perl, its any language you can think of, *every* language has the potential for bad code..

    Readability is a big big win, I don't dispute that.. but sometimes, what may not seem readable to you may well be easy to someone who has actually taken the time out to understand the construct...Perhaps you need to know a little bit more Perl ? things may suddenly become easier to read and understand when you've been exposed to the language a bit more.. I certainly found that to be the case for me...

    However, just so you don't get the impression that I'm dismissing your concerns, this is an article I think a lot of Perl programmers should read..especially if you write Perl code for a living...

    Finally, TIMTOWTDI applies to Perl code.. perhaps you can learn a more efficient way of doing something by looking at someone elses code.. I know I have...
    Update:Attributed sig to arhuman

      its not just Perl, its any language you can think of, *every* language has the potential for bad code..

      More precisely, any Turing complete language.

      This is the substance of the first really big theorem about computers, the Halting problem. If the language is general enough to even model something pretty simple, it is possible to give a series of instructions that no amount of analysis can answer even a simple question about.

      Yes thanks for your reply and I do take onboard that things will get easier as I learn a bit more Perl. Thanks for pointing me to the coding standards. I do currently follow our own works coding standards which are very similar.

      I can not for the life of me understand why people do not use strict and warnings. That's like turning up the stereo in your car so you don't here the engine grinding through lack of oil.

      What do you mean there is something wrong with my car, its moving isn't it. Yes but only just and when will it blow up?

      Don't get me wrong it isn't Perl I dislike. I come from a VB background a have found the use of regular expressions unbelievably powerfull and now use them in VB which is now availble by referencing the VBScript library.

      Thanks for your Comments I'll stick at it and may yet be converted!

      Edit by tye

(Ovid - accidental obfuscation?)Re: Perverse Unreadable Code
by Ovid (Cardinal) on Apr 25, 2001 at 23:17 UTC
    I strongly sympathize with your point of view. There are clearly those out there who write code that is not meant to be read. On the other hand, sometimes unreadable is churned out as a matter of course. From a program I'm currently writing:
    %author = map { /^\d{6}$/ ? $_ : [ split( /\|/, $_, 2 ) ] } map { split( /=/, $_, 2 ) } grep { /^\d{6}=[^|]+\|/ } <FH>;
    Frankly, I can't say that I'm happy with the illegibility that this code presents to the average programmer. Heck, a few months ago, I wouldn't even have been able to read it. Now, however, I sat down and simply wrote it out. There was only one bug (forgetting the third argument to split) and it worked fine.

    While I'll need to stop and read through that when I come across that again, it really seems to be the most straightforward "Perlish" way of writing that. Further, once one develops a high comfort level with Perl, such constructs become (dare I say?) natural.

    Much of the trouble that people have with such things stems from the large amounts of punctuation. This has the unfortunate side-effect of steepening Perl's learning curve. Your patience in learning such things, though, will reward you handsomely in the long run as your ability to harness the full power of Perl develops.

    Side note: do any monks use English for any production code? I've heard about the module and see how it makes Perl more legible, but I've never seen anyone actually use it.


    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Re: your code--I think that were I presented with the same problem I'd probably do it like this:
      my %author; while (<FH>) { next unless /^\d{6}=[^|]+\|/; my($l, $r) = split /=/, $_, 2; $author{$l} = [ split /\|/, $r, 2 ]; }
      I don't like temporary variables much, either, but this, to me, seems:
      • more readable
      • more efficient, both in terms of memory and "algorithm". Your code loops over the data three times (I think); the above would loop over it only once. Furthermore, your code loads the entire contents of FH into memory at the same time, while the above processes the file line by line.
      I'm not trying to bash you or anything. :) Readability is often a rather subjective thing, for one thing, and if you find your code more readable, that's fine.

      In terms of efficiency, though, I think the while loop probably beats a grep-map-map operation (read in reverse), unless there are other issues I'm not thinking about.

        This is a beautiful example of how we can mentally get into a rut and not "rethink" things. Your code is much easier to understand. Thanks!


        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

        Funny, I was thinking virtually the same thing myself looking at his code, but more along the lines of:
        my %author; while (<FH>) { next unless /^(\d{6})=([^|]+?)\|(.*)/; $author{$1} = [ $2, $3 ]; }
        Though perhaps I've missed something here.
                       s aamecha.s a..a\u$&owag.print
      do any monks use English for any production code?

      I don't even use it for test code :) It can make a script slower, especially if you are using regular expressions.
      Right from the POD:

      =head1 BUGS This module provokes sizeable inefficiencies for regular expressions, due to unfortunate implementation details. If performance matters, consider avoiding English.

      This is mainly (the RE part) because it brings $& $' and $` into the game.


      As mentioned in a /msg, I've seen some examples for XML::Parser that use it..You can find the link here... I think none of the examples for the current XML::Parser version use it though..

      Perhaps out of context, and it may have changed later, but this is a thread I found through Google on use English in Perl 6... Link to message archive is here..

      I've wanted to use English in the stuff I write, but I have enough trouble remembering magic variables as it is... so, doesn't look like it's going to happen anytime soon.. :o)

      Side note: do any monks use English for any production code?

      Yes, but not religiously. We use it for some of the lesser-used variables, such as saying $INPUT_RECORD_SEPARATOR instead of $/. But we still use $_ instead of $ARG.

        No, never. If I had to go through the trouble of learning all those arcane variables, why shouldn't everyone else?

      I suspect the redundancy and memory requirements in your one-liner is inefficient and that a while loop would be not only more efficient but more readable. Benchmark in progress ...

      Update:After reviewing the original, its not exactly the same, but I think still a fair enough comparision :)

      #!/usr/bin/perl -w # About the fairest comparison I could think of at the moment use strict; use Benchmark; my $file = "tst1.txt"; open(OUT, ">$file") or die "Can't open $file for output: $!"; for ("000000".."020000") { print OUT "$_=abc|def|ghi|jkl\n"; print OUT "Ignore this line\n"; } open(FH1, $file) or die "1 Can't open $file: $!"; open(FH2, $file) or die "2 Can't open $file: $!"; timethese(1, { MAPIT=>\&map_it, LOOPIT=>\&loop_it, }); close FH1; close FH2; sub map_it { my %author = map {/^\d{6}$/ ? $_ : [ split (/\|/, $_, 2 ]} map { split( /=/, $_, 2 ) } grep { /^\d{6}=[^|]+\|/ } <FH1>; } sub loop_it { my %author; while (<FH2>) { next unless /^(\d{6})=(.+)\|/; # Hmm, the above should really be: # next unless /^(\d{6})=([^|].*)\|/; # Whoops, forgot to limit the split to 2 elements here # No big deal, results are still similar $author{$1} = [ split(/\|/, $2) ]; } } # interesting different results #Under activestate perl Benchmark: timing 1 iterations of LOOPIT, MAPIT... LOOPIT: 5 wallclock secs ( 4.62 usr + 0.00 sys = 4.62 CPU) @ 0 +.22/s (n= ) (warning: too few iterations for a reliable count) MAPIT: 28 wallclock secs (28.73 usr + 0.00 sys = 28.73 CPU) @ 0 +.03/s (n= ) (warning: too few iterations for a reliable count) #under Cygwin perl $ ./tst Benchmark: timing 1 iterations of LOOPIT, MAPIT... LOOPIT: 4 wallclock secs ( 4.67 usr + 0.00 sys = 4.67 CPU) @ 0 +.21/s (n= ) (warning: too few iterations for a reliable count) MAPIT: 5 wallclock secs ( 5.22 usr + 0.00 sys = 5.22 CPU) @ 0 +.19/s (n= ) (warning: too few iterations for a reliable count)
(dws)Re: Perverse Unreadable Code
by dws (Chancellor) on Apr 25, 2001 at 23:44 UTC
    I have also seen people doing horrors like putting if statements after the code to be excuted.

    If the tools you've grown up with lack the descriptive power of Perl, you might well think that such a feature is a horror. But once you've done a bit of Perl and get used to it, you may find yourself cursing the lack of descriptive power of other tools.

    To my eye   print "About to fetch $url\n" if $debug; is more readable, and less disruptive to reading flow, than

    if ( $debug ) { print "About to fetch $url\n"; }
    As with any feature, this one can be abused. Which is why it's important to distinguish between the perversity of the tool and the perversity of the tool user.

      There are advantages in the:

      if ( $debug ) { print "About to fetch $url\n"; }
      approach, mainly because if I want to throw a few more statements into the "if" block, I can do it simply.

      I also find having the code structured that way indicates clearly that a conditional is involved, and by seeing what the condition is, it can often provide an indication of why something is being done. For example:

      if ( $account_balance < '100.00' ) { print "Don't pay the loser any interest.\n"; }
      indicates we are dealing with low value accounts.

      But then again, we are talking subjective matters here. An alternative way, and in my mind just as readible, is:

      &calculte_interest($account_number) unless ($account_balance < '100. +00' );

      As a side line, I recall being told once "Fortran programmers can write fortran programs in any language."

Re: Perverse Unreadable Code
by Chady (Priest) on Apr 25, 2001 at 23:27 UTC

    I couldn't help not noticing the :

    "I have also seen people doing horrors like putting if statements after the code to be excuted "
    where's the horror in that???

    Code is more aesthetical like this :

    if ($var) { &doSomthing; }
    has the (same) effect as:
    &doSomething if ($var);
    both are readable enough, and the second is closer to spoken language. and is less written code.
    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady |
      I've also heard this complain and I agree with you: it stems from people so used to other languages that it looks foreign.

      Personally, I tend not to put the if after the statement unless the statement will be executed most of the time. Then when it comes to maintenance and someone is scanning the code, they will often see that and understand that it's the norm rather than the exception.


      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      &doSomething if ($var);
      This was the construct that tripped me up the most, along with its brother unless, when being brainwashed coming over to perl.
      the typical
      if ($foo) { ... ... }
      sets the reader up -- he knows something might happen, but if he's unfamiliar with the alternate synax, that fact might pass him by. The end result is that I read code a little more thoroughly, and I've gotten used to it, so I guess it's not a total loss.
      I couldn't agree more with you. For instance, take the following function I wrote:

      for ( @status ) { my $pass = 0; chomp; # eliminate that nasty terminator! :) $_ =~ s/\0//; # Ignore the stuff that comes from this # command for now. Maybe later I will # use this information for something but # I will wait until a more mature release # of this code. if ( $watch ) { # I know this next section looks obfuscated # but actually, it was the easiest way for me # to accomplish my task here. # This block takes data that looks like this: # # player name number number # IPaddr number number <- one record # player name number number # IPaddr number number <- another record # # and parses out just the name per record # so that the array is now propagated with # player name <- from reocrd 1 # player name <- from record 2 # etc. # NOTE to self: You will probably need to get # the IP address at some point here! $pass = 1 if $pass == 0; $pass = 2, $_ =~ s/( .*).*// if $pass; $pass = 1 # place regex to extract IP here if $pass == 2; push( @player_info, $_ ) if $_; } # start counting after we see the "-"'s $watch = 1 if ( /-/ ); } if ( $#player_info >= 0 ) { return($#player_info + 1); } else { return(0); } }
      Notice the lil block of if statements?

      $pass = 1 if $pass == 0; $pass = 2, $_ =~ s/( .*).*// if $pass; $pass = 1 # place regex to extract IP here if $pass == 2; push( @player_info, $_ ) if $_;

      To me this seemed to be a much simpler block of code to write while at the same time not too difficult to understand what it was doing. Consider the alternative:

      A rough estimation of the translation of the above code (untested)...

      if ( $pass == 0 ) { $pass = 1; } elsif ( $pass ) { $pass = 2; $_ =~ s/( .*).*//; } elsif ( $pass == 2 ) { $pass = 1; } if ( $_ ) { push( @player_info, $_ ); }

      I'd be curious to know what others think.
      I wonder if I could have used the flip-flop operator here.

      - Jim

Re: Perverse Unreadable Code
by KM (Priest) on Apr 25, 2001 at 22:41 UTC
    I think some people a) think they are 'hiding' their code by making it annoying to read, or b) don't know how to code with style and maintainability in mind.

    I think that most of us who do this (Perl) for a living know better than to write mangled code. But, you can always pretty print the code and see how bad it really is :)


Abusus non tollit sum (abuse doesn't nullify usage)
by frankus (Priest) on Apr 26, 2001 at 16:20 UTC

    By the way, it should be:

    Brother Frankus.


Re: Perverse Unreadable Code
by Beatnik (Parson) on Apr 26, 2001 at 13:53 UTC
    You aint seen nothing yet !
    /me points to obfuscated code

    ... Quidquid perl dictum sit, altum viditur.
Re: Perverse Unreadable Code
by gregor42 (Parson) on Apr 26, 2001 at 18:20 UTC

    Being a new boy to Perl I find I come across plenty of code that is so compact it is on the whole unreadable and therefore un maintainable.

    Oh Brother __your_name__, at the risk of garnishing the mass disapproval of my brothers, I do contend with thee...

    ...If you're already interested in using English then I would suggest an alternative that is of somewhat greater benefit.

    Being a Consultant myself, I write lots of code for other companies & projects that I'll likely never see again. Also I end up working on code that others have written before that, at first make no sense to me whatsoever...

    So cut to the chase ... Use Comments

    gregor42 ducks behind a pew for flying --'s...

    What I mean by this is simply that if your are Yet Another Perl Hacker in a long chain of people who will eventually (ab)use, modify/torture, the code/project in the length of it's lifecycle, then you should put signposts on the trail.

    I hate to get all preachy & sound like a COBOL-pushing-compsci101 prof or anything, but if you write profuse comments you will be doing your clients & possibly yourself a service.

    As you reverse engineer how the code works you take notes & embed them in the code. These may help to serve someone else in the future; even yourself 6 months from now when you've forgotten how it works again.

    In the same spirit of generosity that makes Perlmonks a Great Community, I urge you to share what you learn as you go with those who know less than you.

    Yes, there's a lot to be said for style in writing code. But there's a lot to be said for using something like perldoc to your advantage to keep your comments where they belong, in the code, so they're maintained as you go, as well.

    As far as deliberate Obfuscation.. Well I LOVE it. I can think of no better way to force yourself to dig through text & learn. But then again, there's a time & a place for everything & unless you're really worried about job security, you shouldn't ever use it in production code. (:

    Wait! This isn't a Parachute, this is a Backpack!
Re: Perverse Unreadable Code
by pileswasp (Monk) on May 09, 2001 at 19:58 UTC
Re: Perverse Unreadable Code
by zigster (Hermit) on Apr 26, 2001 at 16:16 UTC
    I have great sympathy with your perspective, and on some levels I agree with you. Bad perl code is very bad.

    I had a discussion regarding perl with a friend whose opinions I respect. He suggested that often when I look at perl and see it as line noise I am missing many subtleties because of my inexperience with the language. This is a point I had not considered but one I have sympathy for. Good code is a universal concept, universal across all languages. Good code comunicates intent along with performing some function. The (valid) critique you were making is that on occasion that intent is not as clear as it could be. It is possible, for ME at least, that sometimes the intent is clear I just cant read it? I understand the individual subs and symbols but do not YET fully understand the idioms and patterns of perl. Tiss a thing I am still learning.

    Most other languages I use the symbols and methods dictate the flow. Perl is more subtle and complex the symbols and subs combine to produce the flow it is only with experience that full apreciation is possible. I almost thing that perl should be marked as a catagory aside a special methodolgy not complex or clever just different. More akin to natural languge where the context is as important as the symbol.