2011-10-11 8 views
6

Tôi có một mạch điều khiển mà tôi giao tiếp với qua cổng nối tiếp. Nếu lệnh trả lời không khớp với một định dạng nhất định, tôi coi đó là lỗi và đã tự hỏi liệu tôi có nên trả lại mã lỗi hoặc ném ngoại lệ không? Ví dụ:C# Mã lỗi so với ngoại lệ

public double GetSensorValue(int sensorNumber) 
{ 
    ... 
    string circuitCommand = "GSV,01," + sensorNumber.ToString(); // Get measurement command for specified sensor. 
    string responseCommand; 
    string expectedResponseCommand = "GSV,01,1,OK"; 
    string errorResponseCommand = "ER,GSV,01,1,62"; 

    responseCommand = SendReceive(circuitCommand); // Send command to circuit and get response. 

    if(responseCommand != expectedResponseCommand) // Some type of error... 
    { 
     if(responseCommand == errorResponseCommand) // The circuit reported an error... 
     { 
     ... // How should I handle this? Return an error code (e.g. -99999) or thrown an exception? 
     } 
     else // Some unknown error occurred... 
     { 
     ... // Same question as above "if". 
     } 
    } 
    else // Everything is OK, proceed as normal. 
     ... 
} 

Cảm ơn!

Trả lời

8

Trong hầu như tất cả trường hợp tôi sẽ liên lạc lỗi qua ngoại lệ. Tôi gần như không bao giờ sử dụng "mã lỗi" như vậy - đôi khi nó rất hữu ích để cung cấp cho thành công/thất bại cùng với kết quả như trong int.TryParse vv, nhưng tôi không nghĩ rằng tình hình này hoạt động như thế. Điều này nghe giống như một điều kiện lỗi thực sự mà nên dừng tiến bộ hơn nữa mặc dù, do đó, một ngoại lệ là thích hợp.

EDIT: Như đã lưu ý trong bình luận, nếu mạch báo cáo lỗi thực sự là "được mong đợi" và người gọi có thể xử lý nó và chủ động tìm kiếm tình huống đó, thì sẽ hợp lý để sử dụng mã trạng thái.

Đáng tiếc là xử lý lỗi là một trong những điều mà chúng ta chưa thực sự có ngay trong công nghệ phần mềm chưa ...

+0

Thú vị; Tôi ngạc nhiên khi bạn đề xuất các trường hợp ngoại lệ đối với việc xử lý lỗi chuẩn. Bạn sẽ không dự trữ ngoại lệ cho các điều kiện bất thường hoặc bất ngờ? –

+0

@JohnWeldon: Không, tôi sẽ sử dụng chúng cho các lỗi có nghĩa là mã gọi điện không nên tiếp tục như thể mọi thứ đều ổn. Có vẻ như điều này * là * một điều kiện bất ngờ mặc dù: "Nếu lệnh trả lời không khớp với một định dạng nhất định, tôi coi đó là lỗi." –

+0

tức làdòng chảy bình thường của chương trình không có ý định xử lý trường hợp này? Tôi đồng ý với việc sử dụng Ngoại lệ trong trường hợp đó. Tuy nhiên, nếu chương trình bình thường mong đợi để đáp ứng với điều kiện lỗi này, tôi sẽ không sử dụng ngoại lệ. Cách giải thích của tôi về câu hỏi là câu hỏi sau, nhưng câu hỏi trước đây sẽ có giá trị như nhau. –

2

Trong trường hợp bạn ném ngoại lệ thì tốt hơn. Bởi vì người gọi phương thức này có thể phân biệt đầu ra "hợp pháp" và một điều kiện lỗi. Nếu bạn trả về một mã lỗi, nó vẫn là một giá trị số để người gọi có thể hiểu sai nó như là một đầu ra từ mạch điều khiển.

3

Nói đúng ra một ngoại lệ sẽ được sử dụng khi bạn đang ở trong một hoàn cảnh 'đặc biệt', tức là cái mà bạn không mong đợi.

Nếu là tôi, tôi có lẽ muốn trả lại một mã lỗi trong trường hợp đầu tiên (được biết đến phản ứng lỗi), và ném một ngoại lệ trong trường hợp thứ hai (mã lỗi không rõ)

+0

+1 "mong đợi điều bất ngờ" - giống như có bảo hiểm (= try + catch) không cho phép tôi lái xe (= ném ngoại lệ) một người không tôn trọng quy tắc lái xe để sau này thấy rằng công ty bảo hiểm không làm những gì cần thiết (xử lý ngoại lệ). – Arun

2

Cá nhân, tôi thích để đối phó với tình huống này bằng cách xác định một đối tượng phản ứng của một số loại. Tôi đã đến đây thông qua kinh nghiệm làm điều này và cân nhắc những gì cần được xem xét đặc biệt. Nếu bạn đang giao tiếp với một số thiết bị và người dùng tắt thiết bị hoặc một cái gì đó, đây là một điều kiện đặc biệt và bạn sẽ ném một ngoại lệ.

Nếu phương pháp cụ thể gọi đến thiết bị không thành công hoặc điều gì đó, điều đó không thực sự đặc biệt, nhưng đó là lỗi. Tôi không muốn định nghĩa một số ma thuật nếu tôi trả lại gấp đôi, và tôi không muốn ném một ngoại lệ. Vì vậy, tôi xác định một cái gì đó như:

