Làm cách nào tôi có thể tạo và thực thi hợp đồng cho các trường hợp ngoại lệ?


33

Tôi đang cố gắng thuyết phục nhóm của mình để cho phép sử dụng các ngoại lệ trong C ++ thay vì trả lại bool isSuccessfulhoặc enum với mã lỗi. Tuy nhiên, tôi không thể chống lại sự chỉ trích này của anh ấy.

Hãy xem xét thư viện này:

class OpenFileException() : public std::runtime_error {
}

void B();
void C();

/** Does blah and blah. */
void B() {
    // The developer of B() either forgot to handle C()'s exception or
    // chooses not to handle it and let it go up the stack.
    C();
};

/** Does blah blah.
 *
 * @raise OpenFileException When we failed to open the file. */
void C() {
    throw new OpenFileException();
};
  1. Hãy xem xét một nhà phát triển gọi B()hàm. Anh ta kiểm tra tài liệu của nó và thấy rằng nó không trả lại ngoại lệ, vì vậy anh ta không cố bắt bất cứ thứ gì. Mã này có thể làm hỏng chương trình trong sản xuất.

  2. Hãy xem xét một nhà phát triển gọi C()hàm. Anh ta không kiểm tra tài liệu để không bắt ngoại lệ. Cuộc gọi không an toàn và có thể làm hỏng chương trình trong sản xuất.

Nhưng nếu chúng ta kiểm tra lỗi theo cách này:

void old_C(myenum &return_code);

Một nhà phát triển sử dụng chức năng đó sẽ bị trình biên dịch cảnh báo nếu anh ta không cung cấp đối số đó và anh ta nói "Aha, điều này trả về mã lỗi tôi phải kiểm tra."

Làm thế nào tôi có thể sử dụng ngoại lệ một cách an toàn, để có một số loại hợp đồng?


4
@Sjoerd Ưu điểm chính là nhà phát triển bị trình biên dịch buộc phải cung cấp một biến cho hàm để lưu mã trả về; anh ta nhận thức được rằng có thể có lỗi và anh ta nên xử lý nó. Điều đó là vô cùng tốt hơn so với các trường hợp ngoại lệ, không có thời gian biên dịch kiểm tra nào cả.
DBedrenko

4
"anh ta nên xử lý nó" - không có kiểm tra xem điều này có xảy ra không.
Sjoerd

4
@Sjoerd Không cần thiết. Nó đủ tốt để làm cho nhà phát triển biết rằng có thể xảy ra lỗi và họ nên kiểm tra lỗi đó. Điều đó cũng nằm trong tầm nhìn của những người đánh giá, cho dù họ có kiểm tra lỗi hay không.
DBedrenko

5
Bạn có thể có cơ hội tốt hơn bằng cách sử dụng Either/ Resultđơn vị để trả lại lỗi theo cách có thể kết hợp an toàn loại
Daenyth

5
@gardenhead Vì quá nhiều nhà phát triển không sử dụng đúng cách, kết thúc với mã xấu và tiến hành đổ lỗi cho tính năng thay vì chính họ. Tính năng ngoại lệ được kiểm tra trong Java là một điều tuyệt vời, nhưng nó có một đoạn rap tệ bởi vì một số người không nhận được nó.
AxiomaticNexus

Câu trả lời:


47

Đây là một chỉ trích chính đáng của các ngoại lệ. Chúng thường ít nhìn thấy hơn xử lý lỗi đơn giản như trả lại mã. Và không có cách nào dễ dàng để thực thi một "hợp đồng". Một phần của vấn đề là cho phép bạn để ngoại lệ được bắt ở cấp độ cao hơn (nếu bạn phải bắt mọi ngoại lệ ở mọi cấp độ, dù sao thì việc trả lại mã lỗi sẽ khác nhau như thế nào?). Và điều này có nghĩa là mã của bạn có thể được gọi bởi một số mã khác không xử lý nó một cách thích hợp.

