2009-07-28 37 views
6

Tôi đang làm một số Perl và nhìn thấy lồng nhau của tôi "nếu" báo cáo là lái xe cho tôi điên. Tôi quản lý để giảm một số người trong số họ với các khối bảo vệ trong một phần khác, nhưng tôi bị mắc kẹt ở đây.Tôi có nên tránh lồng nhau nếu các câu lệnh trong Perl không?

Bạn có nghĩ rằng tôi có thể để nguyên mã như vậy hoặc có cách "thích hợp" để cấu trúc lại những điều sau không? (Tôi cũng thừa nhận là tương đối mới đối với Perl)

Đây thực sự là chương trình con yêu cầu người dùng nhập vào từng thông số của danh sách (tệp bên ngoài). $ [3] là mẫu phù hợp, $ [2] là giá trị mặc định cho tham số được xem xét (NULL nếu không có), $ _ [1] chỉ định nếu nó là bắt buộc hay không. câu lệnh 'next' dùng để chỉ tham số tiếp theo đọc (while loop).

Với sự giúp đỡ của mọi người (cảm ơn!), Đây là phiên bản mới nhất.

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   } 
+1

Điều gì đặc biệt khiến bạn phát điên về những ifs lồng nhau? – innaM

+0

Tôi không biết, tôi chỉ cảm thấy như có một cách khác để viết rằng ... –

Trả lời

10

Dưới đây là một phiên bản nhẹ dễ đọc hơn của sự hỗn loạn câu trả lời:

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

Những điểm chính là:

  • Bạn không cần khác nếu bạn đang thoát khỏi vòng lặp hiện tại với tiếp theo
  • Trường hợp ngoại lệ cần được xử lý trước tiên
  • Bạn có thể cải thiện đáng kể khả năng đọc bằng cách sử dụng các biến được đặt tên
+0

Cảm ơn vì điều đó. Câu trả lời của chúng tôi đã vượt qua (xem bài đăng đầu tiên của tôi). Btw, trong mã của tôi, $ is_required lực lượng người dùng điền vào, nó không phải là một khiếu nại: p (Không thay đổi bất cứ điều gì mặc dù và bạn đã không đọc toàn bộ chương trình con) –

+0

Xin lỗi để tăng gấp đôi bài, nhưng tôi thích cách bình luận của bạn ; và bởi "bạn chưa đọc" tôi có nghĩa là "Tôi chưa đăng". –

+0

Cảm ơn, mặc dù tôi không thể yêu cầu bất kỳ khoản tín dụng nào. Phong cách bình luận là Damian Conway - tôi đã chấp nhận nó sau khi đọc những thứ của anh ấy vì tôi cũng thích nó. ;) –

1

Nếu bạn logic yêu cầu lồng câu lệnh if sau đó tôi đoán không có gì sai với họ là.

Tuy nhiên, bạn có thể cải thiện khả năng đọc của mã của bạn bằng

  1. Sử dụng chỉ là một chút không gian trắng hơn và
  2. Bằng cách sử dụng các biến riêng của bạn thay vì hoạt động trực tiếp trên @_

ISN' điều này có thể đọc được một chút không?

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   } 
+0

