Là bắt ngoại lệ chung thực sự là một điều xấu?


57

Tôi thường đồng ý với hầu hết các cảnh báo phân tích mã và tôi cố gắng tuân thủ chúng. Tuy nhiên, tôi đang có một thời gian khó khăn hơn với điều này:

CA1031: Không bắt các loại ngoại lệ chung

Tôi hiểu lý do cho quy tắc này. Nhưng, trong thực tế, nếu tôi muốn thực hiện cùng một hành động bất kể ngoại lệ bị ném, tại sao tôi lại xử lý từng người một cách cụ thể? Hơn nữa, nếu tôi xử lý các ngoại lệ cụ thể, điều gì sẽ xảy ra nếu mã tôi đang gọi thay đổi để đưa ra một ngoại lệ mới trong tương lai? Bây giờ tôi phải thay đổi mã của mình để xử lý ngoại lệ mới đó. Trong khi đó, nếu tôi đơn giản bắt được Exceptionmã của mình thì không phải thay đổi.

Ví dụ: nếu Foo gọi Bar và Foo cần dừng xử lý bất kể loại ngoại lệ nào được ném bởi Bar, có bất kỳ lợi thế nào trong việc cụ thể về loại ngoại lệ mà tôi bắt được không?

Có lẽ một ví dụ tốt hơn:

public void Foo()
{
    // Some logic here.
    LogUtility.Log("some message");
}

public static void Log()
{
    try
    {
        // Actual logging here.
    }
    catch (Exception ex)
    {
        // Eat it. Logging failures shouldn't stop us from processing.
    }
}

Nếu bạn không bắt được một ngoại lệ chung ở đây, thì bạn phải nắm bắt mọi loại ngoại lệ có thể. Patrick có một điểm tốt OutOfMemoryExceptionkhông nên giải quyết theo cách này. Vậy nếu tôi muốn bỏ qua mọi ngoại lệ OutOfMemoryExceptionthì sao?


12
Thế còn OutOfMemoryException? Mã xử lý giống như mọi thứ khác?
Patrick

@Patrick Điểm tốt. Tôi đã thêm một ví dụ mới trong câu hỏi của tôi để bao gồm câu hỏi của bạn.
Bob Horn

1
Nắm bắt các ngoại lệ chung cũng tệ như đưa ra những tuyên bố chung về những gì bạn nên làm. Nhìn chung không có cách tiếp cận một kích cỡ phù hợp cho tất cả mọi thứ.

4
@Patrick đó sẽ là OutOfMemoryError, tách biệt với Exceptioncây thừa kế vì lý do đó
Darkhogg

Còn trường hợp ngoại lệ bàn phím, như Ctrl-Alt-Del thì sao?
Mawg

Câu trả lời:


33

Những quy tắc này thường là một ý tưởng tốt và do đó nên được tuân theo.

Nhưng hãy nhớ đây là những quy tắc chung. Họ không bao gồm tất cả các tình huống. Họ bao gồm các tình huống phổ biến nhất. Nếu bạn có một tình huống cụ thể và bạn có thể đưa ra lập luận rằng kỹ thuật của bạn tốt hơn (và bạn sẽ có thể viết một nhận xét trong mã để làm rõ lập luận của bạn để làm như vậy), sau đó làm như vậy (và sau đó xem xét nó ngang hàng).

Về phía đối số của các đối số.

Tôi không thấy ví dụ của bạn ở trên là một tình huống tốt để làm như vậy. Nếu hệ thống ghi nhật ký bị lỗi (có lẽ là ghi nhật ký một số ngoại lệ khác) thì có lẽ tôi không muốn ứng dụng tiếp tục. Thoát và in ngoại lệ cho đầu ra để người dùng có thể thấy những gì đã xảy ra.


2
Đồng tình. Ít nhất , bây giờ việc ghi nhật ký thường xuyên ngoại tuyến sẽ tạo ra một số loại điều khoản sẽ cung cấp một loại đầu ra gỡ lỗi nào đó, cho STDERR nếu không có gì khác.
Shadur

