我应该避免在Perl中嵌套if语句吗?

时间:2009-07-28 12:33:18

标签: perl coding-style nested

我正在做一些Perl并且看到我的嵌套“if”语句让我发疯。我设法在另一部分中使用防护块来减少其中一些,但我被困在这里。

您认为我可以保留代码,还是有一种“正确”的方式来重构以下内容? (我也承认对Perl来说比较新)

这实际上是一个子程序,要求用户输入列表的每个参数(外部文件)。 $ [3]是匹配模式,$ [2]是所考虑参数的默认值(如果没有则为NULL),$ _ [1]指定它是否是必需的。 'next'语句引用下一个参数read(while循环)。

在大家的帮助下(谢谢!),这是最新版本。

100         if ( $input ne '' && ( $input !~ $match || $input =~ /'.+'/ ) ) {
101             print "! Format not respected. Match : /$match/ (without \' \')\n";
102             next;
103         }
104         if ( $input eq '' ) {
105             if ( $default eq 'NULL' ) {
106                 if ( $manda eq 'y' ) {
107                     print "! Mandatory parameter not filled in\n";
108                     next;
109                 }
110                 print "+ Ignoring parameter.\n";
111                 $input = '';
112             }
113             else {
114                 print "+ Using default value\n";
115                 $input = $default;
116             }
117         }

 98        if($input eq ''){
 99             if($_[2] eq 'NULL'){
100                 if($_[1] eq 'y'){
101                     print "! Mandatory parameter not filled in\n";
102                     next;
103                 }
104                 else{
105                     print "+ Ignoring parameter.\n";
106                     $input = '';
107                 }
108             }
109             else{
110                 print "+ Using default value\n";
111                 $input = $_[2];
112             }
113         }
114         elsif($input !~ $_[3] || $input =~ /'.+'/){
115                 print "! Format not respected. Match : /$_[3]/ (without \' \')\n"; 
116                 next;
117             }
118         }

10 个答案:

答案 0 :(得分:10)

这是一个稍微更易读的混沌答案版本:

# Set sane variable names...
my ($is_required, $default, $pattern) = @_

# Convert the external string convention for simpler evaluation...
$default = undef if $default eq 'NULL'

# Refuse problematic input before going any further...
if ($input ne '' && $input !~ $pattern || $input =~ /'.+'/) {
    print "! Format not respected. Match : /$pattern/ (without \' \')\n"; 
    next;
}


# If there was no input string...
if($input eq '') {

    # Set the default, if one was provided...
    if( $default ) {
        print "+ Using default value\n";
        $input = $default;
    } 
    # otherwise, complain if a default was required...
    else {
        if( $is_required eq 'y' ){
            print "! Mandatory parameter not filled in\n";
            next;
        }
        print "+ Ignoring parameter (no input or default provided).\n";
    }
}

关键点是:

  • 如果您使用下一步退出当前循环
  • ,则不需要其他
  • 应首先处理特殊情况
  • 使用命名变量
  • 可以极大地提高可读性

答案 1 :(得分:4)

有时有助于提高可读性的另一种方法是将部分或全部分支放在命名良好的代码引用中。以下是这个想法的开始:

$format_not_respected = sub {
    return 0 if ...;
    print "! Format not respected....";
    return 1;
}
$missing_mandatory_param = sub {
    return 0 if ...;
    print "! Mandatory parameter not filled in\n";
    return 1;
}

next if $format_not_respected->();
next if $missing_mandatory_param->();
etc...

答案 2 :(得分:3)

if($input ne '' && ($input !~ $_[3] || $input =~ /'.+'/)) {
    print "! Format not respected. Match : /$_[3]/ (without \' \')\n"; 
    next;
}
if($input eq '') {
    if($_[2] eq 'NULL') {
        if($_[1] eq 'y'){
            print "! Mandatory parameter not filled in\n";
            next;
        }
        print "+ Ignoring parameter.\n";
        $input = '';
    } else {
        print "+ Using default value\n";
        $input = $_[2];
    }
}

答案 3 :(得分:3)

主要关注的是保持代码可读。

如果您可以使用嵌套的if语句获取可读代码,请继续。但始终保持常识活跃。

答案 4 :(得分:2)

通常的做法是为数组索引定义常量,并为它们指定有意义的名称。如:

use constant MANDATORY => 1,
             DEFAULT => 2,
             PATTERN => 3;
...
if($_[DEFAULT] eq 'NULL') {
   ...
}

至于嵌套 - 您应该经常尝试减少缩进(意味着保持嵌套级别低),但绝不会这样做,代价是保持代码可以理解。我对嵌套级别没有任何问题,但这也只是代码的一小部分。如果它确实是一个问题,你可以将条件分解为单独的子程序。

答案 5 :(得分:1)

如果逻辑需要嵌套if语句,那么我猜它们没有任何问题。

但是,您可以通过

提高代码的可读性
  1. 仅使用更多的空白区域
  2. 使用您自己的变量而不是直接在@_
  3. 上操作

    这不是更具可读性吗?

     98        if ($input eq '') {
     99             if ($default eq 'NULL'){
    100                 if ($input eq 'y'){
    101                     print "! Mandatory parameter not filled in\n";
    102                     next;
    103                 }
    104                 else {
    105                     print "+ Ignoring parameter.\n";
    106                     $input = '';
    107                 }
    108             }
    109             else {
    110                 print "+ Using default value\n";
    111                 $input = $default;
    112             }
    113         }
    114         elsif ($input !~ $foo || $input =~ /'.+'/) {
    115                 print "! Format not respected. Match : /$foo/ (without \' \')\n"; 
    116                 next;
    117             }
    118         }
    

答案 6 :(得分:0)

鉴于你可能会做一个意大利面goto,否则,绝对不会。

可能更好的是switch case

答案 7 :(得分:0)

如果您不喜欢其他所有内容,可以简化以下内容。

if($input eq ''){
    $input = $_[2];
    $output = "+ Using default value\n";
    if($_[2] eq 'NULL'){
        $input = '';
        $output = "+ Ignoring parameter.\n";
        if($_[1] eq 'y'){
            $output = "! Mandatory parameter not filled in\n";
        }
    }
}
elsif($input !~ $_[3] || $input =~ /'.+'/){
    $output = "! Format not respected. Match : /$_[3]/ (without \' \')\n"; 
}
print $output;

答案 8 :(得分:0)

我认为关注嵌套的主要原因(如果不仅仅是)是算法的复杂性。在其他情况下,您应该担心可读性和可维护性,这可以通过propoer评论和缩进来解决。

我总是找到一个良好的可操作性练习来阅读我的旧代码,不仅仅是关于可读性的反馈,还有技术......

答案 9 :(得分:-2)

我想你可以做逻辑组合来展平它:

if(($input eq '')&&($_[2] eq 'NULL')&&($_[1] eq 'y')){
  print "! Mandatory parameter not filled in\n";
  next;
}

elsif(($input eq '')&&($_[2] eq 'NULL')){
  print "+ Ignoring parameter.\n";
  $input = '';
}

elsif($input eq ''){
  print "+ Using default value\n";
  $input = $_[2];
  next;
}


elsif($input !~ $_[3] || $input =~ /'.+'/){
  print "! Format not respected. Match : /$_[3]/ (without \' \')\n";
}

print $output;

然后你可以用一个开关来使它好一点。