Tại sao sử dụng nghiêm ngặt và cảnh báo?


104

Đối với tôi, dường như nhiều câu hỏi trong thẻ Perl có thể được giải quyết nếu mọi người sử dụng:

use strict;
use warnings;

Tôi nghĩ rằng một số người coi những điều này giống như các bánh xe huấn luyện, hoặc các biến chứng không cần thiết, điều này rõ ràng là không đúng, vì ngay cả những lập trình viên Perl rất giỏi cũng sử dụng chúng.

Có vẻ như hầu hết những người thành thạo Perl luôn sử dụng hai pragmas này, trong khi những người được lợi nhất từ ​​việc sử dụng chúng thì hiếm khi làm. Vì vậy, tôi nghĩ sẽ là một ý kiến ​​hay nếu có một câu hỏi để liên kết đến khi khuyến khích mọi người use strictwarnings.

Vì vậy, tại sao một nhà phát triển Perl nên use strictwarnings?


14
Tôi luôn tự hỏi cho các công cụ như thế này tại sao họ không chỉ làm cho nó mặc định và có dev thực sự phải thứ tích cực nới lỏng, mà làuse loose;
Paul Tyng

12
Giống như nhiều thứ hay ho và hữu ích, Perl bắt đầu như một bản hack, như một công cụ cho người phát minh ra nó. Sau đó, nó trở nên phổ biến hơn và ngày càng có nhiều người không có kinh nghiệm bắt đầu sử dụng nó. Đây là thời điểm bạn bắt đầu nghĩ cái gì đó như use strictlà một ý tưởng tốt, nhưng tính tương thích ngược đã trở thành một vấn đề thực sự với bạn :-(
Daniel Böhmer

14
@JB Nizet, @Paul T., Trên thực tế, use strict;được bật theo mặc định khi bạn yêu cầu ngôn ngữ Perl 5.12 (hoặc cao hơn). Cố gắng perl -e"use v5.012; $x=123;". no strict;thực sự tắt nó đi.
ikegami

1
Mặc dù cuối cùng quan điểm của bạn là đúng, nhưng chúng ta càng nói nhiều lần, có lẽ càng nhiều người nghe được. Gần đây đã có một số đồn thổi về việc cố gắng cung cấp nhiều hướng dẫn Perl hơn / tốt hơn / hiện đại hơn và chắc chắn các cảnh báo / nghiêm ngặt sẽ ở trên cùng của mỗi hướng dẫn này. Đối với tôi, tôi có kế hoạch để có s / w trên đỉnh của mỗi đoạn, chỉ cần để mọi người mới nhìn thấy nó mỗi lần
Joel Berger

5
@JoelBerger Không, thực ra nó chẳng giống gì cả. Giống như tôi đã nói, nó chỉ có những từ tương tự trong tiêu đề. Nó để tương thích ngược. là câu đầu tiên trong câu trả lời được chấp nhận, làm thế nào để bạn đề xuất áp dụng cho câu hỏi của tôi?
TLP

Câu trả lời:


83

Đối với người mới bắt đầu, use strict;(và ở mức độ thấp hơn, use warnings;) giúp tìm lỗi chính tả trong các tên biến. Ngay cả những lập trình viên có kinh nghiệm cũng mắc lỗi như vậy. Một trường hợp phổ biến là quên đổi tên một phiên bản của biến khi dọn dẹp hoặc cấu trúc lại mã.

Việc sử dụng sẽ use strict; use warnings;bắt được nhiều lỗi sớm hơn so với những lỗi khác, điều này giúp bạn dễ dàng tìm ra nguyên nhân gốc rễ của lỗi hơn. Nguyên nhân gốc rễ có thể là nhu cầu kiểm tra lỗi hoặc xác thực, và điều đó có thể xảy ra bất kể kỹ năng của lập trình viên hay không.

Điều tốt về các cảnh báo Perl là chúng hiếm khi giả mạo, vì vậy không tốn kém chi phí để sử dụng chúng.


Đọc liên quan: Tại sao sử dụng my?


2
@TLP, tôi không định thực hiện một nghiên cứu để định lượng xem nó có ích gì đâu. Chỉ cần nói rằng họ giúp đỡ vô điều kiện là đủ.
ikegami

1
Tại sao nó được làm tùy chọn sau đó nếu nó có rất nhiều lợi ích? Tại sao không bật nó theo mặc định (như ai đó đã nhận xét ở trên)? Có phải vì lý do tương thích không?
Jean,

4
@Jean, khả năng tương thích ngược. Lưu ý rằng use strict;tính năng này được bật theo mặc định nếu bạn sử dụng phiên bản 5.12 hoặc mới hơn của ngôn ngữ ( use 5.012;).
ikegami

@Jean nếu bạn đang viết một kịch bản đơn giản, bạn thực sự không muốn để có được cảnh báo bởi những cảnh báo về tên handler tập tin hoặc không khai báo biến trước khi sử dụng chúng :-)
user2676847