6
Tôi ủng hộ cả hai bạn, nhưng tôi nghĩ rằng bạn đang suy nghĩ như các nhà phát triển, không phải người dùng. Một người dùng thường không quan tâm đến việc đăng nhập có xảy ra hay không, miễn là ứng dụng có thể sử dụng được.
Mawg

1
Thật thú vị, vì log4net rõ ràng không muốn dừng ứng dụng chỉ vì đăng nhập thất bại. Và tôi nghĩ nó phụ thuộc vào những gì bạn đang đăng nhập; kiểm toán an ninh, chắc chắn, giết quá trình. Nhưng nhật ký gỡ lỗi? Không quan trọng.
Andy

1
@Andy: Yep mọi thứ phụ thuộc vào những gì bạn đang làm.
Martin York

2
Tại sao bạn không hiểu họ? Và bạn có nên không phấn đấu để làm như vậy?
Mawg

31

Vâng, bắt ngoại lệ chung là một điều xấu. Một ngoại lệ thường có nghĩa là chương trình không thể làm những gì bạn yêu cầu.

Có một số loại ngoại lệ mà bạn có thể xử lý:

  • Các trường hợp ngoại lệ gây tử vong : hết bộ nhớ, tràn ngăn xếp, v.v ... Một số lực lượng siêu nhiên chỉ làm rối tung vũ trụ của bạn và quá trình này đã chết. Bạn không thể làm cho tình hình tốt hơn vì vậy hãy từ bỏ
  • Ngoại lệ bị ném vì lỗi trong mã mà bạn đang sử dụng : Đừng cố xử lý chúng mà thay vào đó hãy khắc phục nguồn gốc của vấn đề. Không sử dụng ngoại lệ để kiểm soát luồng
  • Tình huống đặc biệt : Chỉ xử lý ngoại lệ trong những trường hợp này. Ở đây chúng tôi có thể bao gồm: rút cáp mạng, kết nối internet ngừng hoạt động, thiếu quyền, v.v.

Ồ, và như một quy tắc chung: nếu bạn không biết phải làm gì với một ngoại lệ nếu bạn bắt được nó, tốt hơn hết là hãy nhanh chóng thất bại (chuyển ngoại lệ cho người gọi và để nó xử lý)


1
Còn trường hợp cụ thể trong câu hỏi thì sao? Nếu có lỗi trong mã đăng nhập, có thể bỏ qua ngoại lệ, vì mã thực sự quan trọng không nên bị ảnh hưởng bởi điều đó.
Svick

4
Tại sao không sửa lỗi trong mã đăng nhập thay thế?
Victor Hurdugaci

3
Victor, nó có lẽ không phải là một lỗi. Nếu đĩa nhật ký tồn tại hết dung lượng, đó có phải là lỗi trong mã đăng nhập không?
Carson63000

4
@ Carson63000 - tốt, vâng. Các nhật ký không được viết, do đó: lỗi. Thực hiện các bản ghi xoay kích thước cố định.
gièm pha

5
Đây là câu trả lời tốt nhất imo, nhưng nó thiếu một khía cạnh quan trọng: bảo mật . Có một số trường hợp ngoại lệ xảy ra là kết quả của những kẻ xấu cố gắng f-up chương trình của bạn. Nếu một ngoại lệ bị ném mà bạn không thể xử lý, thì bạn không nhất thiết phải tin vào mã đó nữa. Không ai thích nghe rằng họ đã viết mã cho phép kẻ xấu vào.
Riwalk

15

Vòng ngoài cùng trên cùng phải có một trong số này để in tất cả những gì có thể, và sau đó chết một cái chết khủng khiếp, dữ dội và KHÔNG CÓ (vì điều này không nên xảy ra và ai đó cần phải nghe).

