Làm thế nào để dạy Xử lý ngoại lệ cho lập trình viên mới? [đóng cửa]


21

Làm thế nào để bạn đi về giảng dạy Xử lý ngoại lệ cho các lập trình viên. Tất cả những thứ khác được dạy dễ dàng - Cấu trúc dữ liệu, ASP.NET, WinForms, WPF, WCF - bạn đặt tên cho nó, mọi thứ đều có thể được dạy dễ dàng.

Với Xử lý ngoại lệ, việc dạy chúng thử bắt cuối cùng chỉ là bản chất cú pháp của Xử lý ngoại lệ.

Tuy nhiên, điều nên được dạy là - Phần nào trong mã của bạn trong khối thử ? Bạn làm gì trong khối bắt ?

Hãy để tôi minh họa nó với một ví dụ.

Bạn đang làm việc trên Windows Forms Project (một tiện ích nhỏ) và bạn đã thiết kế nó như dưới đây với 3 dự án khác nhau.

  1. UILayer
  2. Doanh nhân
  3. Lớp dữ liệu

Nếu Ngoại lệ (giả sử tải XDocument ném ngoại lệ) được nêu ra tại DataLayer (UILayer gọi BusinessLayer, lần lượt gọi DataLayer), bạn chỉ cần làm như sau

//In DataLayer
try {
    XDocument xd_XmlDocument = XDocument.Load("systems.xml");
} 
catch(Exception ex)
{
    throw ex;
}

cái nào được ném lại trong BusinessLayer và cái nào bị bắt trong UILayer nơi tôi viết nó vào tệp nhật ký?

Đây có phải là cách bạn đi về Xử lý ngoại lệ?


15
Nếu bạn đang đi để làm điều đó, bạn không muốn catch (Exception ex) {ném cũ; } - thay vì chỉ bắt {ném; }
Steven Evers

4
Đừng quên về khối cuối cùng?
Chris

1
Bạn nên chỉ định ngôn ngữ trong các thẻ. Bạn đang đi vào chi tiết hơn là phổ biến đối với hầu hết các triển khai ngoại lệ và bỏ qua những thứ bên ngoài các khối. Ví dụ, trong C ++, phần quan trọng nhất của xử lý ngoại lệ là biết cách viết các chương trình an toàn ngoại lệ.
David Thornley


Tôi hy vọng bạn biết rằng đó là một ý tưởng tồi để bắt bất kỳ "Ngoại lệ" nào. Bạn nên có các khối bắt lồng nhau để bắt các ngoại lệ cụ thể và xử lý chúng cho phù hợp (không chỉ ném ngoại lệ).
trừ

Câu trả lời:


29

Để giải thích xử lý ngoại lệ, giải thích khái niệm đằng sau nó: Mã xảy ra lỗi thường xuyên không biết cách xử lý lỗi đó đúng cách. Mã biết cách xử lý nó đúng cách có thể là hàm được gọi là mã đó hoặc có thể tiếp tục lên ngăn xếp cuộc gọi.

Khi bạn viết một thói quen gọi một thói quen có thể đưa ra một ngoại lệ, nếu bạn biết cách xử lý lỗi đó một cách chính xác, hãy đặt cuộc gọi trong một khối thử và đặt mã xử lý lỗi vào khối bắt. Nếu không, hãy để nó một mình và để một cái gì đó phía trên bạn trong ngăn xếp cuộc gọi xử lý lỗi.

Nói "bắt ex, throw ex" không phải là cách hay để xử lý ngoại lệ, vì nó không thực sự xử lý bất cứ điều gì. Ngoài ra, tùy thuộc vào cách mô hình ngoại lệ trong ngôn ngữ của bạn hoạt động, điều đó thực sự có thể gây hại nếu nó xóa thông tin theo dõi ngăn xếp mà bạn có thể đã sử dụng để gỡ lỗi vấn đề. Chỉ cần để ngoại lệ lan truyền ngăn xếp cuộc gọi cho đến khi nó đạt được một thói quen biết cách xử lý nó.


