2010-02-11 7 views
12

xem xét lớp đơn giản này:Làm cách nào để có được ngoại lệ có cấu trúc từ Moose?

package Foo; 
use Moose; 
has foo => (is => 'rw', isa => 'Int'); 

Và sau đó mã này:

use Try::Tiny; 
use Foo; 
my $f = try { 
    Foo->new(foo => 'Not an Int'); 
} 
catch { 
    warn $_; 
}; 

Mã này chết với một thông báo lỗi lớn tốt đẹp về kiểu hạn chế thất bại.

Tôi muốn có thể trích xuất thuộc tính nào không thành công (foo), lý do là gì (hạn chế loại không thành công) và giá trị đã vượt qua là (Not an Int) mà không phải phân tích chuỗi lỗi để nhận thông tin.

Something như thế này:

catch { 
    if($_->isa('MooseX::Exception::TypeConstraint')) { 
     my $attrib = $_->attribute; 
     my $type = $_->type; 
     my $value = $_->bad_value; 

     warn "'$value' is an illegal value for '$attrib'. It should be a $type\n"; 
    } 
    else { 
     warn $_; 
    } 
}; 

Đây có phải là có thể? Có bản phân phối MooseX nào có thể thực hiện điều này không? Tốt hơn, có một số tính năng Moose mà tôi bỏ lỡ mà sẽ làm cho điều này có thể?

Cập nhật: Tôi đặc biệt quan tâm đến các ràng buộc về loại, nhưng các lỗi Moose khác cũng rất tốt. Tôi cũng biết rằng tôi có thể ném các đối tượng với die. Vì vậy, cấu trúc ngoại lệ trong mã tôi viết là tương đối dễ dàng.

Trả lời

4

Tôi chưa thử nó, nhưng tôi nghĩ rằng MooseX::Error::Exception::Class có thể là những gì bạn đang tìm kiếm.

+0

Điều này rất thú vị.Nó hoạt động như MooseX :: Throwable nhưng được xây dựng trên Exception :: Class và định nghĩa sự khởi đầu của một hệ thống phân cấp lớp ngoại lệ. Bên trong, nó phân tích cú pháp thông báo lỗi để xác định loại ngoại lệ nào để ném. – daotoad

+0

Thật không may nó đã không được cập nhật trong một thời gian, và không kiểm tra của nó khá nhiều ở khắp mọi nơi. –

3

Kiểm tra MooseX::Throwable, thay thế giá trị error_class trong metaclass. Mã trông hơi cũ tuy nhiên (metaroles hỗ trợ vai trò lớp lỗi bây giờ), nhưng phương pháp hiện tại có vẻ như nó vẫn sẽ làm việc.

+0

Điều này trông rất hứa hẹn, nhưng thuộc tính duy nhất của nó là: ngăn xếp (dấu vết ngăn xếp), previous_exception (trong trường hợp chúng tôi có ngoại lệ lồng nhau) và thư ("Thuộc tính (foo) không ....") . Vẫn đang phân tích cú pháp thư. – daotoad

+1

Aye, tôi nghi ngờ rằng ai đó sẽ phải tạo một lớp ngoại lệ thực sự và xây dựng nó một cách rõ ràng trong trường hợp lỗi (trong mã lõi), thay vì chỉ đơn giản là xây dựng một lớp xung quanh các thư thô được tạo ra ngay bây giờ. Nó sẽ là khá một công việc để đi qua tất cả các mã cốt lõi để thay đổi nó để sử dụng chúng, nhưng tôi chắc chắn rất nhiều người sẽ cảm ơn bạn! – Ether

+0

oops, tôi không có ý định tình nguyện. :) Tôi đã thực sự hy vọng để có được một câu trả lời RTFM tốt đẹp. C'est la vie. – daotoad

1

Tôi đã có câu hỏi tương tự khoảng một năm trước và được hỏi tại #moose kênh IRC. Câu trả lời là Moose không thực sự hỗ trợ các ngoại lệ có cấu trúc ....

Có một thỏa thuận chung rằng đó là một thiếu sót của Moose cần được khắc phục, nhưng nhiệm vụ giới thiệu ngoại lệ ở khắp mọi nơi là tẻ nhạt và chưa thực hiện (afaik).

Cách tiếp cận trong MooseX :: Lỗi :: Ngoại lệ :: Lớp rất dễ vỡ, vì nó dựa trên phân tích cú pháp thư từ Moose.

Vì bạn không thực sự có được ngoại lệ có cấu trúc đáng tin cậy từ Moose, hãy xem xét sử dụng nội tâm để kiểm tra từng ràng buộc loại của bạn từng cái một khi đặt giá trị mới. Một số lần đây là một cách tiếp cận khả thi.

Btw: lưu ý rằng có a nasty bug in the way Moose handles composite constraints.

+0

Yeouch! Đó là một lỗi heckuva. Trong khi ngoại lệ :: Lớp trông thú vị, có vẻ như ** sai ** với tôi để sử dụng hai thư viện xây dựng đối tượng khác nhau trong một dự án. Throwable là thú vị, nhưng tôi nghĩ ngoại lệ là một trong những nơi mà thừa kế có ý nghĩa. Bất cứ điều gì bạn ném, nên ** là một ngoại lệ **, chứ không phải là "làm Throwable" (bất cứ điều gì có nghĩa là ...). Tôi không được bán 100% số tiền thừa kế đó là * giải pháp đúng. Có lẽ câu trả lời là một lớp ngoại lệ duy nhất với các thuộc tính thích hợp. Tôi chưa chắc chắn. – daotoad

+0

Lỗi đó đã bị đóng, nó sẽ xuất hiện. –