Mặt khác, bạn thường phải rất cẩn thận vì rất có thể bạn đã không lường trước được mọi thứ có thể xảy ra tại địa điểm này, và do đó rất có thể sẽ không xử lý chính xác. Càng cụ thể càng tốt để bạn chỉ bắt những người bạn biết sẽ xảy ra, và để những người không nhìn thấy trước khi nổi bong bóng lên cái chết ồn ào nói trên.


1
Tôi đồng ý với lý thuyết này. Nhưng những gì về ví dụ đăng nhập của tôi ở trên? Điều gì nếu bạn đơn giản muốn bỏ qua các ngoại lệ đăng nhập và tiếp tục? Bạn có cần phải nắm bắt mọi ngoại lệ có thể được ném và xử lý từng trường hợp đó trong khi để bong bóng ngoại lệ nghiêm trọng hơn không?
Bob Horn

6
@BobHorn: Hai cách nhìn vào đó. Có, bạn có thể nói rằng việc đăng nhập không đặc biệt quan trọng và nếu thất bại thì nó không nên dừng ứng dụng của bạn. Và đó là một điểm đủ công bằng. Nhưng, điều gì sẽ xảy ra nếu ứng dụng của bạn không đăng nhập được năm tháng và bạn không biết gì? Tôi đã thấy điều này xảy ra. Và sau đó chúng tôi cần các bản ghi. Thảm họa. Tôi sẽ đề nghị làm mọi thứ bạn có thể nghĩ ra để ngừng đăng nhập thất bại là tốt hơn là bỏ qua nó khi nó xảy ra. (Nhưng bạn sẽ không nhận được nhiều sự đồng thuận về điều đó.)
pdr

@pdr Trong ví dụ đăng nhập của tôi, tôi thường gửi thông báo qua email. Hoặc, chúng tôi có sẵn các hệ thống để giám sát nhật ký và nếu nhật ký không được tích cực sử dụng, nhóm hỗ trợ của chúng tôi sẽ nhận được cảnh báo. Vì vậy, chúng tôi đã nhận thức được vấn đề đăng nhập theo những cách khác.
Bob Horn

@BobHorn ví dụ đăng nhập của bạn khá khó khăn - hầu hết các khung ghi nhật ký mà tôi biết, đi rất lâu để không đưa ra bất kỳ ngoại lệ nào sẽ không được gọi như vậy (vì nó sẽ làm cho bất kỳ "tuyên bố nhật ký nào xảy ra tại dòng X trong tệp Y" đều vô dụng )

@pdr Tôi đã đưa ra câu hỏi trong danh sách đăng nhập (Java) về cách làm cho khung ghi nhật ký tạm dừng ứng dụng nếu cấu hình ghi nhật ký không thành công, đơn giản vì điều quan trọng là chúng tôi có nhật ký và bất kỳ lỗi im lặng nào đều không được chấp nhận. Một giải pháp tốt vẫn đang chờ xử lý.

9

Không phải là nó xấu, chỉ là những sản phẩm khai thác cụ thể sẽ tốt hơn. Khi bạn cụ thể, điều đó có nghĩa là bạn thực sự hiểu, cụ thể hơn, ứng dụng của bạn đang làm gì và có nhiều quyền kiểm soát hơn. Nói chung, nếu bạn gặp một tình huống mà bạn chỉ cần bắt Ngoại lệ, hãy đăng nhập và tiếp tục, có thể có một số điều tồi tệ đang xảy ra. Nếu bạn đặc biệt nắm bắt các ngoại lệ mà bạn biết khối mã hoặc phương pháp có thể ném, thì khả năng cao hơn là bạn có thể thực sự phục hồi thay vì chỉ đăng nhập và hy vọng điều tốt nhất.


5

Hai khả năng không loại trừ lẫn nhau.

Trong một tình huống lý tưởng, bạn sẽ nắm bắt tất cả các loại ngoại lệ có thể mà phương thức của bạn có thể tạo ra, xử lý chúng trên cơ sở ngoại lệ và cuối cùng thêm một catchmệnh đề chung để nắm bắt bất kỳ ngoại lệ nào trong tương lai hoặc không xác định. Bằng cách này bạn có được điều tốt nhất của cả hai thế giới.

