Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How to write better code?

by Anonymous Monk
on Dec 04, 2006 at 14:57 UTC ( [id://587649]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all,
Could you please help me to write best code?
I would like to store the query values in an associative array
Here is my code.
my $string = "name=alex&sex=m&age=20"; my @array = split(/&/,$string); my %hash_init; foreach my $key(@array) { my ($key1,$val1) = split(/=/,$key); $hash_init{$key1}=$val1; } use Data::Dumper; die Dumper(%hash_init);

Thanks

Replies are listed 'Best First'.
Re: How to write better code?
by Corion (Patriarch) on Dec 04, 2006 at 15:01 UTC

    You want to use the CGI.pm module, which can parse that:

    use strict; use CGI; my $string = "name=alex&sex=m&age=20"; my $q=CGI->new($string); print Dumper scalar $q->Vars()"

    If you actually are, as it looks, parsing a CGI query, the CGI module can also take all of the other chores of parsing CGI queries for you:

    use strict; use CGI; my $q=CGI->new(); # parses all CGI parameters print $q->header('text/plain'); print Dumper scalar $q->Vars()"
Re: How to write better code?
by jbert (Priest) on Dec 04, 2006 at 15:17 UTC
    To elaborate on what the others have said: one aspect of good coding/experience is to appropriately choose library code rather than write everything yourself. If you are, as seems likely, parsing CGI parameters, then either the well-used CGI.pm or a related module (e.g. CGI::Lite) might be of use. As you might know, you'll find lots of information on modules on CPAN. This is one of perl's major strengths - there is a lot of useful code already written. (But you do need to be a little selective - perhaps some of it doesn't quite do what you need, etc.)

    In the specific case of the code you've posted, one of the best pieces of advice I'd give is to name things (variables, functions, objects, methods) carefully - and don't be afraid of renaming them if their purpose (or your understanding of their purpose changes).

    In this example, people are guessing that you're writing CGI-parsing code, because you've got variables called $string and @array. This doesn't really convey any information to the reader. It would be much better to write something like:

    my $cgi_query_string = "name=alex&sex=m"; my @components = split(/&/, $cgi_query_string); my %query; foreach my $component (@components) { my ($name, $value) = split(/=/, $component); $query{$name} = $value; }
    otherwise, what you've written is fairly good, idiomatic perl. If you're interested in some other, nice, more modern idioms, take a look in List::Util and List::MoreUtils. These don't really apply to your code above, but they are a nice way of removing some loops and lines from your code and simultaneously expressing the intent of what you're trying to do more clearly.

    Also, there is a lot (too much?) in the [id://Tutorials] section and also a lot of good advice in the book "Perl Best Practices".

      otherwise, what you've written is fairly good, idiomatic perl

      It's pretty decent perl but it's lousy cgi param parsing:

      • no handling of multivalued params
      • no handling of ; as separator
      • no handling of url encoded params or values

      -derby
      I agree with other comments regarding the advisability of use CGI; if parsing CGI. I also agree with your advice to the OP about meaningful variable names. However, while the code does what it is meant to do, I think it might be more readable if the foreach loop and the intermediate variables are dispensed with

      my $cgi_query_string = "name=alex&sex=m"; my %query = map {split m{=}} split m{&}, $cgi_query_string;

      I realise this might be a step too far for some but I find it easier to see the wood for fewer trees. Others may (and probably will) disagree.

      Cheers,

      JohnGG

        It's an interesting point. I almost put in a paragraph on this (saying that some people would suggest dropping the naming variables).

        I tend to view naming vars almost a substitute for comments. They can be a way of better documenting your intent. I mused about that a bit here.

        That said, there's also a lot to be said for brevity, and I like your code too :-).

        If I'm honest, I suspect I'd have dispensed with the @components intermediate array, but written out the foreach. I think this is because I rarely think of assigning arrays to lists (and avoiding using a side-effect like $query{$x} = $y in a map clause is one of my reasons for using an explicit foreach). Maybe I should do that more often.

        One hint is that I had a little trouble coming up with a good name for the intermediate array - always a good sign that it probably isn't necesary/desirable.

        Your implementation using map instead of foreach is slightly more readable, but will be more cumbersome to maintain and debug if additional parsing is required. It is likely a short-term win that will result in a comment block that is larger than the code after a few upgrades are made.

        Another weakness of using map for this is that CGI allows a parameter to have multiple values, but the code you provided will only use the last value.

Re: How to write better code?
by SheridanCat (Pilgrim) on Dec 04, 2006 at 16:38 UTC
    I agree with all the other comments. Just one note on using Data::Dumper. If you pass it a reference, you'll get more readable output. Your code produces:
    $VAR1 = 'name'; $VAR2 = 'alex'; $VAR3 = 'age'; $VAR4 = '20'; $VAR5 = 'sex'; $VAR6 = 'm';
    If you just passed Dumper() a reference, like this:
    print Dumper \%hash_init;
    You'll get this:
    $VAR1 = { 'name' => 'alex', 'age' => '20', 'sex' => 'm' };
    Which is a whole lot nicer to look at.
Re: How to write better code?
by McDarren (Abbot) on Dec 04, 2006 at 15:07 UTC
    CGI.pm is your friend :)
    use CGI qw( Vars ); use Data::Dumper; my %params = Vars() print Dumper(\%params);

    Cheers,
    Darren :)

Re: How to write better code?
by fenLisesi (Priest) on Dec 04, 2006 at 15:02 UTC
    Depending on where the $string comes from, the answer might be use CGI; Cheers.
Re: How to write better code?
by artist (Parson) on Dec 07, 2006 at 21:05 UTC
    Assuming your string comes from a CGI query, following code is the shortest and works best for your use. It will display nicely in HTML format.
    use CGI; print CGI->new->Dump;
    I would suggest that use read 'Perl Best Practices' book.
    --Artist

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-04-19 07:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found