4
+1 cho "... vì nó không thực sự xử lý bất cứ điều gì", mọi người mới xử lý ngoại lệ nên thường nghĩ rằng bắt có nghĩa là xử lý và không nhận ra nếu bạn không làm gì để khắc phục sự cố, đó không phải là xử lý ngoại lệ, Chỉ cần mã phình.
Jimmy Hoffa

13

Giống như hầu hết mọi thứ, các trường hợp ngoại lệ và xử lý ngoại lệ có vẻ như là một giải pháp tìm kiếm vấn đề cho các lập trình viên mới cho đến khi bạn chỉ ra lý do tại sao giải pháp có vẻ đơn giản hơn (mã trả về kiểu C và errno) lại hoạt động kém như vậy. Tôi sẽ bắt đầu bằng cách thúc đẩy vấn đề và đặt nó trong bối cảnh. Chỉ ra cách xử lý lỗi có thể được thực hiện bằng cách sử dụng mã trả về hoặc biến toàn cục / tĩnh. Sau đó đưa ra ví dụ về lý do tại sao nó không hoạt động tốt. Sau đó và chỉ sau đó, giới thiệu các trường hợp ngoại lệ và giải thích rằng chúng là một dạng tín hiệu ngoài băng tần và toàn bộ vấn đề là hành vi mặc định nếu bạn bỏ qua một ngoại lệ là chuyển giao ngăn xếp cuộc gọi cho ai đó có thể xử lý nó

Điểm mấu chốt: Hiển thị cách xử lý lỗi trong C sẽ khiến học sinh hiểu được ngoại lệ thực sự là gì và tại sao bắt các ngoại lệ mà bạn không thể thực sự xử lý về cơ bản là mô phỏng cách mọi thứ được thực hiện trong Thời đại đen tối.


2
+1 cho thực tiễn giảng dạy về việc dẫn dắt họ theo mã trả về kiểu C và số lỗi truyền thống và cho họ thấy rằng nó hoạt động kém và do đó, dạy họ cách nó hoạt động là một điều tuyệt vời!
Kanini

3
@Kanini: Nói chung tôi nghĩ rằng hầu hết các cấu trúc tương đối mới / cấp cao có vẻ như là giải pháp tìm kiếm vấn đề và rất dễ sử dụng sai nếu bạn không hiểu chúng có ý nghĩa gì để giải quyết và tại sao chúng được phát minh.
dsimcha

Tôi đồng ý rằng cho thấy nó sẽ được thực hiện như thế nào mà không có ngoại lệ là tốt, nhưng sau đó là gánh nặng giải thích khi nào nên sử dụng ngoại lệ và khi nào nên sử dụng các kỹ thuật khác (vì không phải tất cả các tình huống đều là ngoại lệ)
Matthieu M.

@Matthieu: Phải. Nhưng nếu bạn hiểu những vấn đề lịch sử ngoại lệ có ý nghĩa gì để giải quyết, thay vì tìm hiểu về chúng trong chân không, thì rõ ràng là thật ngớ ngẩn khi sử dụng chúng cho các tình huống không đặc biệt.
dsimcha

đúng, đó là lý do tại sao bạn có +1 của tôi. Tôi chỉ cảm thấy câu trả lời của bạn có thể được hiểu là "không bao giờ sử dụng cơ chế khác" :)
Matthieu M.

5

Tôi sẽ bắt đầu với Nguyên tắc thiết kế cho các ngoại lệ ngắn và bao gồm DO, KHÔNG và TRÁNH. Nó cũng đưa ra lý do tại sao.

Trong trường hợp ví dụ của bạn, phần tiết lộ sẽ là Gói ngoại lệ