try
{
    this.Foo();
}
catch (BarException ex)
{
    Console.WriteLine("Foo has barred!");
}
catch (BazException ex)
{
    Console.WriteLine("Foo has bazzed!");
}
catch (Exception ex)
{
    Console.WriteLine("Unknown exception on Foo!");
    throw;
}

Hãy nhớ rằng để nắm bắt các ngoại lệ cụ thể hơn, bạn phải đặt chúng lên hàng đầu.

Chỉnh sửa: Vì các lý do đã nêu trong các nhận xét, đã thêm một lần suy nghĩ lại trong lần bắt trước.


2
Chờ đợi. Tại sao bạn muốn đăng nhập một ngoại lệ không xác định vào bảng điều khiển và tiếp tục? Nếu đó là một ngoại lệ mà bạn thậm chí không biết có thể bị ném bởi mã, thì có lẽ bạn đang nói về lỗi hệ thống. Tiếp tục trong kịch bản này có lẽ là một ý tưởng thực sự tồi tệ.
pdr

1
@pdr Chắc chắn bạn nhận ra đó là một ví dụ giả định. Vấn đề là để hạ thấp việc nắm bắt các ngoại lệ cụ thể và chung chung, chứ không phải cách xử lý chúng.
Rotem

@Rotem Tôi nghĩ bạn có một câu trả lời tốt ở đây. Nhưng pdr có một điểm. Các mã, như là, làm cho nó trông giống như bắt và tiếp tục là tốt. Một số người mới bắt đầu, nhìn thấy ví dụ này, có thể nghĩ rằng đó là một cách tiếp cận tốt.
Bob Horn

Có hay không, nó làm cho câu trả lời của bạn sai. Ngay khi bạn bắt đầu bắt được các ngoại lệ như Out Of Memory và Disk Full và chỉ cần nuốt chúng, bạn sẽ chứng minh tại sao việc bắt các ngoại lệ chung trên thực tế lại rất tệ.
pdr

1
Nếu bạn bắt gặp một ngoại lệ chung chỉ để đăng nhập nó, thì bạn nên suy nghĩ lại sau khi đăng nhập.
Victor Hurdugaci

5

Gần đây tôi đã suy nghĩ tương tự, và kết luận dự kiến ​​của tôi là câu hỏi đơn thuần xuất hiện do hệ thống phân cấp .NET Exception bị rối tung nghiêm trọng.

Lấy ví dụ, tầm thường ArgumentNullExceptioncó thể là một ứng cử viên hợp lý cho một ngoại lệ bạn không muốn bắt, bởi vì nó có xu hướng để chỉ ra một lỗi trong mã chứ không phải là một lỗi runtime hợp pháp. À đúng rồi. Cũng vậy NullReferenceException, ngoại trừ việc NullReferenceExceptionxuất phát SystemExceptiontrực tiếp, do đó, không có nhóm nào bạn có thể đặt tất cả "lỗi logic" để bắt (hoặc không bắt).

Sau đó có các IMNSHO lớn làm hư của việc có SEHExceptionlấy được (thông qua ExternalException) SystemExceptionvà do đó làm cho nó một "bình thường"SystemException Khi bạn nhận được mộtSEHException, bạn muốn viết một bãi chứa và chấm dứt nhanh như bạn có thể - và bắt đầu với NET 4 ít nhất một số Các ngoại lệ SEH được coi là Ngoại lệ Nhà nước Tham nhũng sẽ không bị bắt. Một điều tốt, và một thực tế khiến choCA1031quy tắc trở nên vô dụng hơn, bởi vì bây giờ sự lười biếng của bạncatch (Exception)sẽ không bắt được những loại tồi tệ nhất này.

