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

CGI and why?

by Sifmole (Chaplain)
on Dec 31, 2002 at 20:59 UTC ( [id://223462]=perlquestion: print w/replies, xml ) Need Help??

Sifmole has asked for the wisdom of the Perl Monks concerning the following question:

my $q = new CGI; my $name = $q->param('user_name'); my $gender = $q->param('gender'); my $real_name = $q->param('real_name'); my $city = $q->param('city'); my $country = $q->param('country'); my $email = $q->param('email'); my $confirmemail = $q->param('confirmemail'); my $mm = $q->param('birthmm'); my $dd = $q->param('birthdd'); my $yy = $q->param('birthyy');

A block of code like this always hits my pet-peeve meter. The coder then goes off and only use the scalars in ways that the $q->param('varname') call would be just fine. What am I missing that makes people write redundant blocks of useless assignments like this?

Is there a good reason that I am just not aware of? I ask because when you see somthing so often you have to question whether it is yourself that is wrong.

Replies are listed 'Best First'.
Re: CGI and why?
by chromatic (Archbishop) on Dec 31, 2002 at 21:03 UTC

    Two reasons come to mind. First, you can't really manipulate the values (to untaint them) as param() isn't an lvalue. Second, the context is unambiguously scalar in this case. In a print statement, it may be unintentionally list.

    Oh, and a third might be for the efficiency of not calling a method repeatedly.

      I can see your first two points, but you could untaint by using the param methods ability to set a value right?
      $q->param('varname', untaintit($q->param('varname')));

      Your third point I can accept, except that in most cases where I see this the last performance issue that the code has is the method calls to $q

Re: CGI and why?
by Aristotle (Chancellor) on Dec 31, 2002 at 21:18 UTC
    While I do agree with the points in its favour so far, it strikes me as insufficient hubris. Personally I'd probably do something like this:
    my %param = map { $_ => $q->param($_) } qw( user_name gender real_name city country email confirmemail birthmm birthdd birthyy );
    That also retains the visual benefit of a form-submitted parameter standing out as such throughout the program. It does lose the benefits of strict however.

    Makeshifts last the longest.

      You can get the same result with:

      %param = $q->Vars;

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        Nearly, except that retains parameters I don't care about. You might do:
        my %param; @param{@$_} = @{{ $q->Vars }}{@$_} for qw( user_name gender real_name city country email confirmemail birthmm birthdd birthyy );
        ... but, errm. :)

        Makeshifts last the longest.

Re: CGI and why?
by sauoq (Abbot) on Dec 31, 2002 at 22:08 UTC

    I don't find anything particularly irritating about that with the exception of its formatting. It really isn't that hard to line up the assignment operators.

    You've already gotten a few good reasons to do it. I might add readability to the list. Especially if the value is used repeatedly, it is a lot easier to quickly read $real_name than $q->param('real_name') in a line full of other code.

    Another reason might be the desire to use string interpolation. I think

    print "Hello $real_name!\n";
    is much nicer than
    print 'Hello ', $q->param('real_name'), "\n";
    is. Also, with <<HERE documents, using variables becomes a necessity¹.

    1. That is, if you want to avoid ugly constructs such as the one Aristotle mentions in his reply. ;-)

    -sauoq
    "My two cents aren't worth a dime.";
    
      Just to pick nits, no, you don't need variables neither in doublequotes nor heredocs, though the syntax is distracting in doublequotes.
      use constant FOO => "BAR"; print << "BAZ" @{[ FOO ]} BAZ

      I particularly enjoy this "poor man's templating" technique for very short CGI scripts where I don't want to load Template Toolkit II or some such, but still want to enjoy the benefits of separating application logic from display formatting. It can get tricky real quick like if you want to quote stuff inside the deref block though, so it doesn't scale very well. But that's okay - it keeps me from being falsely lazy when such a script happens to grow. :)

      Of course, that's not real a solution for simple doublequotes, as

      print "Hello, @{[ $q->param('real_name') ]}\n"; is of debatable beauty and a real pain to type out more than once or twice.

      Makeshifts last the longest.

        Yes, you can do that if you really want to. Keep in mind, though, that will result in the sub being called in list context. If you want to force scalar context you will have to do so explicitly which makes an ugly construct even more unwieldy.

        -sauoq
        "My two cents aren't worth a dime.";
        
      Line up assignment operators? Not everyone uses a glass TTY or emulates it with a fixed-width font. Personally, I would find the big horizontal gap more distracting.

      As for the example, I'd rather use a slice rather than mentioning the params array on every line. That would mimic the common argument-list idiom of my ($n1, $n2, $n3)= @_;. So that would be something like

      my ($localname1, $ln2, $ln3)= @original{qw/name1 name2 name3/};
      I don't know if the accessor function has something similar. That is, if passed multiple arguments will it return a list as well?

      —John

        Not everyone uses a glass TTY or emulates it with a fixed-width font.

        No, but many of us do. It's the least common denominator. If you want your code to be maintainable regardless of the environment preferred by the maintainer, you really should keep it in mind.

        Even most of those who don't constrain themselves to a proper 80 character line use fixed-width fonts. Even most lame editors that come embedded in the plethora of available "integrated development environments" at least default to a fixed width font. How many nodes here are considered because code tags weren't used and the result is almost unreadable even when BR tags are inserted? What font do you use?

        I strongly stand by my statement that the assignment operators should be lined up. It doesn't take much more work (even when you have to change a bunch of them) and it is worth it to give your code a polished look.

        I think that the code

        my $foo = 'bar'; my $bazqux = 42; my $quux = "$bazqux ${foo}s"; my $money = 'gold'; my $total_fortune = $quux . "of $money\n";
        is simply more readable as
        my $foo = 'bar'; my $bazqux = 42; my $quux = "$bazqux ${foo}s"; my $money = 'gold'; my $total_fortune = $quux . "of $money\n";
        and if you actually disagree, well, you are welcome to your opinion on the matter (right up until the day you do any work for me, that is.)

        As for the example, I'd rather use a slice rather than mentioning the params array on every line.

        In the example, the multiple assignments were separate calls to the param() method of the CGI object called $q, not assignment to several elements at different keys in the same hash. If it was the latter, I probably wouldn't recommend assigning to scalars at all. If it really made sense though, I'd be inclined to agree that a hash slice would be the way to go.... maybe. Even that might be a lot less maintainable if there were many variables. Consider:

        my ($foo, $bar,..., $baz,... $qux) = @hash{'abc', 'def',..., 'pqr',... + 'yz'};
        versus
        my $foo = $hash{abc}; my $bar = $hash{def}; . . . my $baz = $hash{pqr}; . . . my qux = $hash{yz};
        The more verbose method neatly puts each variable on the same line as its hash element. If you had to change the assignment to $baz in the former of those two methods, you'd find yourself counting keys in your slice to find the one it matched with. That's a pretty ugly situation.

        I don't know if the accessor function has something similar. That is, if passed multiple arguments will it return a list as well?

        No. Calling it with multiple arguments, as in

        $q->param('foo','bar','baz')
        will result in the parameter 'foo' being assigned an array with the values 'bar' and 'baz' in it. It's the same as calling it as
        $q->param(-name => 'foo', -values => ['bar', 'baz'])

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: CGI and why?
by pfaut (Priest) on Dec 31, 2002 at 21:10 UTC

    It makes for easier debugging to have all of those values in simple scalars. These can be examined easier to see if the values returned are as expected. I can plug in a new value while debugging to see how it affects the script.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      You can do that by doing $q->param('varname', 'new value');
Re: CGI and why?
by jdporter (Paladin) on Dec 31, 2002 at 21:13 UTC
    In general, Sifmole, I tend to agree with you.

    However, one possible justification is if the variable $q is not in scope at the time (or rather, place) the values are needed. Perhaps something like this:
    my $name; my $real_name; sub get_params { my $q = new CGI; $name = $q->param('user_name'); $real_name = $q->param('real_name'); } sub print_params { print "Name: $name\nReal Name: $realname\n"; }

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

Re: CGI and why?
by tachyon (Chancellor) on Dec 31, 2002 at 21:54 UTC

    Another reason is convenience - you can interpolate scalars into strings/heredocs for output but not method calls.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://223462]
Approved by Aristotle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (10)
As of 2024-03-28 12:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found