Và sẽ mong đợi nó được viết theo cách này. Lưu ý rằng nó bắt được một ngoại lệ cụ thể và cố gắng thêm thông tin để thông điệp có ý nghĩa hơn được lan truyền. Cũng lưu ý rằng ngoại lệ bên trong vẫn được duy trì cho mục đích ghi nhật ký

//In DataLayer

try
{
XDocument xd_XmlDocument = XDocument.Load("systems.xml");
}
catch(FileNotFoundException ex)
{
        throw new TransactionFileMissingException(
                     "Cannot Access System Information",ex);
}

CẬP NHẬT Kanini hỏi có đúng không khi có khối ngoại lệ này trong Lớp dữ liệu hoặc việc kiểm tra tệp có sẵn cho Lớp doanh nghiệp hay không.

Vâng, trước tiên tôi muốn chỉ ra rằng lý do căn bản cho các trường hợp ngoại lệ là đây

Xem xét gói các ngoại lệ cụ thể được ném từ lớp thấp hơn trong một ngoại lệ phù hợp hơn, nếu ngoại lệ lớp thấp hơn không có ý nghĩa trong bối cảnh của hoạt động của lớp cao hơn.

Vì vậy, nếu bạn cảm thấy rằng có một lớp cao hơn nên biết về tệp thì lớp dữ liệu của bạn sẽ trông như thế này

//In DataLayer

XDocument xd_XmlDocument = XDocument.Load("systems.xml");

Không thử không bắt.

Cá nhân tôi cảm thấy rằng trừ khi lớp dữ liệu của bạn có thể làm một cái gì đó hữu ích như sử dụng một hệ thống mặc định là tài nguyên lắp ráp, không làm gì hoặc gói ngoại lệ là một đặt cược tốt vì việc ghi nhật ký của bạn sẽ cho bạn biết phương pháp nào và vấn đề của tệp nào. ( throw extrong trường hợp này hoặc ưu tiên throwcũng vậy nhưng không thêm giá trị). Điều này có nghĩa là một khi đã xác định bạn sẽ có thể khắc phục sự cố nhanh chóng.

Như một sự khẳng định ví dụ cụ thể này cũng có vấn đề sau trong XDocument. Tải có thể ném bốn lần thực thi

  • Đối sốNullException
  • Ngoại lệ an ninh
  • FileNotFoundException
  • Ngoại lệ UriFormat

Chúng tôi không thể đảm bảo một cách an toàn rằng mã sau sẽ không ném và FileNotFoundException, đơn giản vì nó có thể ở đó khi chúng tôi kiểm tra sự tồn tại và biến mất khi chúng tôi tải. Có sẵn cho lớp kinh doanh sẽ không giúp đỡ.

 if (File.Exists("systems.xml")) 
     XDocument.Load("systems.xml");

SecurityException thậm chí còn tồi tệ hơn vì trong số các lý do khác khiến việc này bị ném nếu một quá trình khác có khóa tệp độc quyền, bạn sẽ không gặp lỗi cho đến khi bạn thử mở nó để đọc vì không có phương thức File.CanIOpen This (). Và nếu phương thức đó tồn tại, bạn vẫn gặp vấn đề tương tự như với File.Exists


Khắc phục: Cảm ơn! Nhưng liệu có đúng khối ngoại lệ này trong Lớp dữ liệu không? Toàn bộ việc kiểm tra xem Tệp có khả dụng hay không ở trong Lớp nghiệp vụ? Mặt khác, tôi đồng ý với phương pháp viết mã của bạn.
Kanini

Khắc phục: Trong ngôn ngữ mẹ đẻ của tôi, Kanini có nghĩa là Máy tính trong khi Kani có nghĩa là trái cây ;-)
Kanini

Tôi có thể nói rằng bạn không quá buồn vì lỗi của tôi, nhưng tôi rất xin lỗi và tôi đã sửa nó.
Conrad Frix