Sau đó, có vẻ như các công cụ Framework khác không nhất quán xuất phát Exceptiontrực tiếp hoặc thông qua SystemException, thực hiện bất kỳ nỗ lực nào trong việc nhóm các mệnh đề bắt bằng một cái gì đó giống như mức độ nghiêm trọng.

Có một phần của ông Lippert C#nổi tiếng, được gọi là Vexing Exception , nơi ông đưa ra một số phân loại ngoại lệ hữu ích: Bạn có thể tranh luận rằng bạn chỉ muốn bắt những người "ngoại sinh", ngoại trừ ... C#ngôn ngữ và thiết kế của .NET ngoại lệ khung làm cho không thể "chỉ bắt những người ngoại sinh" theo bất kỳ cách thức cô đọng nào. (và, ví dụ, rấtOutOfMemoryException có thể là một lỗi có thể phục hồi hoàn toàn bình thường đối với một API phải phân bổ bộ đệm lớn bằng cách nào đó)

Điểm mấu chốt đối với tôi là, cách thức C#các khối bắt hoạt động và cách phân cấp ngoại lệ của Khung được thiết kế, quy tắc CA1031vượt quá hoàn toàn vô dụng . Nó giả vờ giúp giải quyết vấn đề gốc của "không nuốt ngoại lệ" nhưng nuốt ngoại lệ không có gì để làm với những gì bạn bắt được, nhưng với những gì bạn làm sau đó :

ít nhất 4 cách để xử lý một cách hợp pháp một người bị bắt ExceptionCA1031dường như chỉ xử lý một cách hời hợt một trong số đó (cụ thể là trường hợp ném lại).


Một lưu ý phụ, có một tính năng C # 6 được gọi là Bộ lọc ngoại lệ sẽ CA1031có hiệu lực hơn một chút kể từ đó, bạn sẽ có thể lọc đúng, đúng, lọc đúng các ngoại lệ bạn muốn nắm bắt và có ít lý do hơn để viết một bộ lọc chưa được lọc catch (Exception).


1
Một vấn đề lớn OutOfMemoryExceptionlà không có mã cách tốt đẹp nào có thể chắc chắn rằng nó "chỉ" cho thấy sự thất bại của một phân bổ cụ thể đã được chuẩn bị để thất bại. Có thể một số ngoại lệ nghiêm trọng khác đã bị ném và OutOfMemoryExceptionđã xảy ra trong quá trình ngăn chặn từ ngoại lệ khác. Java có thể đã bị trễ bữa tiệc với "tài nguyên thử" của mình, nhưng nó xử lý các trường hợp ngoại lệ trong quá trình ngăn xếp tốt hơn một chút so với .NET.
supercat

1
@supercat - đủ đúng, nhưng điều đó khá đúng với bất kỳ ngoại lệ chung nào khác của Hệ thống, khi mọi thứ trở nên tồi tệ trong bất kỳ khối cuối cùng nào.
Martin Ba

1
Điều đó đúng, nhưng người ta có thể (và nói chung nên) bảo vệ finallycác khối chống lại các ngoại lệ mà người ta thực sự có thể mong đợi xảy ra theo cách mà cả hai ngoại lệ ban đầu và mới đều được ghi lại. Thật không may, làm điều đó thường sẽ yêu cầu phân bổ bộ nhớ, có thể gây ra lỗi của chính nó.
supercat

4

Xử lý ngoại lệ Pokemon (phải bắt hết tất cả!) Chắc chắn không phải lúc nào cũng xấu. Khi bạn đưa ra một phương thức cho khách hàng, đặc biệt là người dùng cuối, việc nắm bắt mọi thứ và mọi thứ thay vì ứng dụng của bạn bị sập và cháy sẽ tốt hơn.

Nói chung mặc dù họ nên tránh nơi bạn có thể. Trừ khi bạn có thể thực hiện hành động cụ thể dựa trên loại ngoại lệ, tốt hơn hết là không xử lý và cho phép ngoại lệ nổi lên thay vì nuốt ngoại lệ hoặc xử lý không chính xác.