28

Rõ ràng use strictnên (phải) được sử dụng khi bạn muốn buộc perl phải viết mã đúng cách, điều này có thể buộc phải khai báo, rõ ràng trên các chuỗi và phụ, tức là từ khóa hoặc sử dụng refs một cách thận trọng. Lưu ý: nếu có lỗi sử dụng nghiêm ngặt sẽ hủy thực hiện nếu sử dụng.

Mặc dù use warnings;sẽ giúp bạn tìm ra các lỗi nhập trong chương trình như bạn bỏ sót dấu chấm phẩy, bạn đã sử dụng 'elseif' chứ không phải 'elsif', bạn đang sử dụng cú pháp hoặc hàm không dùng nữa, bất cứ điều gì tương tự. Lưu ý: cảnh báo sử dụng sẽ chỉ cung cấp cảnh báo và tiếp tục thực thi, tức là sẽ không hủy bỏ việc thực thi ..

Dù sao, sẽ tốt hơn nếu chúng ta đi vào chi tiết, mà tôi đang suy đoán bên dưới

Từ perl.com (yêu thích của tôi):

sử dụng 'vars' nghiêm ngặt;

có nghĩa là bạn phải luôn khai báo các biến trước khi sử dụng chúng.

Nếu bạn không khai báo, bạn có thể sẽ nhận được thông báo lỗi cho biến chưa được khai báo

Ký hiệu chung "$ variablename" yêu cầu tên gói rõ ràng tại dòng 3 scriptname.pl

Cảnh báo này có nghĩa là Perl không rõ ràng chính xác về phạm vi của biến là gì. Vì vậy, bạn cần phải rõ ràng về các biến của mình, có nghĩa là khai báo chúng bằng myđể chúng bị hạn chế trong khối hiện tại hoặc đề cập đến chúng với tên đủ điều kiện của chúng (ví dụ: $ MAIN :: tên biến).

Vì vậy, lỗi thời gian biên dịch được kích hoạt nếu bạn cố gắng truy cập vào một biến không đáp ứng ít nhất một trong các tiêu chí sau:

  • Được xác định trước bởi chính Perl, chẳng hạn như @ARGV,% ENV và tất cả các biến dấu câu chung như $. hoặc $ _.

  • Được khai báo với của chúng tôi (đối với toàn cầu) hoặc của tôi (đối với từ vựng).

  • Đã nhập từ gói khác. (Việc sử dụng vars pragma giả mạo quá trình nhập, nhưng thay vào đó hãy sử dụng của chúng tôi.)

  • Hoàn toàn đủ điều kiện sử dụng tên gói của nó và dấu phân tách gói bằng dấu hai chấm.

sử dụng 'subs' nghiêm ngặt;

Hãy xem xét hai chương trình

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

Trong cả hai trường hợp, chúng tôi có một test_value () con và chúng tôi muốn đặt kết quả của nó vào $ a. Tuy nhiên, khi chúng tôi chạy hai chương trình, chúng tôi nhận được hai kết quả khác nhau:

Trong chương trình đầu tiên, tại thời điểm chúng ta đến $a = test_value;, Perl không biết bất kỳ con test_value () nào và test_value được hiểu là chuỗi 'test_value'. Trong chương trình thứ hai, định nghĩa của test_value () đứng trước $a = test_value;dòng. Perl nghĩ rằng test_value là cuộc gọi phụ.

Thuật ngữ kỹ thuật cho các từ riêng biệt như test_value có thể là phụ và có thể là chuỗi tùy thuộc vào ngữ cảnh, nhân tiện, là từ trần . Việc xử lý từ trần của Perl có thể khó hiểu và nó có thể gây ra lỗi trong chương trình.

