2013-08-05 26 views
13

Tôi đã nhìn thấy mã obfuscated và golf mà giữ là để tránh tuyên bố biến, và tôi có thể nhìn thấy bỏ qua chúng trên dòng lệnh với các -e chuyển đổi để giữ cho một lớp lót ngắn hơn. Một số trường hợp bạn không muốn use strict và/hoặc use warnings trong mã sản xuất là gì? Lý do bạn không muốn sử dụng chúng là gì?Tại sao không sử dụng nghiêm ngặt và cảnh báo trong Perl?

Câu hỏi xuất hiện vì tôi đã xem các bài đăng ở đây, nơi người dùng Perl có kinh nghiệm nói với những người mới sử dụng Perl để luôn sử dụng chúng.

Tôi đã tìm thấy một số câu hỏi có liên quan ở đây nhưng chúng không giải thích trường hợp chúng tôi có thể muốn giữ chúng ở chế độ tắt.

+2

Liên quan: http://stackoverflow.com/q/6050031 –

+0

Bật tính năng này có thể dẫn đến ảo giác rằng mã của bạn đã sẵn sàng để sản xuất. –

+1

http://hype-free.blogspot.com/2008/05/my-perl-blog-how-to-turn-off-warnings.html –

Trả lời

20

pragma giới hạn bạn thành một tập hợp con nhỏ của Perl. Một số tính năng cũ làm cho ý nghĩa lịch sử (hoặc có lợi ích với một lớp lót), nhưng không có chỗ trong một cơ sở mã hiện đại, dễ đọc.

Các strict pragma có ba loại:

  • "vars" Forces bạn khai báo tất cả các biến của bạn. Điều này bảo vệ chống lại lỗi chính tả, và chắc chắn rằng bạn chọn một phạm vi (global/lexical). Trong một lớp lót, điều này không cần thiết nhiều, vì thường có rất ít phạm vi và rất ít biến. Một số thành ngữ một lớp lót sẽ không hoạt động với các biến từ vựng.

  • "refs" không cho phép symrefs. Chúng không có ý nghĩa với các biến từ vựng, và Perl5 có các tham chiếu thực sự. Vì vậy, họ thường vô dụng. Tuy nhiên, symrefs vẫn có giá trị cho lập trình meta:

    # generate accessors 
    for my $field (qw/foo bar baz/) { 
        no strict 'refs'; 
        *{ __PACKAGE__ . '::' . $field } = sub { shift()->{$field} }; 
    } 
    
  • "subs" buộc việc giải thích của hầu hết barewords như các cuộc gọi chương trình con. Điều này giải quyết sự mơ hồ của foo . "bar" thành foo() . "bar". Nếu danh mục này không được kích hoạt và nếu không có foo phụ được xác định, thì nó sẽ được phân tích cú pháp là "foo" . "bar". Điều này có ý nghĩa đối với một lập trình viên vỏ, nơi tất cả các barewords là chuỗi. Nhưng trong một chương trình Perl, điều này làm tăng đáng kể tải nhận thức của lập trình viên, và không đáng giá.

Tóm tắt: cho các kịch bản đơn giản mà không tối ưu hóa để có thể đọc, strict "vars" là không thực sự cần thiết. Có một vài trường hợp mà bạn muốn no strict 'refs'.

Pragma warnings cho phép kiểm soát hạt mịn đối với các thông báo cảnh báo. Điều này đặc biệt quan trọng đối với các lập trình viên mới đối với Perl, những người thường xuyên viết các nội dung như

my %hash = { foo => 1, bar => 2 }; 

và tự hỏi mã đó là HASH(0x1234567). Thậm chí trên một lớp lót, cảnh báo là mong muốn, ngoại trừ trong trường hợp bạn sử dụng stringification của undef, vv

Trong một codebase chuyên nghiệp, không có lý do gì để không sử dụng warningsở khắp mọi nơi. Nếu kịch bản cảnh báo, rất có thể có lỗi và no warnings không làm cho lỗi này biến mất.Kiến thức của bạn về Perl không bao giờ lớn bằng kiến ​​thức của pragma warnings. Ngay cả rất kinh nghiệm cũng mắc lỗi. use warnings là một phím tắt gỡ lỗi tuyệt vời.

Điều đó nói rằng, có thể là hoàn toàn bình luận khi use warnings khi triển khai chương trình. Nhưng không bao giờ để phát triển.