Có một cái nhìn vào câu trả lời SO này để đọc thêm.


1
Tình huống này (khi nhà phát triển phải là Pokemon Trainer) xuất hiện khi bạn tự tạo toàn bộ phần mềm: bạn đã tạo các lớp, kết nối cơ sở dữ liệu và GUI của người dùng. Ứng dụng của bạn phải phục hồi sau các tình huống như mất kết nối, thư mục người dùng đã bị xóa, dữ liệu bị hỏng, v.v. Người dùng cuối không thích các ứng dụng bị sập và cháy. Họ thích các ứng dụng có thể hoạt động trên một máy tính bị cháy nổ!
Broken_Window

Tôi đã không nghĩ về điều này cho đến bây giờ, nhưng trong Pokemon, người ta thường cho rằng bằng cách 'bắt tất cả' bạn muốn chính xác từng cái một và phải xử lý việc bắt nó một cách cụ thể, điều này trái ngược với cách sử dụng phổ biến của cụm từ này trong số các lập trình viên.
Magus

2
@Magus: Với một phương thức như LoadDocument(), về cơ bản, không thể xác định tất cả những điều có thể sai, nhưng 99% trường hợp ngoại lệ có thể bị ném sẽ chỉ đơn giản là "Không thể diễn giải nội dung của tệp có tên đã cho là một tài liệu; đối phó với nó. " Nếu ai đó cố gắng mở thứ gì đó không phải là tệp tài liệu hợp lệ, thì không nên làm hỏng ứng dụng và giết bất kỳ tài liệu mở nào khác. Xử lý lỗi Pokemon trong những trường hợp như vậy là xấu, nhưng tôi không biết bất kỳ giải pháp thay thế tốt nào.
supercat

@supercat: Tôi chỉ đang làm một điểm ngôn ngữ. Tuy nhiên, tôi không nghĩ nội dung tệp không hợp lệ nghe có vẻ như là một thứ nên ném nhiều hơn một loại ngoại lệ.
Magus

1
@Magus: Nó có thể đưa ra tất cả các loại ngoại lệ - đó là vấn đề. Thường rất khó để dự đoán tất cả các loại ngoại lệ có thể bị ném do hậu quả của dữ liệu không hợp lệ trong một tệp. Nếu một người không sử dụng xử lý PokeMon, một rủi ro khiến ứng dụng bị chết vì ví dụ: tệp đang tải chứa một chuỗi chữ số đặc biệt dài ở một nơi yêu cầu số nguyên 32 bit được định dạng thập phân và xảy ra tràn số logic phân tích cú pháp.
supercat

1

Bắt ngoại lệ chung là xấu vì nó khiến chương trình của bạn ở trạng thái không xác định. Bạn không biết công cụ đã sai ở đâu nên bạn không biết chương trình của bạn đã thực sự làm gì hoặc chưa làm gì.

Nơi tôi sẽ cho phép bắt tất cả là khi đóng một chương trình. Miễn là bạn có thể làm sạch nó ổn. Không có gì khó chịu bằng một chương trình bạn đóng mà chỉ ném một hộp thoại báo lỗi mà không làm gì ngoài việc ngồi đó, không biến mất và ngăn máy tính của bạn đóng.

Trong một môi trường phân tán, phương thức nhật ký của bạn có thể phản tác dụng: bắt một ngoại lệ chung có thể có nghĩa là chương trình của bạn vẫn giữ khóa trên tệp nhật ký ngăn người dùng khác tạo nhật ký.


0

Tôi hiểu lý do cho quy tắc này. Nhưng, trong thực tế, nếu tôi muốn thực hiện cùng một hành động bất kể ngoại lệ bị ném, tại sao tôi lại xử lý từng người một cách cụ thể?