Lỗi là những gì chúng tôi gặp phải trong chương trình đầu tiên của mình, Hãy nhớ rằng Perl sẽ không mong đợi để tìm thấy test_value(), vì vậy vì nó chưa thấy test_value (), nó giả định rằng bạn muốn một chuỗi. Vì vậy, nếu bạn use strict subs;, nó sẽ khiến chương trình này chết với lỗi:

Không cho phép sử dụng từ trần "test_value" trong khi "đăng ký nghiêm ngặt" được sử dụng tại ./a6-strictsubs.pl dòng 3.

Giải pháp cho lỗi này sẽ là
1. Sử dụng dấu ngoặc đơn để làm rõ rằng bạn đang gọi một phụ. Nếu Perl thấy $ a = test_value () ;,
2. Khai báo phụ của bạn trước khi bạn sử dụng lần đầu

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3. Và Nếu bạn muốn sử dụng nó như một chuỗi, hãy trích dẫn nó.

Vì vậy, sự nghiêm ngặt này khiến Perl coi tất cả các từ khóa trần là lỗi cú pháp. * Một bareword là bất kỳ tên trần hoặc nhận dạng mà không có sự giải thích khác buộc bởi hoàn cảnh. (Ngữ cảnh thường bị ép buộc bởi một từ khóa hoặc mã thông báo gần đó, hoặc bằng cách khai báo trước từ được đề cập.) * Vì vậy, Nếu bạn muốn sử dụng nó như một chuỗi, hãy trích dẫn nó và nếu bạn muốn sử dụng nó như một lệnh gọi hàm, hãy khai báo trước nó hoặc sử dụng dấu ngoặc đơn.

Bareword rất nguy hiểm vì hành vi không thể đoán trước này. use strict; (or use strict 'subs';)làm cho chúng có thể dự đoán được, bởi vì các từ trần có thể gây ra hành vi kỳ lạ trong tương lai sẽ khiến chương trình của bạn chết trước khi chúng có thể tàn phá

Có một nơi mà bạn có thể sử dụng từ trần ngay cả khi bạn đã bật đăng ký nghiêm ngặt: khi bạn chỉ định khóa băm.

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Mật khẩu trong khóa băm luôn được hiểu là chuỗi ký tự, do đó không có sự mơ hồ.

sử dụng 'refs' nghiêm ngặt;

Điều này tạo ra lỗi thời gian chạy nếu bạn sử dụng tham chiếu tượng trưng, ​​cố ý hoặc theo cách khác. Sau đó, một giá trị không phải là một tham chiếu cứng được coi là một tham chiếu tượng trưng . Tức là, tham chiếu được hiểu là một chuỗi biểu diễn tên của một biến toàn cục.

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

cảnh báo sử dụng;

Pragma có phạm vi từ vựng này cho phép kiểm soát linh hoạt các cảnh báo có sẵn của Perl, cả những cảnh báo được phát ra bởi trình biên dịch cũng như những cảnh báo từ hệ thống thời gian chạy.

Từ perldiag:

Vì vậy, phần lớn các thông báo cảnh báo từ các phân loại dưới đây, tức là W, D & S có thể được kiểm soát bằng warningspragma.

(W) Cảnh báo (tùy chọn)
(D) Không dùng nữa (được bật theo mặc định)
(S) Cảnh báo nghiêm trọng (được bật theo mặc định)

Tôi đã liệt kê một số thông báo cảnh báo thường xảy ra bên dưới theo phân loại. Để biết thông tin chi tiết về chúng và những tin nhắn khác, hãy tham khảo perldiag

(W) Một cảnh báo (tùy chọn):

Thiếu đối số trong% s
Thiếu đối số thành -% c
(Ý của bạn là &% s?)
(Ý của bạn là "local" thay vì "our"?)
(Ý của bạn là $ hoặc @ thay vì%?)
% S 'không phải là
độ dài tham chiếu mã () được sử dụng trên% s
Misplaced _ in number

(D) Không dùng nữa (được bật theo mặc định):

đã xác định (@array) không được chấp nhận
được xác định (% băm) không được dùng
nữa Việc sử dụng () của tôi trong điều kiện sai
$ # không còn được hỗ trợ nữa