Về điểm 1., tôi đang sử dụng Perltidy mỗi một lần trong một thời gian. Tôi hiện đang cố gắng giải quyết vấn đề và gỡ lỗi trước. 2. Tôi đọc (trong cuốn sách của O'reilly và ở nơi khác) rằng nó $ _ và $ @ được sử dụng rộng rãi, mà không đề cập đến bất kỳ hạn chế nào? –

+0

1. Cố gắng giải quyết vấn đề là cách dễ dàng hơn với mã dễ đọc. 2. Hạn chế là dễ đọc. Khi thay thế các lần sử dụng $ _ [x] khác nhau của bạn, ví dụ: tôi ngay lập tức nhận thấy rằng mô tả của bạn về những biến đó có thể không hoàn toàn chính xác. – innaM

+0

1. Bạn hoàn toàn đúng. Tôi thích mã như nó, nhưng nó chắc chắn sẽ được duy trì bởi những người khác (đầu tiên là bạn). 2. @_ là một mảng chứa danh sách các tham số được truyền (theo giá trị) cho hàm. Đúng ? Đối với $ _, tôi chỉ sử dụng nó khi r/w (vào) một filehandle. –

2

Thực hành phổ biến là xác định hằng số cho chỉ mục mảng của bạn và đặt tên cho chúng có ý nghĩa. Chẳng hạn như:

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

Theo như làm tổ - Bạn thường nên cố gắng giảm bớt sự thụt lề (có nghĩa là giữ cho mức độ làm tổ thấp), nhưng không bao giờ làm như vậy tại các chi phí của việc giữ mã dễ hiểu. Tôi không có vấn đề với mức độ làm tổ, nhưng đây cũng chỉ là một đoạn mã nhỏ của bạn. Nếu nó thực sự là một vấn đề, bạn có thể phá vỡ các điều kiện thành các chương trình con riêng biệt.

+0

Như tôi đã nói, đó là một chương trình con, tất cả các biến của tôi là cục bộ. Do đó, tôi không thể sử dụng câu lệnh "sử dụng"? Làm tổ không phải là vấn đề về phần còn lại của mã, thật may mắn. Cảm ơn câu trả lời của bạn. –

+1

'hằng số sử dụng' có một số hạn chế. Các hằng số được tạo với hằng số sử dụng không thể được nội suy (ví dụ: trong các chuỗi), vì chúng không có sigil và không bị lốm đốm trong thời gian chạy. Chúng được sắp xếp theo gói và được tạo tại thời gian biên dịch. Đây là vấn đề nếu bạn có tập hợp không đổi trong thời gian chạy, ví dụ: bởi một hàm. Điều này được mô tả tốt hơn nhiều, và với các ví dụ tuyệt vời, trong cuốn sách 'Thực hành tốt nhất Perl', bởi Damian Conway. –

0

Cho rằng có thể bạn sẽ làm một spaghetti goto khác, Tuyệt đối số

gì có thể tốt hơn là một switch case.

+0

Tôi đã học được bài học của mình: goto là HELL. ;) Chưa bao giờ nghĩ về nó. Trường hợp chuyển đổi không thực sự áp dụng ở đây, vì tôi đang thử nghiệm 4 biến khác nhau. –

+0

Bạn không có nghĩa là 'given' /' when'? –

+0

Nó không chỉ được triển khai với 'tính năng sử dụng' hay 'công tắc sử dụng' perl 6.0 ''? –

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]; 
    } 
} 
+0

Tôi thích điều đó! Cảm ơn ! (ngoại trừ cái ôm khác: p) –

0

bạn có thể đơn giản hóa như sau nếu bạn không thích tất cả của người khác.

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; 
+0

imho, nó mất đi một số khả năng đọc. Cảm ơn anyway;) –

3

Mối quan tâm chính là giữ cho mã có thể đọc được.

Nếu bạn có thể nhận được mã có thể đọc được với các câu lệnh lồng nhau, hãy tiếp tục. Nhưng giữ cho cảm giác thông thường luôn hoạt động ở mọi thời điểm.

+0

Nếu bạn phải duy trì mã của tôi, bạn sẽ gặp khó khăn khi làm như vậy? –

+0

@Isaac, no. (Nhưng tôi được đào tạo để duy trì khó đọc mã vì vậy tôi không phải là một tài liệu tham khảo tốt). –

-2

Tôi cho rằng bạn có thể làm kết hợp logic để san bằng nó ra:

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; 

Sau đó, bạn có thể sử dụng một công tắc để làm cho nó tốt hơn một chút.

+0

Đây thực sự là phiên bản trước của tôi, các thử nghiệm '&&' không phù hợp với tôi. –

+0

Điều này làm giảm cả khả năng đọc và tốc độ. – Imagist

+0

Đây không phải là ngay cả Perl. Perl không có 'elseif' chỉ' elsif'. –

0

Tôi nghĩ rằng lý do chính (nếu không chỉ) cho mối quan tâm liên quan đến lồng là phức tạp thuật toán. Trên các trường hợp khác, bạn nên lo lắng về khả năng đọc và khả năng bảo trì, có thể được nhấn mạnh với nhận xét propoer và thụt đầu dòng.

tôi luôn luôn tìm thấy một bài tập tốt trong maintanability để đọc mã cũ của tôi, không chỉ để phản hồi về khả năng đọc mà còn về kỹ thuật ...

4

Một phương pháp khác mà đôi khi giúp với khả năng đọc là để đặt một số hoặc tất cả của các nhánh trong các tham chiếu mã được đặt tên tốt. Đây là sự khởi đầu cho ý tưởng:

$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... 
+0

Tôi không biết về điều đó, cảm ơn! Ngay cả khi trong trường hợp của tôi, tôi đã ở trong một chương trình con (lồng nhau nếu hay tiểu thường trình, đó là câu hỏi), có thể có ích cho các kịch bản khác. –

+0

Điều đó sẽ biên dịch một vài người đăng ký mỗi khi bạn gọi chức năng này - đó là * thực sự * những gì bạn muốn làm? Đó là một ý tưởng gọn gàng - và tôi đã đưa bạn lên, nhưng nếu điều này sẽ được gọi rất nhiều, tốt hơn là không sử dụng hành vi bắt giữ. (Tôi nghĩ.) – Axeman

Các vấn đề liên quan