Như những người khác đã nói, thật khó (nếu không nói là không thể) để tưởng tượng một số hành động mà bạn muốn thực hiện bất kể ngoại lệ được ném ra. Chỉ cần một ví dụ là các tình huống trong đó trạng thái của chương trình đã bị hỏng và bất kỳ quá trình xử lý nào khác có thể dẫn đến các vấn đề (đây là lý do cơ bản phía sau Environment.FailFast).

Hơn nữa, nếu tôi xử lý các ngoại lệ cụ thể, điều gì sẽ xảy ra nếu mã tôi đang gọi thay đổi để đưa ra một ngoại lệ mới trong tương lai? Bây giờ tôi phải thay đổi mã của mình để xử lý ngoại lệ mới đó. Trong khi đó nếu tôi chỉ đơn giản là bắt Ngoại lệ thì mã của tôi không phải thay đổi.

Đối với mã sở thích, chỉ cần nắm bắt tốt Exception, nhưng đối với mã cấp độ chuyên nghiệp giới thiệu một loại ngoại lệ mới nên được đối xử tương tự như thay đổi trong chữ ký phương thức, nghĩa là được coi là thay đổi vi phạm. Nếu bạn đăng ký theo quan điểm này thì rõ ràng việc quay lại thay đổi (hoặc xác minh) mã khách hàng là hướng hành động đúng duy nhất.

Ví dụ: nếu Foo gọi Bar và Foo cần dừng xử lý bất kể loại ngoại lệ nào được ném bởi Bar, có bất kỳ lợi thế nào trong việc cụ thể về loại ngoại lệ mà tôi bắt được không?

Chắc chắn, bởi vì bạn sẽ không bị bắt chỉ là ngoại lệ Bar. Cũng sẽ có ngoại lệ rằng các máy khách của Bar hoặc thậm chí thời gian chạy có thể bị ném trong suốt thời gian Bartrên ngăn xếp cuộc gọi. Một văn bản tốt Barnên xác định loại ngoại lệ của riêng nó nếu cần thiết để người gọi có thể nắm bắt cụ thể các ngoại lệ do chính nó phát ra.

Vậy nếu tôi muốn bỏ qua mọi ngoại lệ trừ OutOfMemoryException thì sao?

IMHO đây là cách sai lầm để suy nghĩ về xử lý ngoại lệ. Bạn nên hoạt động trên danh sách trắng (bắt các loại ngoại lệ A và B), không phải trên danh sách đen (bắt tất cả các ngoại lệ ngoài X).


Thông thường có thể chỉ định một hành động nên được thực hiện cho tất cả các trường hợp ngoại lệ cho thấy rằng một hoạt động đã cố gắng không thành công mà không có tác dụng phụ và ngụ ý bất lợi về trạng thái của hệ thống. Ví dụ: nếu người dùng chọn tệp tài liệu để tải, chương trình sẽ chuyển tên của nó sang phương thức "tạo tài liệu với dữ liệu từ tệp đĩa" và phương thức đó không thành công vì một số lý do cụ thể mà ứng dụng không lường trước được đáp ứng các tiêu chí trên), hành vi thích hợp phải là hiển thị thông báo "Không thể tải tài liệu" thay vì làm hỏng ứng dụng.
supercat

Thật không may, không có phương tiện tiêu chuẩn nào mà một ngoại lệ có thể chỉ ra điều quan trọng nhất mà mã khách hàng muốn biết - liệu nó có ngụ ý gì xấu về trạng thái của hệ thống ngoài những gì có thể được ngụ ý bởi việc không thể thực hiện thao tác được yêu cầu hay không. Do đó, mặc dù các tình huống nên xử lý tất cả các trường hợp ngoại lệ là rất hiếm, nhưng có rất nhiều tình huống trong đó nhiều trường hợp ngoại lệ nên được xử lý theo cùng một cách, và không có tiêu chí nào được thỏa mãn bởi tất cả các ngoại lệ như vậy cũng sẽ được thỏa mãn bởi một số trường hợp ngoại lệ. nên được xử lý khác nhau.
supercat