(S) Cảnh báo nghiêm trọng (được bật theo mặc định)

elseif nên được
tìm thấy elsif % s ở vị trí mà toán tử mong đợi
(Thiếu toán tử trước% s?)
(Thiếu dấu chấm phẩy ở dòng trước?)
% s chưa bao giờ được giới thiệu
Toán tử hoặc thiếu dấu chấm phẩy trước% s
Vấn đề ưu tiên: mở% s nên mở (% s)
Nguyên mẫu không khớp:% s so với% s
Cảnh báo: Việc sử dụng "% s" không có dấu ngoặc đơn là không rõ ràng
Không thể mở% s:% s


10

Hai pragmas này có thể tự động xác định lỗi trong mã của bạn.

Tôi luôn sử dụng điều này trong mã của mình:

use strict;
use warnings FATAL => 'all';

FATALlàm cho mã chết trên các cảnh báo, giống như strictkhông.

Để biết thêm thông tin, hãy xem: Nghiêm ngặt hơn với cảnh báo sử dụng FATAL => 'all';

Ngoài ra ... Các nghiêm khắc, theo Seuss


Trên thực tế, bạn phải trì hoãn FATAL => "all"cho đến thời gian chạy, bằng cách gán cho $SIG{__WARN__} = sub { croak "fatalized warning @_" };hoặc nếu không, bạn làm hỏng trình biên dịch khi cố gắng cho bạn biết nó cần gì.
tchrist

6
@tchrist: Điều này đã luôn hoạt động đối với tôi như hiện tại và đã được ghi nhận. Nếu bạn đã tìm thấy trường hợp nó không hoạt động như được ghi trong tài liệu, vui lòng vá tài liệu bằng cách sử dụng perlbug.
toolic


3

Nguồn :: Các blog khác nhau

Sử dụng sẽ xuất các hàm và tên biến vào không gian tên chính bằng cách gọi hàm import () module.

Một pragma là một mô-đun có ảnh hưởng đến một số khía cạnh của thời gian biên dịch hoặc hành vi thời gian chạy của perl.Pragmas đưa ra gợi ý cho trình biên dịch.

Sử dụng cảnh báo - phàn nàn về các biến chỉ được sử dụng một lần, chuyển đổi không đúng chuỗi thành số,. Cố gắng ghi vào tệp chưa được mở. Điều này xảy ra tại thời điểm biên dịch. Nó được sử dụng để kiểm soát cảnh báo.

Sử dụng phạm vi khai báo biến nghiêm ngặt. Nó được sử dụng để thiết lập một số loại kỷ luật trong tập lệnh. Nếu từ trần được sử dụng trong mã, chúng sẽ được thông dịch.


1

Lệnh "sử dụng nghiêm ngặt" yêu cầu Perl kiểm tra thêm trong quá trình biên dịch mã của bạn. Sử dụng chỉ thị này sẽ giúp bạn tiết kiệm thời gian gỡ lỗi mã Perl của mình vì nó tìm thấy các lỗi mã hóa phổ biến mà bạn có thể bỏ qua.


0

Cảnh báo và nghiêm ngặt đảm bảo rằng các biến của bạn không phải là toàn cục.

Sẽ gọn gàng hơn nhiều khi có thể có các biến duy nhất cho các phương thức riêng lẻ thay vì phải theo dõi từng tên biến.

$ _, hoặc không có biến cho một số hàm nhất định, cũng có thể hữu ích để viết mã nhỏ gọn hơn nhanh hơn.

Tuy nhiên, nếu bạn không sử dụng nghiêm ngặt và cảnh báo, $ _ sẽ trở thành toàn cầu!


0
use strict;
use warnings;

Nghiêm ngặt và cảnh báo là chế độ cho chương trình perl. Nó cho phép người dùng nhập mã một cách tự do hơn và hơn thế nữa, mã perl sẽ trông trang trọng và tiêu chuẩn mã hóa của nó sẽ có hiệu lực.

cảnh báo có nghĩa giống như -wtrong dòng perl shebang, vì vậy nó sẽ cung cấp cho bạn các cảnh báo được tạo bởi chương trình perl, nó sẽ hiển thị trong thiết bị đầu cuối

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.