1
Khắc phục: Khó chịu? Không có gì. Phần lớn là thích thú. Anh tôi đã không ngừng cười kể từ khi tôi chỉ ra điều này với anh ấy chủ yếu bởi vì, dù sao tôi cũng không giống một trái cây ngoại trừ có thể có hình dạng kỳ lạ ...
Kanini

4

Hãy làm một vai trò. (đây không phải là một bài viết đùa)

Bạn nên làm một hội thảo nơi bạn thực hiện chuỗi cuộc gọi. Mỗi người là một đối tượng. Bạn sẽ cần một số người mới và một số người hiểu "trò chơi" giúp.

Sử dụng một vấn đề thực sự đơn giản như tập tin IO. gui-> mô hình-> file_io

Người đang đọc tệp cần phải nói tiếp theo ....

Đầu tiên làm điều đó với mã trả lại. (sử dụng ghi chú sau nó?)

nếu các tương tác chỉ là "những gì mã nói" khá sớm, bạn có thể khiến mọi người nhận ra rằng các ngoại lệ là đặc biệt.

đối với mã trả lại, vượt qua một ghi chú sau nó.

để có ngoại lệ, hãy giơ tay lên và nói vấn đề là gì.

sau đó yêu cầu họ thực hiện "bắt x, ném x" và xem chẩn đoán tệ hơn nhiều là GUI chỉ là "mô hình có ngoại lệ".

Tôi nghĩ rằng điều này sẽ làm việc để đào tạo những người bạn có bởi vì mọi người hiểu tương tác với người khác khá tốt.


+1 cho ý tưởng đóng vai. Chúng tôi chưa bao giờ nghĩ về nó sớm hơn. Bất cứ ai có thể nghĩ rằng việc lập trình giảng dạy có thể được thực hiện thông qua Trò chơi đóng vai?
Kanini

1

Tôi sẽ tưởng tượng để hiểu các trường hợp ngoại lệ trước tiên bạn cần hiểu mối quan hệ con / cha mẹ của các lớp chẳng hạn. Nếu bạn hiểu rằng một đứa trẻ có thể thừa hưởng chức năng từ cha mẹ, thì chúng có thể ở cấp tiểu học hiểu rằng nếu một đứa trẻ có vấn đề thì không thể xử lý nó sẽ chuyển vấn đề này (ngoại trừ) cho cha mẹ và để cha mẹ giải quyết với nó.

Điều này trở thành một mối quan hệ bị xiềng xích cho đến khi bạn kết thúc với một nơi mà một cái gì đó biết cách xử lý ngoại lệ.

Và cuối cùng, đây là phần tầm thường ... khi xảy ra sự cố, phải xử lý nó để chương trình không thoát ra một cách nguy hiểm, sau khi ngoại lệ đó được xử lý, khối cuối cùng sẽ luôn thực thi bất kể bắt thử .

Một ví dụ tốt về điều này có thể là với mạng:

  • chúng tôi tạo kết nối
  • kết nối ổn, vì vậy chúng tôi sử dụng nó
  • khi hoàn thành, chúng tôi đóng và tài nguyên miễn phí

hoặc trong trường hợp ngoại lệ:

  • tạo kết nối
  • một ngoại lệ xảy ra mà một cái gì đó xử lý
  • tại điểm này, chúng tôi giải phóng kết nối và tài nguyên liên quan

1

Cung cấp một Ứng dụng cho người mới có khả năng xử lý Ngoại lệ rất tốt trong đó. Ném một số ngoại lệ ở đâu đó và để chúng gỡ lỗi với sự trợ giúp của Nhật ký. Bằng cách theo dõi xu hướng của Ngoại lệ, họ sẽ có thể gỡ lỗi nó. Làm bài tập này 3 hoặc 4 lần. Bây giờ chỉ cần loại bỏ tất cả các xử lý Ngoại lệ khỏi mã và để chúng cố gắng theo dõi cùng một ngoại lệ.

