2011-06-20 23 views
9

Tôi đã đọc bài đăng trên blog JRuby Performance: Exceptions are not flow control được chủ trương tránh sử dụng Ngoại lệ ngoại trừ các trường hợp ngoại lệ.Có cách nào khác để giải cứu LoadError cho Ruby không?

Tôi nhận thấy rằng tôi vô tội khi sử dụng cứu hộ để xử lý LoadErrors một cách thường xuyên.

Có cách nào khác thay thế cho require cố gắng tải tệp nếu nó tồn tại, nhưng không ném ngoại lệ nếu không?

Bối cảnh: Nếu bạn đang tự hỏi "tại sao bạn đã có yêu cầu bạn không hoàn toàn yêu cầu?", Đây là câu chuyện của tôi:

  1. Trong khi tôi đang lập trình cho Ruby 1,8, tôi sử dụng require "rdoc/usage" để tôi có thể cung cấp thông tin sử dụng nếu tôi không nhập đúng số tham số trong ứng dụng dòng lệnh của mình. Điều này ném một ngoại lệ trên out-of-the-box 1.9.
  2. Một phần của ứng dụng của tôi liên quan đến mã để thao tác win32ole khi nó chạy trên máy tính để bàn Windows của tôi. Điều này gây ra một LoadError nếu các tập tin có liên quan được chạy dưới máy chủ Linux có tác dụng tính toán nặng. Các tệp sử dụng win32ole cũng có mã khác được kiểm tra trong bộ thử nghiệm của tôi, vì vậy khi chạy bộ thử nghiệm của tôi trong Linux, tôi phải yêu cầu các tệp đó. Tôi nên chia nhỏ các tập tin như vậy, nhưng điều đó có vẻ hơi giống yak cạo râu.
+0

Tôi có trường hợp sử dụng rất giống nhau (cụ thể là: tiện ích mở rộng tùy chọn trong công cụ). Tôi muốn được tò mò để biết nếu LoadError là cách duy nhất để làm điều đó. –

+8

Lưu ý rằng bài viết nói về một trường hợp * vài trăm * ngoại lệ được gửi cho * mọi yêu cầu * Rails đơn lẻ, trong khi bạn đang nói về việc tăng * hai * ngoại lệ * một lần * trong toàn bộ thời gian tồn tại của chương trình. –

Trả lời

2

Sử dụng ngoại lệ cho trường hợp đầu tiên của bạn có thể tốt và ít lộn xộn hơn nhiều so với cố gắng tìm ra nếu require không thành công trước khi gọi. Nếu tất cả những gì bạn đang làm là cố gắng tải một cái gì đó tùy chọn (hoặc, tương tự, bạn cần hỗ trợ một số thư viện khác nhau làm cùng một điều), sau đó cố gắng tải nó và xử lý ngoại lệ là hành vi tốt, tốt và đạo đức.

Trong trường hợp thứ hai của bạn, bạn có thể kiểm tra RUBY_PLATFORM hoặc sys-uname trước khi cố gắng làm những điều cụ thể cho nền tảng như OLE. Đôi khi yak không cần cạo râu. Trong trường hợp này, nếu bạn đang sử dụng Windows thì bạn thực sự muốn có yêu cầu thất bại trong khi nếu bạn đang sử dụng Linux, bạn không muốn yêu cầu gì cả; bạn đang sử dụng các hiệu ứng phụ của ngoại lệ thay vì ngoại lệ.

Đôi khi mọi người cố gắng sử dụng ngoại lệ như một goto có thể bẫy của các loại. Các ngoại lệ dành cho các điều kiện lỗi không thể phục hồi, không phải là một hệ thống thông báo sự kiện chung. Sử dụng ngoại lệ như một goto (tức là kiểm soát dòng chảy) là lạm dụng hệ thống xử lý ngoại lệ và những người xây dựng hệ thống sử dụng ngoại lệ để kiểm soát luồng thường kết thúc trong bệnh viện (để "rơi", vào hộp búa, mười lần một hàng).

+0

Bạn sẽ không thực sự sử dụng RUBY_PLATFORM, nhưng tôi hiểu ý của bạn là gì. –

+0

@Andrew: Tôi đã không phải đối phó với các vấn đề đa nền tảng của Ruby, vì vậy, 'RUBY_PLATFORM' là một chút đoán, AFAIK nó có vấn đề về JRuby nên một cái gì đó rõ ràng hơn (chẳng hạn như sys-uname) sẽ tốt hơn ý kiến. –

7

Chương trình máy tính dành hầu hết thời gian của họ trong các vòng lặp. Nếu bạn liên tục nâng cao và cứu các ngoại lệ trong một vòng lặp bên trong, được thực hiện hàng triệu lần trong khi thực thi chương trình của bạn, bạn có thể thực sự có vấn đề về hiệu năng. Nhưng tải các tập tin là một cái gì đó mà thường được thực hiện chỉ trong quá trình khởi tạo chương trình. Nếu bạn nâng cao và giải cứu một vài ngoại lệ trong quá trình khởi động chương trình, tác động đến hiệu suất sẽ quá gần bằng không cho bất kỳ ai để ý.

Bằng cách này, nếu bạn có một phương pháp thực sự nhạy cảm (ví dụ: thực hiện nhiều lần), nhưng bạn muốn có một "goto" cho phép bạn nhảy ra khỏi nhiều khối và thậm chí lên ngăn xếp cuộc gọi (như một ngoại lệ), sử dụng throwcatch. Chúng tương tự như raiserescue, nhưng nhanh hơn nhiều. Hầu hết chi phí hiệu suất của việc tăng ngoại lệ đến từ việc điền vào dấu vết ngăn xếp và throw không làm điều đó.

IMHO, begin; require "..."; rescue LoadError là thành ngữ Ruby và không được coi là thực hành không tốt theo bất kỳ cách nào, bất kể mọi người nói gì về "sử dụng ngoại lệ cho kiểm soát luồng". Nếu kịch bản của bạn thường được thực hiện trên Windows, chạy trên Linux có thể được coi là một "điều kiện đặc biệt", và đáng được sử dụng ngoại lệ. Nói chung, nếu một tệp bạn muốn tải không có ở đó, đó là "điều kiện ngoại lệ" - đó là lý do tại sao require đặt ra ngoại lệ ngay từ đầu!

Giữ đầu bạn lên cao! Đừng để những kẻ thù ghét làm bạn cảm thấy tội lỗi khi sử dụng mã đơn giản, thông thường!

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