Ngoại lệ có nhược điểm; bạn phải làm một trường hợp dựa trên lợi ích chi phí.
Tôi thấy hai bài viết này hữu ích: Sự cần thiết của ngoại lệMọi thứ đều sai với ngoại lệ. Ngoài ra, bài đăng trên blog này cung cấp ý kiến ​​của nhiều chuyên gia về các trường hợp ngoại lệ, tập trung vào C ++ . Trong khi ý kiến ​​chuyên gia dường như nghiêng về các trường hợp ngoại lệ, nó là xa sự đồng thuận rõ ràng.

Đối với việc thuyết phục đội của bạn, đây có thể không phải là trận chiến phù hợp để chọn. Đặc biệt là không có mã kế thừa. Như đã lưu ý trong liên kết thứ hai ở trên:

Các ngoại lệ không thể được truyền qua bất kỳ mã nào không ngoại lệ an toàn. Do đó, việc sử dụng các ngoại lệ ngụ ý rằng tất cả các mã trong dự án phải là ngoại lệ an toàn.

Thêm một chút mã sử dụng ngoại lệ cho một dự án mà chủ yếu không có lẽ sẽ không phải là một cải tiến. Không sử dụng các ngoại lệ trong mã được viết tốt khác xa với một vấn đề thảm khốc; nó có thể không phải là một vấn đề, tùy thuộc vào ứng dụng và chuyên gia mà bạn yêu cầu. Bạn phải chọn các trận đánh của bạn.

Đây có lẽ không phải là một đối số mà tôi sẽ dành nỗ lực - ít nhất là cho đến khi một dự án mới được bắt đầu. Và ngay cả khi bạn có một dự án mới, nó sẽ được sử dụng hoặc được sử dụng bởi bất kỳ mã kế thừa nào?


1
Cảm ơn lời khuyên và các liên kết. Đây là một dự án mới, không phải là một di sản. Tôi tự hỏi tại sao các trường hợp ngoại lệ rất phổ biến khi chúng có một nhược điểm lớn đến mức khiến cho việc sử dụng chúng không an toàn. Nếu bạn bắt một cấp độ ngoại lệ n cao hơn, thì sau đó bạn sửa đổi mã và di chuyển nó, không có kiểm tra tĩnh để đảm bảo ngoại lệ vẫn bị bắt và xử lý (và quá nhiều để yêu cầu người đánh giá kiểm tra tất cả các chức năng ở cấp độ n ).
DBedrenko

3
@Dee xem các liên kết ở trên để biết một số đối số có lợi cho các trường hợp ngoại lệ (Tôi đã thêm một liên kết bổ sung với ý kiến ​​chuyên gia nhiều hơn).

6
Câu trả lời này là tại chỗ!
Doc Brown

1
Tôi có thể nói từ kinh nghiệm rằng cố gắng thêm ngoại lệ vào một cơ sở mã có sẵn là một ý tưởng tồi. Tôi đã làm việc với một cơ sở mã như vậy và thật sự rất khó để làm việc vì bạn không bao giờ biết điều gì sẽ xảy ra trên khuôn mặt của bạn. Ngoại lệ CHỈ nên được sử dụng trong các dự án mà bạn lên kế hoạch cho chúng ở phía trước.
Michael Kohne

26

Có tất cả các cuốn sách được viết về chủ đề này, vì vậy bất kỳ câu trả lời sẽ là một bản tóm tắt tốt nhất. Dưới đây là một số điểm quan trọng tôi nghĩ là đáng để thực hiện, dựa trên câu hỏi của bạn. Đây không phải là một danh sách đầy đủ.


Các ngoại lệ được dự định KHÔNG được bắt gặp ở khắp mọi nơi.

Miễn là có một trình xử lý ngoại lệ chung trong vòng lặp chính - tùy thuộc vào loại ứng dụng (máy chủ web, dịch vụ cục bộ, tiện ích dòng lệnh ...) - bạn thường có tất cả các trình xử lý ngoại lệ bạn cần.