Tùy thuộc vào sự đồng thuận trong đội dev, pragmas khác nên được sử dụng cũng như:

  • no indirect không cho phép các ghét new Foo lời gọi phương thức. Tôi đã nhìn thấy lỗi lẻn trong đó có thể đã bị bắt tại thời gian biên dịch với pragma này.
  • no autovivification ngăn tham chiếu mọc vào sự tồn tại của các hoạt động chỉ đọc như $hash{doesnt_exist}{foo}.
+0

Rất hữu ích! Bạn có một sự cân bằng tuyệt vời giữa việc cung cấp chi tiết và chưa cho bất cứ ai cảm giác rằng họ không cần phải sử dụng cảnh báo/nghiêm ngặt nữa chỉ vì họ biết một số chi tiết. –

4

Làm use strictuse warnings giúp ai đó hiểu chính xác những gì Perl đang làm.

Ai đó hiểu chính xác những gì Perl đang làm và tại sao, tất cả thời gian (tức là, không có ai nhiều), đủ điều kiện để bỏ qua chúng để tiết kiệm không gian và thời gian thực hiện. Thật không may, nhiều người muốn tiết kiệm không gian và thời gian là những người không biết chính xác những gì Perl đang làm và tại sao, và sự hiểu biết của họ về những gì Perl đang làm là dựa trên rất nhiều giả định sai được học từ các ngôn ngữ khác, rằng họ hoàn toàn không bao giờ được phép bỏ qua chúng.

Có một số lý do chính đáng khác nữa:

  • thử nghiệm với hành vi đó sẽ tạo ra một cảnh báo rằng bạn đã nhận thức đầy đủ (ví dụ, rất nhiều đệ quy)
  • sử dụng gói cũ (mặc dù bất kỳ gói nào của tôi được viết sau khoảng tháng 7 năm 2000 vẫn không có thông báo nào với số use strict hoặc use warnings, vì vậy "cũ" ở đây có nghĩa là thực sự, thực sự cũ, như Perl phiên bản 4 trở lên)
  • khi bạn muốn tận dụng lợi thế của Perl huyền diệu hành vi mà không ai mong đợi (nhưng bạn có do mong đợi vì bạn là một chuyên gia) và không muốn trả giá của một cảnh báo để làm như vậy

Bằng cách này, cho các chương trình chấp nhận bất kỳ đầu vào và thực hiện hành động nào dựa trên đầu vào đó, nó cũng rất quan trọng để sử dụng cờ -T để giúp theo dõi việc sử dụng dữ liệu có thể bị nhiễm bẩn thu được từ đầu vào của người dùng.

Cập nhật: @mob đưa ra xác nhận quyền sở hữu trong một nhận xét mang lại một số điều tra, tức là không sử dụng nghiêm ngặt và cảnh báo là tối ưu hóa vi mô bên dưới điểm siêu nhỏ trung bình không đáng kể. Trong mọi trường hợp dưới đây, thời gian thực cho không phải là sử dụng nghiêm ngặt và cảnh báo là 12 mili giây và trong mọi trường hợp bên dưới, thời gian thực để sử dụng chúng là 57 mili giây trở lên. Vì vậy, có thể, giống như tôi đã nói ban đầu, một lợi ích có thể là trong thời gian thực thi (điều đó sẽ chỉ quan trọng nếu bạn đang làm một việc như nhúng các tập lệnh Perl trong các mẫu và chạy 10 hoặc 20 trong số đó mỗi lần một trang web đã được tải, ví dụ), nhưng nó là vẫn còn đề nghị bạn sử dụng chúng trừ khi bạn thực sự biết chính xác những gì Perl đang làm và tại sao, tất cả các thời gian. Mô tả của tôi về danh mục "chuyên gia" này được dự định rất gần với tập hợp trống. Nếu bạn nghĩ rằng bạn rơi vào thể loại này, bạn sẽ tự động không.

[[email protected] ~]$ time perl -e '1;' 

real 0m0.012s 
user 0m0.005s 
sys  0m0.007s 
[[email protected] ~]$ time perl -e '1;' 

real 0m0.012s 
user 0m0.010s 
sys  0m0.005s 
[[email protected] ~]$ time perl -e '1;' 

real 0m0.012s 
user 0m0.011s 
sys  0m0.001s 
[[email protected] ~]$ time perl -e '1;' 

real 0m0.012s 
user 0m0.004s 
sys  0m0.007s 
[[email protected] ~]$ time perl -e '1;' 