0

Có lẽ . Có những ngoại lệ cho mọi quy tắc, và không có quy tắc nào nên được tuân theo một cách thận trọng. Ví dụ của bạn có thể hình dung là một trong những trường hợp có ý nghĩa để nuốt tất cả các ngoại lệ. Ví dụ: nếu bạn muốn thêm dấu vết vào một hệ thống sản xuất quan trọng và bạn muốn chắc chắn rằng bạn thay đổi không làm gián đoạn nhiệm vụ chính của ứng dụng.

Tuy nhiên , bạn nên suy nghĩ cẩn thận về những lý do có thể dẫn đến thất bại trước khi bạn quyết định âm thầm bỏ qua tất cả. Ví dụ: nếu lý do cho ngoại lệ là:

  • một lỗi lập trình trong phương thức ghi nhật ký khiến nó luôn luôn đưa ra một ngoại lệ cụ thể
  • một đường dẫn không hợp lệ đến tệp nhật ký trong cấu hình
  • Đĩa đầy

Bạn không muốn được thông báo ngay rằng vấn đề này đã có, vì vậy bạn có thể khắc phục nó không? Nuốt phải ngoại lệ có nghĩa là bạn không bao giờ biết điều gì đã xảy ra.

Một số vấn đề (như đĩa đã đầy) cũng có thể khiến các phần khác của ứng dụng bị lỗi - nhưng lỗi này không được ghi lại ngay bây giờ, vì vậy bạn không bao giờ biết!


0

Tôi muốn giải quyết vấn đề này từ góc độ logic hơn là kỹ thuật,

Bây giờ tôi phải thay đổi mã của mình để xử lý ngoại lệ mới đó.

Vâng, ai đó sẽ phải xử lý nó. Đó là ý tưởng. Những người viết mã thư viện sẽ thận trọng khi thêm các loại ngoại lệ mới bởi vì nó có khả năng phá vỡ các máy khách, bạn không nên gặp điều này rất thường xuyên.

Câu hỏi của bạn về cơ bản là "Điều gì sẽ xảy ra nếu tôi không quan tâm điều gì đã xảy ra? Tôi thực sự phải trải qua những rắc rối để tìm hiểu nó là gì?"

Đây là phần làm đẹp: không có bạn.

"Vì vậy, tôi có thể nhìn theo cách khác và có bất cứ điều gì khó chịu bật lên quét dưới thảm tự động và được thực hiện với nó?"

Không, đó cũng không phải là cách nó hoạt động.

Vấn đề là, bộ sưu tập các ngoại lệ có thể luôn lớn hơn bộ sưu tập bạn mong đợi và quan tâm đến bối cảnh của vấn đề nhỏ cục bộ của bạn. Bạn xử lý những người bạn dự đoán và nếu có điều gì đó bất ngờ xảy ra, bạn để nó cho người xử lý cấp cao hơn thay vì nuốt nó. Nếu bạn không quan tâm đến một ngoại lệ mà bạn không mong đợi, bạn đặt cược ai đó lên ngăn xếp cuộc gọi và sẽ phá hoại để giết một ngoại lệ trước khi nó đến tay người xử lý.

"Nhưng ... nhưng ... thì một trong những trường hợp ngoại lệ khác mà tôi không quan tâm có thể khiến nhiệm vụ của tôi thất bại!"

Đúng. Nhưng họ sẽ luôn luôn quan trọng hơn những người được xử lý tại địa phương. Giống như một thiết bị báo cháy hoặc ông chủ bảo bạn dừng những gì bạn đang làm và nhận một nhiệm vụ khẩn cấp hơn xuất hiện.


-3

Bạn nên nắm bắt các ngoại lệ chung ở cấp cao nhất của mọi quy trình và xử lý bằng cách báo cáo lỗi cũng như có thể và sau đó chấm dứt quy trình.

Bạn không nên bắt ngoại lệ chung và cố gắng tiếp tục thực hiện.

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.