Trong mã của tôi, chỉ có một vài câu lệnh bắt - nếu có ở tất cả - bên ngoài vòng lặp chính. Và đó dường như là cách tiếp cận phổ biến trong C ++ hiện đại.


Các ngoại lệ và mã trả lại không loại trừ lẫn nhau.

Bạn không nên biến điều này thành một cách tiếp cận toàn diện hoặc không có gì. Trường hợp ngoại lệ nên được sử dụng cho các tình huống đặc biệt. Những thứ như "Không tìm thấy tệp cấu hình", "Đĩa đầy" hoặc bất cứ thứ gì khác không thể xử lý cục bộ.

Các lỗi thường gặp, như kiểm tra xem tên tệp do người dùng cung cấp có hợp lệ không, không phải là trường hợp sử dụng cho các trường hợp ngoại lệ; Sử dụng một giá trị trả lại trong những trường hợp thay thế.

Như bạn thấy trong các ví dụ trên, "không tìm thấy tệp" có thể là ngoại lệ hoặc mã trả về, tùy thuộc vào trường hợp sử dụng: "là một phần của cài đặt" so với "người dùng có thể mắc lỗi chính tả".

Vì vậy, không có quy tắc tuyệt đối. Một hướng dẫn sơ bộ là: nếu nó có thể được xử lý cục bộ, hãy biến nó thành giá trị trả về; nếu bạn không thể xử lý nó cục bộ, hãy ném một ngoại lệ.


Kiểm tra tĩnh các trường hợp ngoại lệ là không hữu ích.

Vì các trường hợp ngoại lệ không được xử lý cục bộ, nên thường không có ngoại lệ nào quan trọng. Thông tin hữu ích duy nhất là liệu có ngoại lệ nào có thể được ném ra không.

Java có kiểm tra tĩnh, nhưng nó thường được coi là một thử nghiệm thất bại và hầu hết các ngôn ngữ vì - đặc biệt là C # - không có loại kiểm tra tĩnh đó. Đây là một bài đọc tốt về lý do tại sao C # không có nó.

Vì những lý do đó, C ++ đã throw(exceptionA, exceptionB)từ chối ủng hộ noexcept(true). Mặc định là một hàm có thể ném, vì vậy các lập trình viên nên mong đợi điều đó trừ khi tài liệu hứa hẹn rõ ràng khác.


Viết mã an toàn ngoại lệ không có gì để làm với trình xử lý ngoại lệ.

Tôi muốn nói rằng viết mã an toàn ngoại lệ là tất cả về cách tránh viết trình xử lý ngoại lệ!

Hầu hết các thực hành tốt nhất có ý định giảm số lượng xử lý ngoại lệ. Viết mã một lần và tự động gọi nó - ví dụ thông qua RAII - dẫn đến ít lỗi hơn so với sao chép cùng một mã ở khắp mọi nơi.


3
" Miễn là có một trình xử lý ngoại lệ chung ... bạn thường đã ổn rồi. " Điều này mâu thuẫn với hầu hết các nguồn, nhấn mạnh rằng rất khó để viết mã an toàn ngoại lệ.

12
@ dan1111 "Viết mã an toàn ngoại lệ" không liên quan nhiều đến việc viết trình xử lý ngoại lệ. Viết mã an toàn ngoại lệ là về việc sử dụng RAII để đóng gói tài nguyên, sử dụng "làm tất cả công việc cục bộ trước sau đó sử dụng trao đổi / di chuyển" và các thực tiễn tốt nhất khác. Đó là những thách thức khi bạn không quen với chúng. Nhưng "xử lý ngoại lệ bằng văn bản" không phải là một phần của những thực tiễn tốt nhất đó.
Sjoerd