real 0m0.012s 
user 0m0.005s 
sys  0m0.007s 
[[email protected] ~]$ time perl -e 'use strict; use warnings;' 

real 0m0.058s 
user 0m0.058s 
sys  0m0.000s 
[[email protected] ~]$ time perl -e 'use strict; use warnings;' 

real 0m0.057s 
user 0m0.041s 
sys  0m0.016s 
[[email protected] ~]$ time perl -e 'use strict; use warnings;' 

real 0m0.057s 
user 0m0.033s 
sys  0m0.025s 
[[email protected] ~]$ time perl -e 'use strict; use warnings;' 

real 0m0.057s 
user 0m0.050s 
sys  0m0.009s 
+2

Bỏ qua cảnh báo 'nghiêm ngặt' và' như một tối ưu hóa vi mô là một ý tưởng khủng khiếp, thậm chí so với các tối ưu hóa vi mô khác. Các lập trình viên chuyên nghiệp, những người hiểu chính xác những gì Perl đang làm là lỗi chính tả, tạo ra các lỗi bất cẩn khác và đọc dữ liệu dơ bẩn mọi lúc. – mob

+2

Và bằng cách tối ưu hóa vi mô, tôi không chỉ có nghĩa là một tối ưu hóa tiết kiệm một lượng thời gian không đáng kể. Nó có nghĩa là "tối ưu hóa" hy sinh nhiều hơn về chất lượng mã, bảo mật, khả năng bảo trì, khả năng đọc và các thứ nguyên khác của kỹ thuật phần mềm vượt quá thời gian chạy. – mob

+0

@mob Cảm ơn, tôi đánh giá cao điều đó. Và một phần của tôi, bởi "một người hiểu chính xác những gì Perl đang làm, và tại sao, tất cả thời gian" Tôi đang có ý định xác định một tập hợp rỗng của các "chuyên gia" thần thoại. Tôi đồng ý với bạn rằng đó là một ý tưởng tồi cho bất cứ ai làm điều này ... ngoại trừ việc một trong những mô hình của Perl là cho phép mọi người "làm theo cách sai lầm nếu họ muốn", điều đó khiến tôi thở phào cứu trợ thay vì cảm thấy tội lỗi khi tôi làm điều đó "sai đường" trong một lớp lót, vv –

9

Đôi khi strictwarnings ngăn cản bạn làm điều bạn muốn làm, thích làm thao tác nhất định trên bảng biểu tượng đó sẽ vi phạm strict 'refs', hoặc xác định lại một chương trình con nơi warnings 'redefine' sẽ được kích hoạt. Vào những lúc khác thuận tiện hơn khi bỏ qua những cảnh báo nhất định hơn là viết mã phòng thủ chống lại chúng, giống như kết xuất cơ sở dữ liệu nhanh chóng và bẩn cho một bảng có thể chứa các giá trị NULL/undef kích hoạt warnings 'uninitialized'.

use strictuse warnings, và chất chống họ no strictno warnings có thể được scoped tại địa phương, vì vậy nó là một thực hành tốt nhất để vô hiệu hóa strictwarnings trong phạm vi thực tế nhỏ nhất.

@data = get_some_data_from_database(); 
if (some_condition()) { 
    no warnings 'uninitialized'; 
    logger->debug("database contains: @$_") for @data; 

    ## otherwise, suppressing the warnings would take something 
    ## less readable and more error-prone like: 
    # logger->debug("database contains: @{[map{defined?$_:''}@$_]}") for @data 
    # logger->debug("database contains: @{[map{$_//''}@$_]}") for @data 
} 
# end of scope, warnings `uninitialized' is enabled again 
+2

Tôi không bỏ phiếu, nhưng điều duy nhất làm phiền tôi về việc đưa ra một ví dụ mã như thế này trong câu trả lời của bạn là mọi người sẽ phóng to trên mã đó. Tôi đã sử dụng để cung cấp cho cùng một loại câu trả lời (ví dụ mã) khi đồng nghiệp hỏi tôi câu hỏi này. Và những gì tôi tìm thấy từ kinh nghiệm là loại ví dụ mã này tạo ra rất nhiều "kiddies script" tắt cảnh báo trong các phần khác nhau của mã của họ vì không có lý do chính đáng, chỉ vì họ nghĩ rằng nó làm cho họ trông giống như một "chuyên gia". –

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