in reply to Coding for maintainability
Just for fun, I converted your monster switch into a data-driven function. The data are "rules"; the function performs a generic matching operation on those rules. For compactness of representation, I've written the rule data as one specially formatted text block, which means there's a parsing function as well.
So you'd call define_rules first, passing it the text string defining the rules in the compact notation:{ my @ruleset; sub define_rules { my $rules = shift; for my $rp ( split /\n\n/, $rules ) { my @rules = grep !/^#/, split /\n/, $rp; s/#.*// for @rules; s/^\s+// for @rules; s/\s+$// for @rules; my $fam_pat = shift @rules; my %rules = map { my( $when ) = $_->[0] =~ /(.*):/; # will be undef if n +o colon defined $when or $when = ''; ( $when => $_->[1] ) } map { /(.*)\bkey\s*=\s*(.*)/ ? [ $1, $2 ] : () } @rules; push @ruleset, [ $fam_pat, \%rules, ]; } } # $key = get_key_by_rules( $family, $family_release ); # if it matches a rule but the rule doesn't specify a key to retur +n, # this function returns its first argument (i.e. $family). # if no match occurs, it returns undef; but your ruleset should # probably have a catch-all condition at the end so this never hap +pens. sub get_key_by_rules { my( $major, $minor ) = @_; defined $minor or $minor = ''; for my $ruleset ( @ruleset ) { my( $maj_pat, $rules_hr, $default ) = @$ruleset; if ( $major =~ /$maj_pat/ ) { if ( exists $rules_hr->{$minor} ) { my $ret = $rules_hr->{$minor}; return $ret gt '' ? $ret : $major; } elsif ( exists $rules_hr->{''} ) { my $ret = $rules_hr->{''}; return $ret gt '' ? $ret : $major; } else { return(); } } } return(); } }
Then you'd call it like so:define_rules( <<'EOF' ); # careful - all whitespace is significant in this format. # use whole-line comments if you need spacers. UNIGRAPHICS_NX 1: key = NX1 2: key = NX2 key = other \bNX\b 3: key = NX3 4: key = NX4 SOLID_EDGE 18: key = SE18 16: key = SE16 17: key = SE17 key = other WEBTOOLS key = # use the default key, which is $family TC_ENGR-IMAN key = TC_ENG TC_COMMUNITY key = TC_COM # default. Unfortunately, this "comment" isn't optional. :-( key = other EOF
$family = trim($family); ( undef, $family_release ) = $family_release =~ /(P|V)(\d+)*/; #print "$family\n"; my $key = get_key_by_rules( $family, $family_release ); $people{$user}{$key}++; $people{$user}{TOTAL}++;
Yep, it's that simple. Although you'd actually want to test that $key isn't undef; that's the case when there is no rule that matches the given family/release.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Coding for maintainability
by monsterzero (Monk) on Feb 16, 2006 at 21:55 UTC |