4
@AxiomaticNexus Ở một mức độ nào đó, bạn có thể giải thích mọi việc sử dụng một tính năng không thành công là "nhà phát triển xấu". Những ý tưởng lớn nhất là những ý tưởng làm giảm việc sử dụng xấu bởi vì chúng làm cho việc thực hiện đúng trở nên đơn giản. Các trường hợp ngoại lệ được kiểm tra tĩnh không thuộc danh mục đó. Họ tạo ra công việc không tương xứng với giá trị của họ, thường ở những nơi mà mã được viết đơn giản thậm chí không cần quan tâm đến chúng. Người dùng bị cám dỗ để bịt miệng họ theo những cách sai lầm để làm cho trình biên dịch ngừng làm phiền họ. Thậm chí được thực hiện đúng, chúng dẫn đến rất nhiều lộn xộn.
jpmc26

4
@AxiomaticNexus Lý do nó không tương xứng là vì điều này có thể dễ dàng truyền tới gần như mọi chức năng trong toàn bộ cơ sở mã của bạn . Khi tất cả các hàm trong một nửa các lớp của tôi truy cập vào cơ sở dữ liệu, không phải tất cả các hàm cần khai báo rõ ràng, nó có thể đưa ra một biểu thức SQLException; không phải mọi phương thức điều khiển gọi chúng. Nhiều tiếng ồn đó thực sự là một giá trị âm, bất kể khối lượng công việc nhỏ như thế nào. Sjoerd đánh vào đầu đinh: hầu hết các mã của bạn không cần phải quan tâm đến các ngoại lệ vì dù sao nó cũng không thể làm gì được chúng .
jpmc26

3
@AxiomaticNexus Có, bởi vì các nhà phát triển tốt nhất rất hoàn hảo, mã của họ sẽ luôn xử lý mọi đầu vào người dùng có thể hoàn hảo, và bạn sẽ không bao giờ thấy những ngoại lệ đó trong prod. Và nếu bạn làm thế, điều đó có nghĩa là bạn là một kẻ thất bại trong cuộc sống. Nghiêm túc, đừng cho tôi rác này. Không ai là hoàn hảo, thậm chí không phải là tốt nhất. Và ứng dụng của bạn nên hoạt động hoàn toàn ngay cả khi đối mặt với những lỗi đó, ngay cả khi "hoàn toàn" là "dừng và trả lại một nửa trang / thông báo lỗi". Và đoán xem: đó cũng là điều bạn làm với 99% IOExceptions . Bộ phận kiểm tra là tùy ý và vô dụng.
jpmc26

8

Các lập trình viên C ++ không tìm kiếm thông số kỹ thuật ngoại lệ. Họ tìm kiếm sự đảm bảo ngoại lệ.

Giả sử một đoạn mã đã ném một ngoại lệ. Những giả định nào mà lập trình viên có thể đưa ra vẫn sẽ hợp lệ? Từ cách viết mã, mã đảm bảo điều gì sau hậu quả của một ngoại lệ?

Hoặc có thể là một đoạn mã nhất định có thể đảm bảo không bao giờ bị ném (tức là không có gì thiếu trong quá trình HĐH bị chấm dứt)?

Từ "quay lại" xảy ra thường xuyên trong các cuộc thảo luận về các trường hợp ngoại lệ. Có thể quay trở lại trạng thái hợp lệ (được ghi lại rõ ràng) là một ví dụ về bảo đảm ngoại lệ. Nếu không có bảo đảm ngoại lệ, một chương trình nên chấm dứt tại chỗ vì thậm chí không đảm bảo rằng bất kỳ mã nào nó thực thi sau đó sẽ hoạt động như dự định - giả sử, nếu bộ nhớ bị hỏng, mọi hoạt động tiếp theo là hành vi không xác định về mặt kỹ thuật.

Các kỹ thuật lập trình C ++ khác nhau thúc đẩy đảm bảo ngoại lệ. RAII (quản lý tài nguyên dựa trên phạm vi) cung cấp một cơ chế để thực thi mã dọn dẹp và đảm bảo rằng các tài nguyên được giải phóng trong cả trường hợp bình thường và trường hợp ngoại lệ. Tạo một bản sao dữ liệu trước khi thực hiện sửa đổi trên các đối tượng cho phép một người khôi phục trạng thái của đối tượng đó nếu thao tác thất bại. Và như vậy.

