重构现有的perl子类

重构现有的perl子类,perl,Perl,在我的perl代码中有两个几乎相同的subs。我很好奇,如何将它们重构成一个sub 它们之间唯一真正的区别是正则表达式和通过预处理语句进行的查询。准备好的语句也采用不同的参数 想法 sub showcaseViewsSubData { my ($api_call, $stat_section, $idsite, $prev_date, $last_of_month, $params, $subtable) = @_; return unless ($subtable);

在我的perl代码中有两个几乎相同的
sub
s。我很好奇,如何将它们重构成一个
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;
}


正如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;

当你随身携带这么多行李时,你需要一些物品是个很好的例子。除此之外,您可以将其全部打包到单个“bag”散列中,或者使用命名对参数——至少这样看起来会更好

从代码中,我不知道为什么要调用每一个,因此我在名为
差异的散列中加入了一个笨拙的字符

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;
}

您在重新分解方面的最佳尝试是什么?首先,我会删除每个子调用前面的
&
。仅供参考:当您的子调用7个位置参数,其中一个被称为
$params
,我相信可以肯定地说,您的整个方法都需要重新设计。我会从一开始就不写这些东西开始。另外,编写SQL时只返回所需的数据。不要在Perl中过滤结果。我想,这需要一个设计合理的表,表中有
类型
列或其他内容,而不是依赖URL。最后,但并非最不重要的一点是,在要求其他人重写您的代码之前,不要在评论中说您不知道,并找出原因。@gms8994重新组织这两个sub都没有意义。我唯一的建议是从头开始;s/refactor/$alias[rand@alias]/eg除非$REALLY\u LAME\u委婉语
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  => ??
    });