Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Pearls (not really) of Perl programming

by PetaMem (Priest)
on Nov 24, 2004 at 16:46 UTC ( #410170=perlmeditation: print w/ replies, xml ) Need Help??

Hello Monks,

most of you probably have encountered foreign code of questionable quality. While this can be kind of frustrating if one finds himself in the situation of a maintainer, it can be (should be) fun without those bad feelings if one just may sight such code and float by.

This is a call for a fashion parade...

...of such code snippets that will remain unforgettable to you. I'll make a start with some of those I encountered:

Example 1: cut first and last char of string

chop $str; reverse $str; chop $str; reverse $str;
Example 2: ensure string isn't longer than 50 chars

chop $default_title while (length $default_title > 50);
Make your contribution. Let's have a laugh together. Perhaps we even make it to sum up enough material for a anti-cookbook ;-)

Bye
 PetaMem
    All Perl:   MT, NLP, NLU

Comment on Pearls (not really) of Perl programming
Select or Download Code
Re: Pearls (not really) of Perl programming
by itub (Priest) on Nov 24, 2004 at 16:59 UTC
    Great idea! I've seen this on actual code:
    my @lines; while (<>) { @lines = (@lines, $_); }
Re: Pearls (not really) of Perl programming
by trammell (Priest) on Nov 24, 2004 at 17:12 UTC
    Code to "scrub" CGI inputs:
    s/\&\;\`\'\\\"\|\*\?\~\<\>\^\(\)\[\]\{\}\$\n\r//g;

      That belongs in the obfuscated code section, perhaps as part of a larger script full of such stuff.

      - apotheon
      CopyWrite Chad Perrin

      Should those all have alternators between them? If not, it's looking for a specific string. Of course, it should use tr instead, but I presume that's why it's bad code.

      Caution: Contents may have been coded under pressure.
Re: Pearls (not really) of Perl programming
by cosimo (Hermit) on Nov 24, 2004 at 17:27 UTC
    I've found this in our code base, though I'm proud to say that this is not my stuff... :-)
    @aFieldsList = sort { $a eq 'listtype' and -1 or $b eq 'listtype' and 1 or $a eq 'listcode' and ( $b ne 'listtype' and -1 or 1 ) or $b eq 'listcode' and ( $a ne 'listtype' and 1 or -1 ) or $a eq 'funclist' and ( $b !~ /^(listtype|listcode)$/ and -1 or + 1 ) or $b eq 'funclist' and ( $a !~ /^(listtype|listcode)$/ and 1 or -1 ) } @aFieldsList;
    Maybe it'll take 2 or 3 days to understand what is goin'on here... ;-)
      I love when you get the opportunity to put obfu into production code :)
      This is not that baroque once you grasp how the writer is approaching the sort. I looked at this quickly and knee-jerked that the logical expression is Wrong then I realized that it was in a sort block.

      The writer is using short-circuiting to exit the block with -1 or 1 values; so that listtype sorts before listcode before funclist before every thing else.

      I don't write that way. This seems to rely on luck as the block may yield "" which sort is not advertised to accept. I think it needs a catch-all  or ( $a cmp $b ).

      Be well.

        This seems to rely on luck as the block may yield "" which sort is not advertised to accept.
        That code always returns 1 or -1 AFAICT. Can you explain?

        Update: it will return false if $a or $b isn't any of the types tested for, but false isn't "", it's both 0 and "":

        $ perl -we'@_ = sort { "" } 1,2' Sort subroutine didn't return a numeric value at -e line 1. $ perl -we'@_ = sort { !1 } 1,2'
Re: Pearls (not really) of Perl programming
by Mutant (Priest) on Nov 24, 2004 at 17:35 UTC
    Haven't really got any nice snippets to post, but the application I managed to convince management to throw away and replace has this in one of the files:
    __END__ ONE DAY SOMEONE WILL HAVE TO UPDATE THIS. APOLOGIES FOR THIS, TIME WAS NOT GIVEN TO ALLOW FOR PROPER ORGANISATIO +N OF THIS CODE
    I think that pretty well sums it up :)

    (I happen to know exactly how long the developer had as well.. can't really say it's an excuse).
      I saw a study cited in Steve MacConnell's Rapid Development where they gave the same task to five teams of programmers, but each team had a different priority: one had to optimize for memory use, other for programming time, other for program size, other for code readability, and the last one for output readability. Every team ranked first or second in the aspect that they were told to optimize. Guess who did worst on code readability? The team that was told to optimize programming time! (And the team the optimized code readability was the worst in terms of programming time.)
      My personal favourite is, "forgive me father, for I have sinned." I tend to write that when other people force me to do poopy things.

      ----
      Then B.I. said, "Hov' remind yourself nobody built like you, you designed yourself"

Re: Pearls (not really) of Perl programming
by cosimo (Hermit) on Nov 24, 2004 at 17:36 UTC
    Another one, from the obscure deepness of perl realms (whatever this may mean)...
    my @where = ("item='$item'", "location='$location'", ... ); my $cSql; foreach( @where ) { $cSql .= ' ' . $_ . ' AND'; } chop $cSql; chop $cSql; chop $cSql;
    In our team, this is called the famous Triple Chop Technique.
    Probably it should be considered a kind of negative pattern.

      I've actually used:

      $sql = '... WHERE 1=1'; $sql .= ' AND ...' if (...); $sql .= ' AND ...' if (...); $sql .= ' AND ...' if (...);

      In defense, 1) it wasn't in Perl, which has the convenient join function, and 2) the conditions where not already in an array as in the above snippet.

      For the following, though, I deserve to be shot:

      if (0 || ... || ... || ... ) { ... }

      I do it just so all the conditions line up nicely.

      Update: That should be WHERE 1=1 (not WHERE 1) because 1 does not mean true in SQL, or at least not for the database I was using.

        Hey, I've done that! ;-) But let me explain: it was a quick and dirty way of forcing the if to go one particular way during debugging. The zero is a no-op, but you can then easily turn it into a 1 when you want to force the condition to be true. I don't think it is much worse than commenting out some code.

        I am very glad that ikegami posted this, because this touches on something of a pet peeve. This should be considered by anyone who has ever added a noop to code for the mere sake of symmetry.

        Considering that ikegami is someone who knows his stuff ... the (tongue-in-cheek) "deserves to be shot" remark is well taken, but also a bit discouraging because of a common tendency out there ... what is that tendency?

        Programmers tend to unfairly critique (and even bully) themselves (and others) when they don't take the time to distinguish anomolies that arise from ignorance, from anomolies that arise from a justifiable desire to do things differently.

        Who knows how it got started, perhaps when we were small children and told to "color inside the lines" of our coloring book ... but dammit ... what if the lines are in the wrong place to begin with? The mere fact that many many (experienced) people have done this kind of 'coding faux pas' indicates to me that there is some merit to this 'anti-pattern', and we should think twice before poking fun or shooting at ourselves when we use it.

        This is not to detract from ikegami's point, but rather a tangent, in hopes that we don't stifle our own creativity in our attempts to do 'what is expected of us'.

        Sometimes you just gotta color outside the lines.

        It's not that bad, at least in perl, as it appears to optimize it away. At least, on ActivePerl 5.8.4, the following script:
        #! perl $x = 3; if(0 || $x == 2 || $x == 3) { print "Yeah!\n"; }
        under `perl -MO=Deparse test.pl`, produces:
        test.pl syntax OK $x = 3; if ($x == 2 or $x == 3) { print "Yeah!\n"; }

        In general, I prefer my "||" on the right:

        $x = 3; if( $x == 2 || $x == 3) { print "Yeah!\n"; }

        If you want, you can still append "|| 0" to the condition, allowing for more symmetry, but not optimized away. At least it'll only be executed if every other condition fails.

        There's a reason why Perl accepts lists ending with ",", or at least: it's a good thing Perl accepts lists ending with ",". In a way it's too bad (tough understandable) it won't do the same for "||".

        Ah!

        After reading it three or four times, I suddenly realized now that the other conditions where OR'ed, not AND'ed! Beautiful (++)! I thought that you used the Zeroing Technique™ to automatically determine boolean value of whole expression (0 or 1).

        And the nicest thing is that my mind shifted towards that interpretation because I actually used it somewhere... ;-)

      Might be negative pattern in Perl with its join() and map() builtins, but assuming you happen to be forced to write code is a language that doesn't provide anything similar ... I use something like this quite often actually when "working" in VBScript. Better than trying to make sure you do not put the separator before the first item or after the last one. Recently had a problem with some code that tried that. And failed miserably because it did not take into account that the joined values could be empty.

      Jenda
      We'd like to help you learn to help yourself
      Look around you, all you see are sympathetic eyes
      Stroll around the grounds until you feel at home
         -- P. Simon in Mrs. Robinson

Re: Pearls (not really) of Perl programming
by kutsu (Priest) on Nov 24, 2004 at 17:40 UTC

    We use custom tags (%B% = start bold, /B/ = end bold and others) for reports that are printed on both the internet and a high speed printer. The data for these reports is pulled from several (more then 7) files and at each of these I found:

    s/\%B\%/<b>/g; s/\/B\//<\/b>/g;

    seems the writter didn't know about subs and \Q\E or quotemeta() ;)

    "Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce

      Seems kutsu doesn't know about using a seperator other than / ;) Neither \Q\E nor quotemeta() are needed here.

      s#%B%#<b>#g; s#/B/#</b>#g;
Re: Pearls (not really) of Perl programming
by hardburn (Abbot) on Nov 24, 2004 at 17:44 UTC

    A lovely ROT-13 encoder:

    # $str contains the characters to encode my @chars = split //, $str; for (@chars) { if( $_ eq 'a' ) { $_ = 'n' } if( $_ eq 'b' ) { $_ = 'o' } if( $_ eq 'c' ) { $_ = 'p' } # And so on. I think you all see where this is going }

    Hey, how about this one-liner: $str =~ tr/A-Za-z/N-ZA-Mn-za-m/;.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Pearls (not really) of Perl programming
by Ovid (Cardinal) on Nov 24, 2004 at 18:06 UTC

    I would cheerfully have strangled the guy:

    { no strict; &{$cgi->param('action')}; }

    Cheers,
    Ovid

    New address of my CGI Course.

      It could have been worse :-)

      eval $cgi->param('action'); open F, $cgi->param('file'); $dbh->do( "SELECT * FROM blah WHERE foo LIKE %" . $cgi->param('search' +) .'%' );
Re: Pearls (not really) of Perl programming
by kscaldef (Pilgrim) on Nov 24, 2004 at 18:23 UTC
    for (1..10) { my $i = $_; # some stuff with $i }

      I've done that! For two reasons, one good, one bad.

      Bad Reason

      I thought

      for my $i (1..10) { # some stuff with $i }

      was the same as

      my $i; for $i (1..10) { # some stuff with $i }

      rather than being the same as

      { my $i; for $i (1..10) { # some stuff with $i } }

      because in C++, (IIRC)

      for (int i=0, i<5; i++) { ... } // i in still in scope here!
      .

      I didn't do use int as shown here, but my coworkers did and I would find it misleading. Perl doesn't have that problem, but I only learned that recently.

      Good Reason

      This fails ('Modification of a read-only value attempted')

      foreach my $var ('a', 'b') { ...something that may modify $var... print($var); }

      but this doesn't

      foreach ('a', 'b') { my $var = $_; ...something that may modify $var... print($var); }

        Your good reason has a corollary, which happens to be another good reason to use the original code. This modifies the original array:

        @array = 1 .. 10; for my $var (@array) { $var++; print "$var\n"; } print "@array\n";

        But this does not:

        @array = 1 .. 10; for (@array) { my $var = $_; $var++; print "$var\n"; } print "@array\n";
        Actually, I believe that the C++ behaviour you pointed out is an MSVC glitch.
        for(int i = 0; ;) { }
        ... should have "i" visible only inside the for loop. I think gcc actually does this properly, as does MSVC .NET. ... unless I'm horribly wrong?
      Oh yes!

      Seen that. Especially guys coming from the chr(ord('A')+2) programming language cannot get rid of the indexing-loop concept in their head.

      Bye
       PetaMem
          All Perl:   MT, NLP, NLU

Re: Pearls (not really) of Perl programming
by revdiablo (Prior) on Nov 24, 2004 at 18:35 UTC

    Everyone loves to post bad examples from other peoples' code. But I will [once again] bravely delve into my own code archives for terrible examples!

    This is at the beginning of a script that I must have written shortly after I learned about use strict. I didn't really understand lexical scope, I just wanted the errors to go away. Can we say "missing the point"?

    my($all,$com,$csv,$ctr,$desc,$dir,$fname,$found,$fsize, $line,$longline,$null,$one); my($parm,$parms,$pattern,$seekrc,$value); my(@coms,@csvin,@grep,@parms,@seekrc);

    Here's another fun one. I can think of one or two easier ways to do this nowadays....

    ($start,$stop,$adv,$desc) = split(/\,/,$line); $start =~ s/^\s+//g; $stop =~ s/^\s+//g; $adv =~ s/^\s+//g; $desc =~ s/^\s+//g;

    Or how about something like this. I guess I didn't yet understand how to access nested hashes, because the use of %temphash is just bizarre (trimmed for pasting):

    while(defined($line = <IN>)) { ... $temphash{'size'} = $size; $temphash{'crc'} = $crc; if($dir eq "" || $csvdirs == 1) { ... $temphash{'dir'} = $good; } elsif($csvdirs == 2) { ... $temphash{'dir'} = $good . "/" . $dir; } else { $temphash{'dir'} = $dir; } $bighash{$name} = { %temphash }; }

    I could go on all day, to my own humiliation. I'll leave it at that though. Perhaps others will now be tempted to post their own bad code, rather than someone else's. :-)

      This is at the beginning of a script that I must have written shortly after I learned about use strict.

      I think everyone goes through a phase like that. I certainly have code with "global lexicals" from my early use strict days.

      $start =~ s/^\s+//g;

      Is there a reason for the /g?

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

        Is there a reason for the /g?

        Since the code is several years old (perhaps 5 or 6), I don't remember exactly. But the most likely explanation is that I used to be a pretty bad cargo-cult programmer.

        An obvious reason. Habit. I'm always typing ~s/.../.../g out of habit, never thinking of doing a replace only once.

        ----
        Then B.I. said, "Hov' remind yourself nobody built like you, you designed yourself"

      This is at the beginning of a script that I must have written shortly after I learned about use strict. I didn't really understand lexical scope, I just wanted the errors to go away. Can we say "missing the point"?
      I'm still in the bad habit of doing this. I blame C for the habit.
        It's funny that you mention C - whenever I had to deal with it, I would always create additional blocks inside a func just to limit variable scope.
        int a() { { int a, b; ... } /* move on */ { int a, b, c; } }
        That did result in some excessive indentation though.
Re: Pearls (not really) of Perl programming
by tall_man (Parson) on Nov 24, 2004 at 19:22 UTC
    I knew a programmer who was unsure how to set values through a hash reference, so he did things like this all over the place:
    my %hash = %{$href}; $hash{"abc"} = 1; $href = \%hash;
Re: Pearls (not really) of Perl programming
by Anonymous Monk on Nov 24, 2004 at 20:32 UTC
    Example 1
    #!/usr/bin/perl #--------------------------------------------------------------- # Saltillo Perl Mongers # Generoso Montemayor # 24/11/2004 # #--------------------------------------------------------------- # use strict; my $str; $str = "1some text1"; $str = substr($str, 1, -1); print ($str,"\n");

    Edit by castaway - added code tags

Re: Pearls (not really) of Perl programming
by Anonymous Monk on Nov 24, 2004 at 20:37 UTC
    $default_title = substr($default_title, 0, 50);

      What's bad about this? Sure, there are other ways to do it, but it doesn't seem particularly egregious to me. For those following along at home, here are some other ways:

      $default_title =~ s/(.{50}).*/$1/; $default_title =~ s/./$ctr++<50?$&:""/ge; $default_title = pack "A50", $default_title; $default_title = join "", (split //, $default_title)[0..50];

      Personally, I like the original much better than these alternatives. The only other way that I would possibly use is:

      substr($default_title, 50) = "";

      But substr as an lvalue is not something everyone knows about, so it's not clearly the best option.

        More regex solutions: (don't forget the s modifier)

        ($default_title) = $default_title =~ /(.{0,50})/s; $default_title =~ s/(?<=.{50}).*//s;
        I'd also want to add
        substr($default_title, 50, length($default_title), '');
        and second you and the original isn't that bad.

        ihb

        See perltoc if you don't know which perldoc to read!
        Read argumentation in its context!

Re: Pearls (not really) of Perl programming
by radiantmatrix (Parson) on Nov 24, 2004 at 23:16 UTC

    One of mine, in the early days of learning about DBI...

    open INFILE, '<source.txt'; while (<INFILE>) { my $dbh = DBI->connect("dbi:mysql:database=maindb;host=localhost"); my $sth = $dbh->prepare("SELECT * FROM $table WHERE uid=$user"); $sth->execute; print join(',', $sth->fetchrow_array); print "\n"; }

    Note the complete lack of error handling, no use of prototypes, and the assumption that only one row would be returned. I also particularly enjoy the two separate print statements. And, I printed to STDOUT (without setting $|) even though I wanted to write to a file.


    radiantmatrix
    require General::Disclaimer;
    Perl is

      Plus, depending on the number of lines in the INFILE, you probably swamped the DB by not keeping the $dbh outside of the while.

        Quite. Not to mention that particular app connected to a mysql instance that was about 5 router hops away over not-the-fastests links. Connect times averaged 5s, which really reared its ugly head when the input file was 2_000 lines. ;-)


        radiantmatrix
        require General::Disclaimer;
        Perl is

      Also, there's no localization of the filehandle.

      ihb

      See perltoc if you don't know which perldoc to read!
      Read argumentation in its context!

      I could probably write a book on the subject of the OP but I'll stick to just one DBI example.

      my $dbh = DBI->connect($database, $user, $password) or die $dbh->errstr;

      When I found it, I decided to grep for it. It was being used in every script that pulled from the database!

Re: Pearls (not really) of Perl programming
by Jenda (Abbot) on Nov 24, 2004 at 23:48 UTC
    @EXPORT = qw(new);
    From one of the very first versions of Mail::Sender. Oops.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

Re: Pearls (not really) of Perl programming
by jryan (Vicar) on Nov 25, 2004 at 08:16 UTC

    Here is some code that I wrote almost 5 years ago. It was my first real Perl program; I had previously been a PHP programmer, and really had no clue what I was doing at the time when I wrote this. Really, read the code; I think it really tops anything anyone has posted in this thread so far. I'd be embarassed about it, but is *just* *too* *funny*.

    Among the highlights:

    1. Probably the most gratuitous use of eval I've ever seen. I use eval here for everything from recursively calling a function (I think to avoid infinite recursion warnings) to simple assignments.
    2. I use eval + symrefs instead of using hashes. I don't even think I knew that hashes existed at that point.
      for ($i=0; $i<$cutlevelat; $i++) { eval("\$n".$i."=0"); }
      Fun Fun Fun?
    3. I also use arrays and linear scans instead of hashes to store the results. Oh boy.
    4. I remember having to research "my" when I was writing this. You might notice that the recursive subroutine uses "my" with its variables while the rest of the program doesn't. This wasn't because I had discovered lexical scoping halfway through writing this. This was because I couldn't figure out a consistant way to do it with eval.
    5. And the fun goes on and on...

    Despite all of these problems, the program had some pretty cool functionality. It would scan a condendensed apache log file (which I condensed with another script that ran as a cron job) and turned it into a heirarchy view that told how many hits each page on our school's website got, with higher levels having the sum of the hits on the lower levels.

    So, it might be total garbage, but it just shows how far I've come, right? :)

    (P.S.: I remember being confused as to why the node recieved such a high rep, because I knew it was garbage when I posted it. (it was my 3rd node on this site). It wasn't until later that I learned that people often voted on frontpaged nodes without reading them.)

Re: Pearls (not really) of Perl programming
by stefan k (Curate) on Nov 25, 2004 at 14:07 UTC
    Fellow Monks,
    blushing I must confess that I did feel dirty the day I wrote this:
    for my $wfref (@{$data{flows}{$data{partners}{$part_id}{flow}}}) { #... }
    Keep your data structured, clean, organized and simple... not.

    Regards... stefan k
    you begin bashing the string with a +42 regexp of confusion

      There's a trick that helps with deep structures:

      my $flow_id = $data{partners}{$part_id}{flow}; for my $wfref (@{$data{flows}{$flow_id}}) { #... }

      While not necessary here, you can always break things down further:

      my $partner = $data{partners}; my $flow_id = $partner->{$part_id}{flow}; my $flows_ref = $data{flows}{$flow_id}}; for my $wfref (@$flows_ref) { #... }

      or

      my $flow_id = $data{partners}{$part_id}{flow}; my $flows_ref = $data{flows}{$flow_id}}; for my $wfref (@$flows_ref) { #... }

      But in this case, I don't see why flows and partners are in the same structure

      Change %{$data{flows }} to just %flows. Change %{$data{partners}} to just %partners.
Re: Pearls (not really) of Perl programming
by Juerd (Abbot) on Nov 25, 2004 at 17:06 UTC

    reverse $str;

    That doesn't affect $str. Does this come from production or otherwise tested code?!

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      Have another look. This thead is discussing bad code. (I was confused a little a first too.) reverse $str not doing anything is exactly the point.

        This thead is discussing bad code.

        That I gathered. I was wondering where this example came from. I find it hard to believe it was encountered in the wild. Conceived examples work, but they aren't as good, IMO.

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        Perhaps, although even if it did work, it would be a lot less clear than a substr, IMO.
Re: Pearls (not really) of Perl programming
by NodeReaper (Curate) on Nov 25, 2004 at 19:32 UTC
    This node was taken out by the NodeReaper on Fri Nov 26 03:36:28 2004 (EST)
    Reason: [htoug]: completely off-topic and without any perlcontent. troll?

    For more information on this node visit: this

Horrors abound
by htoug (Deacon) on Nov 25, 2004 at 23:59 UTC
    I just fell face forward into this earlier today (sorry for the extremely long lines):
    use vars qw/ + + $AllowFullYearView + + $LevelForRobotsDetection $LevelForWormsDetection $LevelForBrowsersDete +ction $LevelForOSDetection $LevelForRefererAnalyze + $LevelForFileTypesDetection $LevelForSearchEnginesDetection $LevelForK +eywordsDetection + /; ($AllowFullYearView, $LevelForRobotsDetection, $LevelForWormsDetection, $LevelForBrowsersD +etection, $LevelForOSDetection, $LevelForRefererAnalyze, $LevelForFileTypesDetection, $LevelForSearchEnginesDetection, $LevelF +orKeywordsDetection)= (2,2,0,2,2,2,2,2,2); use vars qw/ + + $DirLock $DirCgi $DirConfig $DirData $DirIcons $DirLang $AWScript $Arc +hiveFileName + $AllowAccessFromWebToFollowingIPAddresses $HTMLHeadSection $HTMLEndSec +tion $LinksToWhoIs $LinksToIPWhoIs + $LogFile $LogType $LogFormat $LogSeparator $Logo $LogoLink $StyleSheet + $WrapperScript $SiteDomain + $UseHTTPSLinkForUrl $URLQuerySeparators $URLWithAnchor $ErrorMessages +$ShowFlagLinks + /; ($DirLock, $DirCgi, $DirConfig, $DirData, $DirIcons, $DirLang, $AWScri +pt, $ArchiveFileName, $AllowAccessFromWebToFollowingIPAddresses, $HTMLHeadSection, $HTMLEnd +Section, $LinksToWhoIs, $LinksToIPWhoIs, $LogFile, $LogType, $LogFormat, $LogSeparator, $Logo, $LogoLink, $Sty +leSheet, $WrapperScript, $SiteDomain, $UseHTTPSLinkForUrl, $URLQuerySeparators, $URLWithAnchor, $ErrorMessa +ges, $ShowFlagLinks)= ('','','','','','','','','','','','','','','','','','','','','','','' +,'','','','');
    etc for several pages, followed by:
    #--------------------------------------------------------------------- +--------- + # Function: Write on ouput header of HTML page + + # Parameters: None + + # Input: %HTMLOutput $PluginMode $Expires $Lang $StyleS +heet $HTMLHeadSection $PageCode $PageDir + # Output: $HeaderHTMLSent=1 + + # Return: None + + #--------------------------------------------------------------------- +--------- + sub html_head { my $dir=$PageDir?'right':'left'; if (scalar keys %HTMLOutput || $PluginMode) { my $MetaRobot=0; # meta robots + + my $periodtitle=" ($YearRequired".($MonthRequired ne 'all'?"-$Mont +hRequired":"").")"; # Write head section + + if ($BuildReportFormat eq 'xhtml' || $BuildReportFormat eq 'xml') +{ if ($PageCode) { print "<?xml version=\"1.0\" encoding=\"$PageCode\"?>\n"; } else { print "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"; } ; if ($FrameName ne 'index') { print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//E +N\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"; } else { print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset/ +/EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">\n"; } print "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"$ +Lang\">\n"; } else { if ($FrameName ne 'index') { print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitio +nal//EN\">\n\n"; } else { print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset/ +/EN\">\n\n"; } print "<html lang='$Lang'".($PageDir?" dir='rtl'":"").">\n"; } print "<head>\n"; print "<meta name=\"generator\" content=\"AWStats $VERSION from co +nfig file awstats.$SiteConfig.conf (http://awstats.sourceforge.net)\" + />\n"; if ($MetaRobot) { print "<meta name=\"robots\" content=\"".($FrameName eq 'mainlef +t'?'no':'')."index,nofollow\" />\n"; } else { print "<meta name=\"robots\" content=\"noindex,nofollow\" />\n"; }
    and so on for more than 10,000 lines - in one file.

    Note the way arguments are passed to a function: in global variables, and the neat way of printing just one line per print statement (OK: in all fairness later the author has discovered here-docs, but he has not refactored).
    And of course it is a CGI program, but does not use CGI;.

    I was trying to find a web-log-analyser tool with nice pictures for the PHBs, and google pointed me towards a site on sourceforge, where a well-documented tool was available in perl, with all the nice graphs management likes.

    I recoiled in horror on looking inside the code and discovering a true treasure-trove for the perlmonks Pearls (or not) - a sample of which I just had to share.
    I will now go on my way and find something better or (yuck) do it myself. Pity - it did look promising, and I am lazy and impatient.

    All names withheld to protect the unnamed author.

      This is an interesting point you raise here: Do Open Source programs have to be pretty inside? Sometimes you have a really capable program, which does its job very well, you use it, recommend it to others, but you better not look under the surface, as the source could make you blind.

      I know which project you are talking about here, because I use it frequently, and when I wanted to replace the home-spun referrer-scanning logic for my blog (code I have to update all the time to keep up with all the different search engines) with something more complete, I looked at above source to see if I could use some of their code for that purpose. And yes, I also recoiled in horror (and gave up). Totally monolithic, horrible from a software engineering stand-point.

      Would this be a better project if its code was more modular, with components useful outside its primary application? Yes. But is the reverse also true? Does a useful program become less useful because the implementation is ugly?

      I was trying to find a web-log-analyser tool with nice pictures for the PHBs, and google pointed me towards a site on sourceforge, where a well-documented tool was available in perl, with all the nice graphs management likes.
      I will now go on my way and find something better or (yuck) do it myself. Pity - it did look promising, and I am lazy and impatient.

      I would not do that, especially when you are lazy and impatient. Your PHB is not going to look at the source, the project is, as you say, well-documented, popular and works as advertised. Just treat this open-source project as closed-source (for your own safety).

        I agree - it will probably be best to accept the project just as any other shrink wrapped system we buy.

        I is a terrible shame though that all the effort that has gone into this project has ended with such a poor result. If it had been done according to 'proper' software engineering methods, it could have been augmented with you referrer-scanning logic and my additions.

        It does make the program less useful because you and I have had to do something else, and thus we have had to spread our tuits. The program could have saved us valuable time for something vital (like playing with the dogs) instead of having to do something that has beeen done many times already. If the implementation is 'nice' (from an engineering point of view) it adds considerable value. OK: it does as advertised, but extra value can be had if it is possible to reuse parts of it in new and unforseen ways. I think that perl (and Perl) is a good example of this.

        Does a useful program become less useful because the implementation is ugly?

        Yes, I would say so. A less maintainable program results in longer development times for bug fixes and security patches. A less maintainable program also has a greater chance of having a bug introduced whenever the program is changed.

        I guess that any kind of obfuscation is, in a way, against OpenSource. Who would dare to help if understanding such criptical code would consume most of someones' spare time?

        .{\('v')/}
        _`(___)' __________________________
        Wherever I lay my KNOPPIX disk, a new FREE LINUX nation could be established.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://410170]
Approved by inman
Front-paged by itub
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (10)
As of 2014-08-01 08:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (257 votes), past polls