Các câu trả lời cho câu hỏi StackOverflow này cung cấp một cái nhìn thoáng qua về độ dài tuyệt vời mà các lập trình viên C ++ tìm hiểu tất cả các chế độ thất bại có thể xảy ra với mã của họ và cố gắng bảo vệ tính hợp lệ của trạng thái chương trình mặc dù thất bại. Phân tích từng dòng mã C ++ trở thành thói quen.

Khi phát triển trong C ++ (để sử dụng sản xuất), người ta không thể bỏ qua các chi tiết. Ngoài ra, blob nhị phân (không phải nguồn mở) là nguyên nhân của các lập trình viên C ++. Nếu tôi phải gọi một số blob nhị phân, và blob thất bại, thì kỹ thuật đảo ngược là điều mà một lập trình viên C ++ sẽ làm tiếp theo.

Tham khảo: http://en.cppreference.com/w/cpp/lingu/exceptions#Exception_safe - xem trong An toàn ngoại lệ.

C ++ đã thất bại trong việc thực hiện các thông số kỹ thuật ngoại lệ. Phân tích sau này trong các ngôn ngữ khác nói rằng các thông số kỹ thuật ngoại lệ đơn giản là không thực tế.

Tại sao nó là một nỗ lực thất bại: để thực thi nó một cách nghiêm ngặt, nó phải là một phần của hệ thống loại. Nhưng nó không phải là. Trình biên dịch không kiểm tra đặc tả ngoại lệ.

Tại sao C ++ chọn điều đó và tại sao kinh nghiệm từ các ngôn ngữ khác (Java) chứng minh rằng đặc tả ngoại lệ là moot: Khi một người sửa đổi việc thực hiện một chức năng (ví dụ: nó cần thực hiện một cuộc gọi đến một chức năng khác có thể đưa ra một loại mới ngoại lệ), việc thực thi đặc tả ngoại lệ nghiêm ngặt có nghĩa là bạn cũng phải cập nhật thông số kỹ thuật đó. Điều này tuyên truyền - cuối cùng bạn có thể phải cập nhật các thông số kỹ thuật ngoại lệ cho hàng chục hoặc hàng trăm chức năng cho một thay đổi đơn giản. Mọi thứ trở nên tồi tệ hơn đối với các lớp cơ sở trừu tượng (tương đương với giao diện C ++). Nếu đặc tả ngoại lệ được thi hành trên các giao diện, việc triển khai các giao diện sẽ không được phép gọi các hàm ném các loại ngoại lệ khác nhau.

Tham khảo: http://www.gotw.ca/publications/mill22.htm