class DeviceResult //could also be struct 
{ 
    public double ReturnValue { get; set; } 
    public bool IsValid { get; set; } 
    public string ErrorMessage { get; set; } 
} 

Các chi tiết cụ thể ở đây không thực sự quan trọng - bạn sẽ thích ứng với những gì khách hàng của bạn muốn. Trong ví dụ này, API ứng dụng khách sẽ kiểm tra xem có hợp lệ không và nếu có, hãy sử dụng giá trị trả về - không có số ma thuật và không có ngoại lệ. Mô hình là điều quan trọng hơn. Cách tôi nhìn thấy nó, bạn đang sử dụng một ngôn ngữ hướng đối tượng - vì vậy bạn cũng có thể sử dụng các đối tượng. :)

+0

Ngẫu nhiên, nếu bạn có một số kiểu trả về khác nhau từ API thiết bị, bạn có thể xác định DeviceResult với giá trị trả về là "T" –

0

Mã lỗi.

  1. Trường hợp ngoại lệ ném hoạt động chậm hơn giá trị trả lại.
  2. Bạn được tự do thiết kế chữ ký phương thức, vì vậy bạn có thể trả về bất kỳ loại nào bạn muốn. Nếu bạn phải trả lại một số loại cụ thể mà không thể được mở rộng một cách có ý nghĩa, thì bạn chắc chắn phải ném một ngoại lệ.
  3. Dễ dàng bỏ qua các ngoại lệ hơn mã lỗi khi gọi phương thức. Bạn sẽ phải ghi lại các ngoại lệ mà phương thức của bạn đang ném và hy vọng rằng nhà phát triển khác sẽ đọc nó.
  4. Phản hồi của phương pháp GetSensorValue có các đường dẫn khác nhau. "Con đường hạnh phúc" rõ ràng là mong đợi và thú vị nhất. Nhưng nếu bạn biết rằng người tiêu dùng có thể xử lý các kết quả của ít đường dẫn hapy, thì có nghĩa là đi với mã lỗi là phản ứng "đường không hài lòng" sẽ được mong đợi nhiều hơn.
  5. Việc ném nhiều ngoại lệ có thể khiến trình gỡ lỗi liên tục ngắt tùy thuộc vào cài đặt ngoại lệ trình gỡ lỗi của bạn.
  6. Mã lỗi trở về chắc chắn sẽ làm cho loại câu trả lời của bạn phức tạp hơn, điều này sẽ đòi hỏi nhiều mã hơn để mở khóa giá trị. Nhưng nó thực sự khó đọc và viết "if (response.Status == Statuses.Success) {var value = response.Value;}" thay vì try-catch?

Khi nó là một thực hành tốt để ném ngoại lệ:

  1. Khi bạn có thể thấy trước rằng phương pháp gọi của bạn sẽ thất bại (kiểm tra nếu bạn có thể thực hiện một hoạt động trước khi thực hiện nó). Phương thức "thực hiện" có thể được triển khai để trả lại mã lỗi, nhưng cặp phương thức kiểm tra thực hiện này được coi là một mẫu.
  2. Bạn không thể mở rộng loại phản hồi theo cách có ý nghĩa, nhưng bạn cần báo hiệu phản hồi ở trạng thái không được dự đoán trước theo hợp đồng của phương thức.
  3. Tương tự như trước, bạn có lý do chính đáng để chỉ trả lại kết quả "đường dẫn hạnh phúc".
0

tôi sẽ khuyên bạn sử dụng trường hợp ngoại lệ trong hầu hết các trường hợp do một vài sự kiện đơn giản:

  1. Exceptions là toàn cầu, tất cả -developers C# biết những gì một ngoại lệ là (và hy vọng) làm thế nào để sử dụng nó để gỡ lỗi .
  2. Trường hợp ngoại lệ thoát ra khỏi tất cả các phương thức gọi đến "try catch" gần nhất. Nếu tôi có nhiều lớp và lớp trong cùng ném một ngoại lệ thì tôi có thể xử lý ngoại lệ đó trong bất kỳ lớp nào tôi muốn (thường là lớp ngoài cùng ngoài cùng hoặc ngoài cùng bên ngoài).
  3. Hầu hết các loại dự án đều có một số loại phương thức hoặc sự kiện có thể ghi đè có thể bị ghi đè/đăng ký để triển khai mã ngoại trừ đơn giản toàn cầu. Điều này làm cho nó đơn giản để định dạng thông báo lỗi, thực hiện đăng nhập, gửi thư và cầu nguyện cho các vị thần (hoặc bất cứ điều gì bạn làm gì khi bạn xử lý các trường hợp ngoại lệ;)).

Có một vài điều cần lưu ý mặc dù:

  1. Đó là không được tự do ném một ngoại lệ. Nếu mã của bạn cần được tối ưu hóa 100% thì việc ném ngoại lệ có thể là điều bạn muốn tránh.
  2. Trường hợp ngoại lệ có rất nhiều thông tin bạn có thể không cần. Bạn có thực sự cần một stacktrace nếu tất cả các bạn muốn làm là để hiển thị một người dùng một thông báo lỗi đơn giản?

Nhưng như một quy luật chung, tôi muốn nói: dính vào Exceptions, nó đơn giản, thông tin, thể gỡ lỗi và dễ dàng để xử lý mặc dù nó có thể đến tại một buổi biểu diễn nhẹ chi phí