重构现有的perl subs

时间:2010-11-11 16:20:38

标签: perl

我的perl代码中有2 sub个,但它们完全相同。我很好奇SO会如何重构它们来制作一个sub

它们唯一真正的区别是正则表达式和通过预处理语句的查询。准备好的陈述也采用不同的参数。

思想?

sub showcaseViewsSubData {
    my ($api_call, $stat_section, $idsite, $prev_date, $last_of_month, $params, $subtable) = @_;

    return unless ($subtable);

    my %sub_params = %{ clone ($params) };
    $sub_params{'idSubtable'} = $subtable->{'idsubdatatable'};

    # $data contains views for each primary showcase page
    my $data = &fetchStatsData($api_call, \%sub_params);

    foreach my $visit_group (@$data) {

        # ignore product pages
        next if ($visit_group->{'url'} && $visit_group->{'url'} =~ /\/products?\//);

        # if ($visit_group->{'url'} && $visit_group->{'url'} =~ /inthenews|pressreleases|downloads/) {
        if ($visit_group->{'idsubdatatable'}) {
            &showcaseViewsSubData($api_call, $stat_section, $idsite, $prev_date, $last_of_month, $params, $visit_group);
            next;
        }

        my $division_name;

        if ($visit_group->{'url'}) {
            my $showcase_id = $visit_group->{'url'};
            $showcase_id =~ s/^.*?\/(\d+)\/.*$/$1/;

            $division_by_showcase_id_sth->execute($showcase_id);
            ($division_name) = $division_by_showcase_id_sth->fetchrow_array();

        } else {
            $visit_group->{'orig_label'} = $visit_group->{'label'};
            $visit_group->{'label'} =~ s/-/%/g;
            $visit_group->{'label'} =~ s|^/||g;
            $visit_group->{'label'} .= '%';
            $division_sth->execute($visit_group->{'label'});
            ($division_name) = $division_sth->fetchrow_array();
        }

        if ($division_name) {

            ## no idea why this is nb_hits, and not nb_actions, like every other method
            my @data_value = ( { 'nb_actions' => ($visit_group->{'nb_hits'} || $visit_group->{'nb_visits'}), 'label' => $division_name } );
            &updateCompanyStats($idsite, 'showcase', $prev_date, \@data_value);
        }
    }
    return 1;
}

sub researchViewsSubData {
    my ($api_call, $stat_section, $idsite, $prev_date, $last_of_month, $params, $subtable) = @_;

    return unless ($subtable);

    my %sub_params = %{ clone ($params) };
    $sub_params{'idSubtable'} = $subtable->{'idsubdatatable'};

    # $data contains views for each primary showcase page
    my $data = &fetchStatsData($api_call, \%sub_params);

    if (ref $data ne 'ARRAY') {
        carp "$api_call returned something not an array!";
        return 0;
    }

    foreach my $visit_group (@$data) {
        # if ($visit_group->{'url'} && $visit_group->{'url'} =~ /inthenews|pressreleases|downloads/) {
        if ($visit_group->{'idsubdatatable'}) {
            &researchViewsSubData($api_call, $stat_section, $idsite, $prev_date, $last_of_month, $params, $visit_group);
            next;
        }

        my $division_name;

        if ($visit_group->{'url'}) {
            my $tag_id = $visit_group->{'url'};
            $tag_id =~ s/^.*?\/(\d+)\/.*$/$1/;

            next if ($tag_id !~ /^\d+$/);

            $division_by_tag_id_sth->execute(int($tag_id), int($idsite));
            ($division_name) = $division_by_tag_id_sth->fetchrow_array();

        } else {
            carp Dumper($visit_group);
        }

        if ($division_name) {
            ## no idea why this is nb_hits, and not nb_actions, like every other method
            my @data_value = ( { 'nb_actions' => ($visit_group->{'nb_hits'} || $visit_group->{'nb_visits'}), 'label' => $division_name } );

            &updateCompanyStats($idsite, 'research', $prev_date, \@data_value);
        }
    }
    return 1;
}

2 个答案:

答案 0 :(得分:5)

正如Sinan所说,你应该从头开始设计一个新的类或模块(或一组)来处理你需要的功能。

以下是我根据您的代码制作的内容。这只是一个给你指路的大纲。

package MyCompanyStats;

sub process_stats {
    my $params = shift;
    my $data = fetchStatsData($params);
    foreach my $visit_group (@$data) {
        process_stats_group($visit_group);
    }
}

sub process_stats_group {
    my $group = shift;
    if ($group->{'url'}) {
        my $showcase_id = get_showcase_id($group);
        save_by_showcase_id($showcase_id, $group);
    } else {
        my $group_label = get_group_label($group);
        save_by_label($group_label, $group);
    }
}

sub get_group_label {
    my $group = shift;
    my $label = $group->{'label'};
    for ($label) {
        s/-/%/g;
        s|^/||g;
    }
    $label .= '%';
    return $label;
}

sub get_showcase_id {
    my $group = shift;
    my $showcase_id = $visit_group->{'url'};
    $showcase_id =~ s/^.*?\/(\d+)\/.*$/$1/;
    return $showcase_id;
}

1;

答案 1 :(得分:3)

当你携带这个很多行李时,你需要一些物品是个好例子。除此之外,您可以将它们全部打包成一个“bag”哈希或使用命名对参数 - 至少它看起来会更好。

从代码中我不知道为什么要调用每个代码,所以我把一个笨重的东西放到了名为theDifference的哈希中。

use Params::Util qw<_ARRAY _HASH>;

sub viewsSubData {
    my %params = @_ % 2 ? %{ &_HASH } : @_;

    # we delete because 1. we don't pass it, and we use it once.
    return unless my $subtable = delete $params{subtable};

    # If we only want a hashref to pass to fetchStatsData then 
    # stream params and the desired value in a hashref, and we're done.
    # don't need the clone() call because listing out the hash takes care of that.
    # $data contains views for each primary showcase page
    my $data 
        = fetchStatsData( 
          $params{api_call}
        , { %{ $params{params} }
          , idSubtable => $subtable->{'idsubdatatable'}
          }
        );

    # This was made standard--because the loop will fail with the derefence, anyway
    if ( _ARRAY( $data )) {
        # returning undef is for bad states is standard in Perl
        carp( "$api_call returned something not an array!" ) and return;
    }

    my $is_showcase = $params{theDifference};

    foreach my $visit_group (@$data) {

        # ignore product pages
        next if  $is_showcase
             and $visit_group->{'url'}
             and $visit_group->{'url'} =~ /\/products?\//
             ;

        # if ($visit_group->{'url'} && $visit_group->{'url'} =~ /inthenews|pressreleases|downloads/) {
        if ($visit_group->{'idsubdatatable'}) {
            showcaseViewsSubData( %params, subtable => $visit_group);
            next;
        }

        my $division_name;

        if ( $visit_group->{'url'} ) {
            my ( $tag_id ) = $visit_group->{'url'}=~ m{/(\d+)/};

            $division_by_tag_id_sth->execute( $tag_id, ( $is_showcase ? () : int( $params{idsite} ));
            ($division_name) = $division_by_tag_id_sth->fetchrow_array();

        } 
        elsif ( $is_showcase ) {
            # orig_label seems to do nothing
            for ( $visit_group->{label} ) { 
                s|^/||;
                s/-/%/g;
            }
            $division_sth->execute( $visit_group->{'label'} . '%' );
            ($division_name) = $division_sth->fetchrow_array();
        }
        else {
            carp Dumper( $visit_group ) . "\n ";
        }

        if ($division_name) {

            ## no idea why this is nb_hits, and not nb_actions, like every other method
            my @data_value 
                = { nb_actions => ( $visit_group->{'nb_hits'} || $visit_group->{'nb_visits'} )
                  , label      => $division_name 
                  };
            updateCompanyStats( $idsite, @params{ qw<theDifference prev_date> }, \@data_value );
        }
    }
    return 1;
}

你会这样称呼它:

viewsSubData(
    { theDifference => $whatever ? 'showcase' : 'research'
    , api_call      => $api_call
    , idsite        => $idsite
    , prev_date     => $prev_date
    , params        => $params
    , subtable      => $subtable
    # neither of these were used.
    #, last_of_month => ??
    #, stat_section  => ??
    });