Bắt đầu với C ++ 17, [[nodiscard]]thuộc tính có thể được sử dụng cho các giá trị trả về của hàm (xem: https://stackoverflow.com/questions/39327028/can-ac-feft-be-declared-such-that-the-return-value -cannot-bị bỏ qua ).

Vì vậy, nếu tôi thực hiện thay đổi mã và đưa ra một loại điều kiện thất bại mới (tức là một loại ngoại lệ mới), đó có phải là một thay đổi vi phạm không? Nó có nên bắt buộc người gọi cập nhật mã, hoặc ít nhất là được cảnh báo về sự thay đổi?

Nếu bạn chấp nhận các đối số mà các lập trình viên C ++ tìm kiếm các đảm bảo ngoại lệ thay vì các đặc tả ngoại lệ, thì câu trả lời là nếu loại điều kiện thất bại mới không phá vỡ bất kỳ ngoại lệ nào đảm bảo mã hứa hẹn trước đó, thì đó không phải là một thay đổi vi phạm.


"Khi một người sửa đổi việc thực hiện một chức năng (ví dụ, nó cần thực hiện một cuộc gọi đến một chức năng khác có thể đưa ra một loại ngoại lệ mới), việc thực thi đặc tả ngoại lệ nghiêm ngặt có nghĩa là bạn cũng phải cập nhật thông số kỹ thuật đó" - Tốt , như bạn nên. Điều gì sẽ là sự thay thế? Bỏ qua ngoại lệ vừa được giới thiệu?
AxiomaticNexus

@AxiomaticNexus Điều đó cũng được trả lời bằng bảo đảm ngoại lệ. Trong thực tế, tôi cho rằng đặc điểm kỹ thuật không bao giờ có thể được hoàn thành; đảm bảo là những gì chúng tôi tìm kiếm. Thông thường, chúng tôi so sánh loại ngoại lệ trong nỗ lực tìm hiểu bảo đảm nào đã bị hỏng - để đoán xem bảo đảm nào vẫn còn hiệu lực. Đặc tả ngoại lệ liệt kê một số loại bạn cần kiểm tra, nhưng hãy nhớ rằng trong bất kỳ hệ thống thực tế nào, danh sách có thể có thể hoàn thành. Hầu hết thời gian, nó buộc mọi người phải sử dụng phím tắt "ăn" loại ngoại lệ, bọc nó trong một ngoại lệ khác, khiến cho loại ngoại lệ kiểm tra khó khăn
rwong

@AxiomaticNexus Tôi không tranh cãi hay phản đối việc sử dụng ngoại lệ. Việc sử dụng ngoại lệ điển hình khuyến khích có một lớp ngoại lệ cơ sở và một số lớp ngoại lệ dẫn xuất. Trong khi đó, người ta phải nhớ rằng các loại ngoại lệ khác là có thể, ví dụ như các loại được ném từ C ++ STL hoặc các thư viện khác. Có thể lập luận rằng đặc tả ngoại lệ có thể được thực hiện để hoạt động trong trường hợp này: xác định rằng các ngoại lệ tiêu chuẩn ( std::exception) và ngoại lệ cơ sở của riêng bạn sẽ bị ném. Nhưng khi áp dụng cho toàn bộ dự án, điều đó chỉ có nghĩa là mọi chức năng đơn lẻ sẽ có cùng đặc điểm kỹ thuật này: tiếng ồn.
rwong

Tôi sẽ chỉ ra rằng khi nói đến ngoại lệ, C ++ và Java / C # là các ngôn ngữ khác nhau. Thứ nhất C ++ không an toàn kiểu theo nghĩa là cho phép thực thi mã tùy ý hoặc ghi đè dữ liệu, thứ hai C ++ không in dấu vết ngăn xếp đẹp. Những khác biệt này buộc các lập trình viên C ++ phải đưa ra các lựa chọn khác nhau về lỗi và xử lý ngoại lệ. Điều đó cũng có nghĩa là một số dự án nhất định có thể tuyên bố hợp pháp rằng C ++ không phải là ngôn ngữ phù hợp với họ. (Ví dụ, cá nhân tôi cho rằng việc giải mã hình ảnh TIFF sẽ không được phép thực hiện trong C hoặc C ++.)
rwong

1
@rwong: Một vấn đề lớn với việc xử lý ngoại lệ trong các ngôn ngữ theo mô hình C ++ catchlà dựa trên loại đối tượng ngoại lệ, trong nhiều trường hợp, vấn đề không phải là nguyên nhân trực tiếp của ngoại lệ mà là nó liên quan đến điều gì trạng thái hệ thống. Thật không may, loại ngoại lệ thường không nói gì về việc liệu nó có khiến mã đột ngột thoát khỏi một đoạn mã theo cách khiến một đối tượng ở trạng thái được cập nhật một phần (và do đó không hợp lệ).
supercat

4

Hãy xem xét một nhà phát triển gọi hàm C (). Anh ta không kiểm tra tài liệu để không bắt bất kỳ trường hợp ngoại lệ nào. Cuộc gọi không an toàn

Nó hoàn toàn an toàn. Anh ta không cần phải bắt ngoại lệ ở mọi nơi, anh ta chỉ có thể ném thử / bắt ở một nơi mà anh ta thực sự có thể làm điều gì đó hữu ích về nó. Nó chỉ không an toàn nếu anh ta cho phép nó rò rỉ ra khỏi một luồng, nhưng thường không khó để ngăn điều đó xảy ra.


Điều đó không an toàn vì anh ta không mong đợi một ngoại lệ xuất hiện C()và do đó không bảo vệ được mã sau khi cuộc gọi bị bỏ qua. Nếu mã đó được yêu cầu để đảm bảo rằng một số bất biến vẫn còn đúng, thì bảo đảm đó sẽ bị trục trặc ở ngoại lệ đầu tiên xuất hiện C(). Không có thứ gọi là phần mềm hoàn toàn ngoại lệ, và chắc chắn không phải là trường hợp ngoại lệ không bao giờ được mong đợi.
cmaster

1
@cmaster Anh ấy không mong đợi một ngoại lệ xuất hiệnC() là một sai lầm lớn. Mặc định trong C ++ là bất kỳ hàm nào cũng có thể ném - nó yêu cầu một tường minh noexcept(true)để báo cho trình biên dịch khác. Không có lời hứa này, một lập trình viên phải cho rằng một hàm có thể ném.
Sjoerd

1
@cmaster Đó là lỗi ngớ ngẩn của chính mình và không liên quan gì đến tác giả của C (). An toàn ngoại lệ là một điều, anh ta nên tìm hiểu về nó, và làm theo nó. Nếu anh ta gọi một chức năng mà anh ta không biết là không có khả năng, anh ta nên xử lý tốt những gì xảy ra nếu nó ném. Nếu anh ta cần không có ngoại lệ, anh ta nên tìm một triển khai.
DeadMG

@Sjoerd và DeadMG: Mặc dù tiêu chuẩn cho phép bất kỳ chức năng nào đưa ra một ngoại lệ, điều đó không có nghĩa là các dự án phải cho phép các ngoại lệ trong mã của họ. Nếu bạn cấm ngoại lệ từ mã của mình, giống như nhóm trưởng của OP dường như đang làm, bạn không phải lập trình ngoại lệ an toàn. Và nếu bạn cố gắng thuyết phục một nhóm trưởng để cho phép các ngoại lệ vào một cơ sở mã mà trước đây là ngoại lệ miễn phí, sẽ có rất nhiều C()chức năng bị phá vỡ khi có ngoại lệ. Đây thực sự là một điều rất không khôn ngoan để làm, nó cam chịu dẫn đến một tấn vấn đề.
cmaster

@cmaster Đây là về một dự án mới - xem bình luận đầu tiên về câu trả lời được chấp nhận. Vì vậy, không có chức năng hiện tại sẽ phá vỡ, vì không có chức năng hiện có.
Sjoerd

3

Nếu bạn đang xây dựng một hệ thống quan trọng, hãy cân nhắc làm theo lời khuyên của nhóm trưởng và không sử dụng ngoại lệ. Đây là Quy tắc AV 208 trong Tiêu chuẩn mã hóa máy bay chiến đấu chung C ++ của Lockheed Martin . Mặt khác, hướng dẫn MISRA C ++ có các quy tắc rất cụ thể về thời điểm ngoại lệ có thể và không thể được sử dụng nếu bạn đang xây dựng một hệ thống phần mềm tuân thủ MISRA.

Nếu bạn đang xây dựng các hệ thống quan trọng, rất có thể bạn cũng đang chạy các công cụ phân tích tĩnh. Nhiều công cụ phân tích tĩnh sẽ cảnh báo nếu bạn không kiểm tra giá trị trả về của phương thức, làm cho các trường hợp thiếu xử lý lỗi trở nên rõ ràng. Theo hiểu biết tốt nhất của tôi, công cụ tương tự hỗ trợ phát hiện xử lý ngoại lệ phù hợp không mạnh bằng.

Cuối cùng, tôi sẽ lập luận rằng thiết kế theo hợp đồng và lập trình phòng thủ, kết hợp với phân tích tĩnh sẽ an toàn hơn cho các hệ thống phần mềm quan trọng hơn là ngoại lệ.

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.