Tôi tin rằng sự đánh giá cao cho mã Xử lý ngoại lệ sẽ được đánh giá cao ngay lập tức.


Nghe có vẻ giống như một kế hoạch. Bạn có bất kỳ mã mẫu nào có sẵn trên Internet (giả sử, sourceforge.net) mà bạn muốn giới thiệu không?
Kanini

0

IMO, bạn nên nghĩ rằng các câu lệnh xử lý ngoại lệ và kiểm soát luồng về cơ bản là giống nhau. Bạn sử dụng chúng để kiểm soát luồng chương trình của mình dựa trên tình trạng hiện tại của chúng. Sự khác biệt là xử lý ngoại lệ sẽ chỉ phản ứng khi xảy ra lỗi (hoặc ngoại lệ).


@denny: Mặc dù tôi đồng ý với "xử lý ngoại lệ sẽ chỉ phản ứng khi xảy ra lỗi (hoặc ngoại lệ)", tôi không chắc chắn về tuyên bố rằng "các câu lệnh xử lý ngoại lệ và kiểm soát luồng về cơ bản là giống nhau". Tôi tôn trọng không đồng ý ở đó. Khối bắt được thừa nhận làm những gì nó nên làm trong điều kiện đó. Tuy nhiên, khối thử không hoàn toàn về lưu lượng hoặc kiểm soát. Khối cuối cùng, một lần nữa hoàn toàn không phải là về dòng chảy hoặc kiểm soát. Có thể, tôi đã hiểu nhầm câu trả lời của bạn, nhưng bạn có thể làm rõ vì lợi ích của tôi và những người khác không?
Kanini

0

Nó có thể sẽ không giúp một lập trình viên mới, nhưng tôi thấy rằng tôi hiểu khái niệm ngoại lệ tốt hơn rất nhiều khi tôi bắt đầu sử dụng các đơn vị trong lập trình chức năng. Một đơn vị buộc bạn phải xem xét mọi "kênh" thông qua đó dữ liệu có thể đi vào hoặc ra khỏi chương trình, vì tất cả những gì nó cung cấp một sự trừu tượng hóa thuận tiện để "ẩn" một số luồng dữ liệu đó.

Ý tưởng rằng một hàm có thể có các loại đầu ra khác nhau và một ngoại lệ giống như một kiểu trả về ưu tiên cao hơn từ hàm là khá gọn gàng.

Nhắc bạn, tôi hiểu đó không phải là cách các ngoại lệ hoạt động trong hầu hết các ngôn ngữ (chi tiết triển khai), nhưng theo nghĩa trừu tượng, đó là những gì đang xảy ra.


0

Giả vờ một con khỉ đang sử dụng bàn phím

Tôi thường nói với các bạn của mình khi họ đang viết mã để giả vờ rằng một con khỉ sẽ ngồi ở keyborad và sử dụng ứng dụng này.

Điều này dạy họ làm thế nào để dự đoán tất cả các loại:

  • Dữ liệu bị mất
  • Thiếu tập tin
  • Nhân vật Alpha khi bạn mong đợi số
  • Chia cho số không

Tôi nghĩ rằng đó là hình ảnh của việc một con khỉ chỉ cần gõ phím và làm bất cứ điều gì nó muốn thay vì làm theo một cách độc đáo đã làm điều đó. Nó làm việc cho tôi.


Khỉ? Tôi cho rằng, người dùng doanh nghiệp của bạn chưa bao giờ nghe thấy điều đó ;-)
Kanini

@Kanini - Tốt một. Đó là trong những ngày Thủy quân lục chiến của tôi. Tôi chỉ muốn các bạn của tôi nghĩ bên ngoài hộp khi gặp lỗi. Có phải tôi vừa nói bẫy lỗi ... Tôi có nghĩa là xử lý ngoại lệ.
Michael Riley - AKA Gunny
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.