Điều gì thật tệ?
Các vấn đề với ký hiệu phương pháp gián tiếp có thể tránh được, nhưng dễ dàng hơn khi yêu cầu mọi người tránh ký hiệu phương pháp gián tiếp.
Vấn đề chính rất dễ bị gọi nhầm chức năng.Đi đoạn mã sau, ví dụ:
package Widget;
sub new { ... }
sub foo { ... }
sub bar { ... }
sub method {
...;
my $o = new SubWidget;
...;
}
1;
Trong mã đó, new SubWidget
dự kiến sẽ có nghĩa
SubWidget->new()
Thay vào đó, nó thực sự có nghĩa là
new("SubWidget")
Điều đó nói rằng, sử dụng nghiêm ngặt sẽ bắt hầu hết các trường hợp lỗi này. Được use strict;
để được thêm vào đoạn mã trên, các lỗi sau đây sẽ phải xuất trình:
Bareword "SubWidget" not allowed while "strict subs" in use at Widget.pm line 11.
Điều đó nói rằng, có những trường hợp sử dụng nghiêm ngặt sẽ không bắt lỗi. Chúng chủ yếu liên quan đến việc sử dụng các parens xung quanh các đối số của cuộc gọi phương thức (ví dụ: new SubWidget($x)
).
Vì vậy, đó có nghĩa là
- Sử dụng Object Notation gián tiếp mà không cần dấu ngoặc có thể dẫn đến các thông báo lỗi kỳ lạ.
- Sử dụng Ký hiệu đối tượng gián tiếp với dấu ngoặc đơn có thể dẫn đến mã sai được gọi.
Trường hợp cũ có thể chịu đựng được và sau đó có thể tránh được. Nhưng thay vì nói với mọi người "tránh sử dụng parens xung quanh các đối số của các cuộc gọi phương thức bằng cách sử dụng ký hiệu phương pháp gián tiếp", chúng tôi chỉ nói với mọi người "tránh sử dụng ký hiệu phương pháp gián tiếp". Nó quá mỏng manh.
Có một vấn đề khác. Nó không chỉ là sử dụng ký hiệu đối tượng gián tiếp mà là một vấn đề, nó hỗ trợ nó trong Perl. Sự tồn tại của tính năng này gây ra nhiều vấn đề. Chủ yếu,
- Nó gây ra một số lỗi cú pháp dẫn đến thông báo lỗi rất kỳ quặc/gây nhầm lẫn vì mã dường như đang sử dụng ION khi không.
- Nó ngăn các tính năng hữu ích được triển khai kể từ khi chúng xung đột với cú pháp ION hợp lệ.
Mặt khác, sử dụng no indirect;
sẽ giúp khắc phục sự cố đầu tiên.
dòng đó nên được viết lại như thế nào?
Cách đúng để viết các lời gọi phương thức như sau:
my $some_object = Some::Module->new(FIELD => 'value');
Điều đó nói rằng, ngay cả cú pháp này là mơ hồ. Trước tiên nó sẽ kiểm tra xem một hàm có tên là Some::Module
tồn tại hay không. Nhưng đó là rất không chắc rằng rất ít người tự bảo vệ mình khỏi những vấn đề như vậy.Nếu bạn muốn tự bảo vệ mình, bạn có thể sử dụng như sau:
my $some_object = Some::Module::->new(FIELD => 'value');
Ví dụ yêu thích của tôi về ký hiệu đối tượng gián tiếp: [Tại sao chương trình này hợp lệ? Tôi đã cố gắng để tạo ra một lỗi cú pháp] (http://stackoverflow.com/q/11695110/176646) – ThisSuitIsBlackNot
Vấn đề chính với ION không sử dụng nó nhiều như sự hỗ trợ cho nó trong Perl. Sự tồn tại của tính năng này gây ra nhiều vấn đề. Hai tôi có thể nhớ ngay bây giờ: 1) Nó gây ra một số lỗi cú pháp dẫn đến thông báo lỗi rất kỳ quặc/sai lệch, 2) Nó ngăn các tính năng hữu ích được triển khai kể từ khi chúng xung đột với cú pháp ION hợp lệ. – ikegami