"If you can't speak the language, get out of the editor" --or-- "Don't write Perl if you can't write Perl"



  • My team has recently inherited a steaming pile of WTFery.  Everything around this application absolutely sucks.  It was written in C by non-programmers, so naturally it crashes several times a day.  Finding this perfectly acceptable for mission-critical software, no effort was put in place to fix the years-old software.  (It was written in the late 90s.  And it's still mission-critical.)  Instead, a monitoring system was built to make sure the program is running and restart it when it dies.  Unfortunately, the monitoring software was also pretty questionable, so another monitoring system was put in place to monitor the monitor.  As one might expect, this didn't always work either.  But it has a happy ending: since then, I have replaced the junk monitors with my own, which of course does work.  (But sadly, I do not know C well enough to find all the original bugs.)  But that's all background information, here today is some actual code from some of the support software of the first monitor.

    Yes, it's written Perl.  No, TRWTF is not Perl; I love Perl thankyouverymuch.  And let's just get the obligatory "it looks like line noise hur hur hur" / "write-only language hur hur hur" bit out of the way.  Ok, disclaimer dispatched.  Let's go.

    First, some appetizers:
    These are the first lines after the boilerplate:

    package WtfLib;

    $WTFLIB::GLOBAL_DEBUG = 0;

    Yes, the package uses lower case, but the namespace of GLOBAL_DEBUG is in upper case.  Looking through the file, EVERYTHING is using the upper case namespace.   These aren't the namespaces you're looking for...  Move along, move along...

    Scrolling down a bit...  (Fore-hint: cwd() does the same thing as cwd in ftp: returns the current working directory.)

    $WTFLIB::HTTP_PATH = join('/', split('/', cwd(), 3));

    Err...  Wtf?  WHY!??

    (Lest the '3' in the argument confuse you, this splits the path a list of at most 3 elements -- if there are more delimiters after the three, it doesn't throw them away, it just takes the remaining string as the third element. And then the statement joins them back up again. Go ahead and run

    perl -e 'use Cwd; print join("/", split("/", cwd(), 3));'
    anywhere on in path: it will always return the same as cwd().)


    After those two bites, here's the main course.  This is the subroutine that nearly made me fall out of my chair.  Hold on to yours.

    #***************************************************************************
    # Function:            Change_Case
    #    Synopsis:            Used for changing case
    #    Parameters:        $str, $case
    #    Description:    Takes $str, if $case equals "upper", changes $str to upper
    #                                case.   If $case equals "lower", changes $str to lower case.
    #
    sub Change_Case {
    # change Case
        my($str, $case) = @_;

        $case =~y/A-Z/a-z/;
        if ($case eq "upper") {
            $str =~y/a-z/A-Z/;
        } elsif ($case eq "lower") {
            $str =~y/A-Z/a-z/;
        }
        return $str;
    }


    This library is only used in one script.  Change_Case is only used ONCE, and its usage is in the library.  Here's the line that leverages this enterprise technology:

    $language = &Change_Case($language, "upper");


    And for those of you unfamiliar with Perl, here's the spoiler: http://perldoc.perl.org/functions/uc.html and http://perldoc.perl.org/functions/lc.html


    This monitoring program was designed to check if another program is running or not.  In case you're wondering why such a monitor needs needs a HTTP_PATH variable or needs to change the case of a language variable, well, ... that's an exercise for the reader.  And/or management.

    There are a million more WTFs in this library, such as its bizarre mix of HEREDOCs and line and lines of string literal concatenation.  I'll post more if this one's a hit.

    Oh, just found another.  One of the lines in this library is just 304 tabs in a row.  The line after it is 300 tabs in a row.  Sure, whatever.



  •  

    # Function:            Change_Case
    #    Synopsis:            Used for changing case

    Whodathunkit?

    @Xyro said:

    'll post more if this one's a hit.

    Looks promising. I'd like to have a second helping.



  • #***************************************************************************
    #    Function:            Is_Blank
    #    Synopsis:            Used for checking blank fields.
    #    Parameters:        $param, $mesg
    #    Description:    Takes $param and checks if it is blank.  If it is blank,
    #                                and $mesg is blank, returns 'NA'.  If $param is not blank
    #                                and $mesg is blank, returns $param.  If $mesg is not blank,
    #                                returns $mesg.
    #
    sub Is_Blank {
    # return mesg or 'NA' if param is blank
        my ($param, $mesg) = @_;
        my $cmpstr;

        $cmpstr = ' ' x length($param);
        if ($cmpstr eq $param) {
            if (!$mesg) { $mesg = 'NA'; }
            return $mesg;
        }
        return $param;
    }



  • Here's another snippet of doom.  It's found right after a lengthy heredoc (which included the inexplicable hundreds of tabs).  Why they didn't just continue the heredoc, I can't speculate.  Oh, quick aside:  Every line in the heredoc was appended with a "\n".  Yeah.

    Ok, so this is never a good thing:

    # Round top of label
    $htmlStream .= "   <TR><TD align=center valign=top colspan=3>\n";
    $htmlStream .= "     <TABLE width=88% border=0 cellspacing=0 cellpadding=0 bgcolor=#BBC4EE><TR><TD align=center valign=top><IMG src=$WTFLIB::internet_loc/template/images/%pixel.gif width=1 height=1 border=0 hspace=0 vspace=0></TABLE>\n";
    $htmlStream .= "     <TABLE width=92% border=0 cellspacing=0 cellpadding=0 bgcolor=#BBC4EE><TR><TD align=center valign=top><IMG src=$WTFLIB::internet_loc/template/images/%pixel.gif width=1 height=1 border=0 hspace=0 vspace=0></TABLE>\n";
    $htmlStream .= "     <TABLE width=95% border=0 cellspacing=0 cellpadding=0 bgcolor=#BBC4EE><TR><TD align=center valign=top><IMG src=$WTFLIB::internet_loc/template/images/%pixel.gif width=1 height=1 border=0 hspace=0 vspace=0></TABLE>\n";
    $htmlStream .= "     <TABLE width=97% border=0 cellspacing=0 cellpadding=0 bgcolor=#BBC4EE><TR><TD align=center valign=top><IMG src=$WTFLIB::internet_loc/template/images/%pixel.gif width=1 height=1 border=0 hspace=0 vspace=0></TABLE>\n";
    $htmlStream .= "     <TABLE width=100% border=0 cellspacing=0 cellpadding=0 bgcolor=#BBC4EE><TR><TD align=center valign=top><IMG src=$WTFLIB::internet_loc/template/images/%pixel.gif width=1 height=1 border=0 hspace=0 vspace=0></TABLE>\n";
    $htmlStream .= "   </TD></TR>\n";

    (And no, there is no such file as "%pixel.gif".  So you can probably imagine the rendered output of this quality enterprise solution.)

     

     Edit:   It just occurred to me, %pixel will be interpolated by Perl as a hash which will be coerced into a scalar.  There is no such %pixel hash (and you'd be out of your mind if you think they declared "use strict;"), so the output just becomes ".gif".  But that's okay, there is no ".gif" file either.


  • 🚽 Regular

     I hate to defend the original coders, as the other WTFs you showed us are definitely worthy of a WTF, but besides the use of %pixel, the table approach was really the only way to have snazzy rounded corners back in the late-90s. We take for granted our CSS and (mostly) HTML-compliant browsers we have today, but back in the old days, tables and god-awful HTML was what it took to layout a webpage that has anything as complicated as rounded edges and "cool looking" buttons.



  • @Xyro said:

    Here's another snippet of doom.  It's found right after a lengthy heredoc (which included the inexplicable hundreds of tabs).  Why they didn't just continue the heredoc, I can't speculate.  Oh, quick aside:  Every line in the heredoc was appended with a "\n".  Yeah.

    Ok, so this is never a good thing:

    # Round top of label
    $htmlStream .= "   <TR><TD align=center valign=top colspan=3>\n";
    <snip>

    They did that because they didn't know how to do

    $htmlStream = <<"HEREDOC_END";

    (Yes, I know that one can leave off the double quotes and get the same effect.  However, they obviously thought that the here document always acts like it does if it's single quoted.)



  • @tgape said:

    @Xyro said:

    Here's another snippet of doom.  It's found right after a lengthy heredoc (which included the inexplicable hundreds of tabs).  Why they didn't just continue the heredoc, I can't speculate.  Oh, quick aside:  Every line in the heredoc was appended with a "\n".  Yeah.

    Ok, so this is never a good thing:

    # Round top of label
    $htmlStream .= "   <TR><TD align=center valign=top colspan=3>\n";
    <snip>

    They did that because they didn't know how to do

    $htmlStream = <

    (Yes, I know that one can leave off the double quotes and get the same effect.  However, they obviously thought that the here document always acts like it does if it's single quoted.)

    I thought for certain I'd checked that in preview.  Let me try it again...

    $htmlStream = <<"HEREDOC_END";


  • However, in other places they do use $htmlStream .=<< HEREDOC_END; with variables in place.  I can understand learning the language as you go,  who hasn't made those same sorts of mistakes before?  But then after you learn, you're supposed to correct those mistakes, right?

    @RHuckster said:

    the table approach was really the only way to have snazzy rounded corners back in the late-90s

    Yeah, I suppose you are right.  Although they could have at least used the scripting language's power to make the string literals less ugly.

    Consider this, though: the question such an analysis should be provoking is, "Why are they sending out snazzy rounded corners from a monitor program?".  The answer to which is too horrible/wonderful to say.

    Ok, I'll say it.  The monitor was entirely HTTP driven.  Another program was used to GET the results from the Perl script at a frequency of every minute in order to screen-scrape the output from the result of the monitor's test.  Tee hee.  THAT program would be the one that actually instigated the restarts.

    The chain goes likes this:

    [A program that automatically sends HTTP requests] -> [local IIS instance] -> [The Perl script that uses this lib] ->  [A Java program so badly written that it occasional hangs itself somehow] -> [bad old C program that crashes several times a day]
    and then back up the chain.

    The insanity doesn't stop there though!  But I can't share all of this at once, it would just be too much.



  • @Xyro said:

    However, in other places they do use $htmlStream .=<< HEREDOC_END; with variables in place.  I can understand learning the language as you go,  who hasn't made those same sorts of mistakes before?  But then after you learn, you're supposed to correct those mistakes, right?

    @RHuckster said:

    the table approach was really the only way to have snazzy rounded corners back in the late-90s

    Yeah, I suppose you are right.  Although they could have at least used the scripting language's power to make the string literals less ugly.

    Consider this, though: the question such an analysis should be provoking is, "Why are they sending out snazzy rounded corners from a monitor program?".  The answer to which is too horrible/wonderful to say.

    Ok, I'll say it.  The monitor was entirely HTTP driven.  Another program was used to GET the results from the Perl script at a frequency of every minute in order to screen-scrape the output from the result of the monitor's test.  Tee hee.  THAT program would be the one that actually instigated the restarts.

    The chain goes likes this:

    [A program that automatically sends HTTP requests] -> [local IIS instance] -> [The Perl script that uses this lib] ->  [A Java program so badly written that it occasional hangs itself somehow] -> [bad old C program that crashes several times a day]
    and then back up the chain.

    The insanity doesn't stop there though!  But I can't share all of this at once, it would just be too much.

     So where does the wooden table fit into that chain?


  • Considered Harmful

    @RHuckster said:

     I hate to defend the original coders, as the other WTFs you showed us are definitely worthy of a WTF, but besides the use of %pixel, the table approach was really the only way to have snazzy rounded corners back in the late-90s. We take for granted our CSS and (mostly) HTML-compliant browsers we have today, but back in the old days, tables and god-awful HTML was what it took to layout a webpage that has anything as complicated as rounded edges and "cool looking" buttons.

    My memory isn't perfect, but I don't recall "the table approach" being a series of tables each with a single row and a single cell with a single GIF inside...



  • @Xyro said:

    However, in other places they do use $htmlStream .=<< HEREDOC_END; with variables in place.  I can understand learning the language as you go,  who hasn't made those same sorts of mistakes before?  But then after you learn, you're supposed to correct those mistakes, right?

    Most of the managers for whom I've worked have not agreed with that ideal.  They have been, instead, of the opinion, if it appeared to be working to them, one shouldn't futz with it.

    I think I've only had two supervisors who seemed to understand that inconsistencies in code make bug detection more difficult.  That is, if all of the code triggers a programmer's code sense, then the programmer's intuition will not be able to point out any bugs.  Also, such code can inspire bugs, by throwing off ones code sense as one is writing new code.


  • 🚽 Regular

    @joe.edwards said:

    My memory isn't perfect, but I don't recall "the table approach" being a series of tables each with a single row and a single cell with a single GIF inside...

     

     Good point, missed that.



  •  @Xyro said:

    Edit:   It just occurred to me, %pixel will be interpolated by Perl as a hash which will be coerced into a scalar.

    No, Perl doesn't interpolate hashes.


Log in to reply