주장이나 오류로 예외?


10

저는 전문 C 프로그래머이자 애호가 인 Obj-C 프로그래머 (OS X)입니다. 최근에는 매우 풍부한 구문으로 인해 C ++로 확장하려는 유혹을 받았습니다.

지금까지 코딩은 예외를 많이 다루지 않았습니다. Objective-C에는 이러한 기능이 있지만 Apple의 정책 은 매우 엄격합니다.

중요 사항 범위를 벗어난 콜렉션 액세스, 변경 불가능한 오브젝트의 변경 시도, 유효하지 않은 메시지 보내기 및 창 서버와의 연결 유실과 같은 예기치 않은 런타임 오류 프로그래밍 또는 예외에 대한 예외 사용을 예약해야합니다.

C ++은 예외를 더 자주 사용하는 것을 선호합니다. 예를 들어 RAII 의 wikipedia 예제 는 파일을 열 수 없으면 예외를 발생시킵니다. Objective-C는 return nilout 매개 변수에서 보낸 오류가 있습니다. 특히 std :: ofstream은 어느 쪽이든 설정할 수 있습니다.

프로그래머에서 나는 오류 코드 대신 예외 를 사용한다고 선언 하거나 예외전혀 사용하지 않는 몇 가지 대답을 발견했습니다 . 전자가 더 널리 보인다.

C ++에 대한 객관적인 연구를하는 사람을 찾지 못했습니다. 포인터가 드물기 때문에 예외를 피하려면 내부 오류 플래그를 사용해야 할 것 같습니다. 처리하기가 너무 귀찮습니까, 아니면 예외보다 더 잘 작동합니까? 두 경우를 비교하는 것이 가장 좋습니다.

편집 : 완전히 관련이 없지만 무엇인지 명확히해야합니다 nil. 기술적으로는와 동일 NULL하지만 메시지를 (으)로 보내도됩니다 nil. 그래서 당신은 같은 것을 할 수 있습니다

NSError *err = nil;
id obj = [NSFileHandle fileHandleForReadingFromURL:myurl error:&err];

[obj retain];

첫 번째 호출이 반환 된 경우에도 마찬가지 nil입니다. 그리고 *objObj-C에서는 절대로하지 않기 때문에 NULL 포인터 역 참조의 위험이 없습니다.


Imho, Objective C 코드를 보여 주면 오류가 발생하는 방식이 더 좋습니다. 사람들이 당신이 요구하는 것과 다른 것에 대해 이야기하고있는 것 같습니다.
Gangnus

어떤 식 으로든 예외 사용에 대한 정당성을 찾고 있다고 생각합니다. 구현 방법에 대한 아이디어가 있기 때문에 비용이 얼마나 드는지 잘 알고 있습니다. 그러나 나는 그들의 사용에 대해 충분한 논쟁을 얻을 수 있다면 그렇게 할 것이라고 생각합니다.
당 Johansson

C ++의 경우 C ++ 을 사용하지 않기 위해서는 정당성이 필요 합니다. 여기에 반응에 따르면.
Gangnus

2
아마도, 그러나 지금까지 왜 그들이 더 나은지 설명하는 사람은 없었습니다 (오류 코드와 비교하여). 예외가 아닌 것들에 대해 예외를 사용하는 개념을 좋아하지 않지만 사실에 근거한 것보다 더 본능적입니다.
당 요한슨

"나는 예외적이지 않은 것들에 대해 예외를 사용하는 것을 좋아하지 않는다"-동의했다.
Gangnus

답변:


1

C ++은 예외를 더 자주 사용하는 것을 선호합니다.

C ++ 표준 라이브러리는 일반적으로 가장 일반적인 경우 디자인 형태 ( operator[]예 :) 또는 랜덤 액세스 시퀀스의 범위를 벗어난 액세스와 같은 프로그래머 오류를 발생시키지 않기 때문에 실제로 어떤 측면에서 Objective-C보다 적을 것을 제안합니다. 잘못된 반복자를 역 참조하려고합니다. 언어는 범위를 벗어난 배열에 액세스하거나 null 포인터 또는 이와 같은 것을 참조하지 않습니다.

예외 처리 방정식에서 프로그래머의 실수를 크게 받아들이면 실제로 다른 언어가 자주 응답하는 매우 큰 범주의 오류를 제거합니다 throwing. C ++은 assert(릴리스 / 프로덕션 빌드에서 컴파일되지 않고 디버그 빌드 만) 경향이 있거나 그러한 경우 글리치 아웃 (종종 충돌)하는 경향이 있습니다. 언어가 그러한 런타임 검사 비용을 부과하지 않기 때문에 부분적으로 프로그래머가 구체적으로 이러한 검사를 수행하는 코드를 작성하여 비용을 지불하기를 원하지 않는 한 이러한 프로그래머 실수를 감지하는 데 필요한 것입니다.

Sutter는 C ++ 코딩 표준과 같은 경우 예외를 피하도록 권장합니다.

예외를 사용하여 프로그래밍 오류를보고 할 때의 주요 단점은 디버거가 위반이 감지 된 정확한 라인에서 라인 상태를 그대로 유지하면서 디버거를 시작하려는 경우 실제로 스택 해제가 발생하지 않게한다는 것입니다. 요약 : 발생할 수있는 오류가 있습니다 (항목 69-75 참조). 해서는 안되는 모든 것에는 프로그래머의 잘못이 assert있습니다.

그 규칙은 반드시 돌로 설정되지는 않습니다. 좀 더 미션 크리티컬 한 경우에는 프로그래머 실수가 발생하는 위치와 throw유효하지 않은 무언가를 연기하거나 한계를 벗어난 액세스와 같은 프로그래머 실수가있는 경우를 일관되게 기록하는 래퍼 및 코딩 표준을 사용하는 것이 바람직 할 수 있습니다. 이 경우 소프트웨어에 기회가있는 경우 복구에 실패하면 비용이 너무 많이들 수 있습니다. 그러나 전반적으로 더 일반적인 언어 사용은 프로그래머 실수에 직면하지 않는 편이 좋습니다.

외부 예외

예를 들어 표준위원회에 따르면 C ++에서 가장 많이 권장되는 예외는 프로그램 외부의 일부 외부 소스에서 예기치 않은 결과와 같이 "외부 예외"에 대한 것입니다. 예를 들어 메모리를 할당하지 못했습니다. 다른 소프트웨어가 소프트웨어를 실행하는 데 필요한 중요한 파일을 열지 못했습니다. 다른 서버가 필요한 서버에 연결하지 못했습니다. 다른 하나는 사용자가 중단 버튼을 방해하여 일반적인 경우 실행 경로가이 외부 중단없이 성공할 것으로 예상되는 작업을 취소하는 것입니다. 이 모든 것은 즉각적인 소프트웨어와 소프트웨어를 작성한 프로그래머의 통제를 벗어납니다. 외부 소스에서 예기치 않은 결과로 인해 작업 (실제로 필자의 책에서 불가분의 거래라고 생각해야 함)이 성공하지 못합니다.

업무

try트랜잭션은 전체적으로 성공하거나 전체적으로 실패해야하기 때문에 블록을 "트랜잭션"으로 보는 것이 좋습니다 . 우리가 무언가를 시도하고 반쯤 실패하면 일반적으로 트랜잭션이 전혀 실행되지 않은 것처럼 시스템을 유효한 상태로 되돌리려면 프로그램 상태에 대한 부작용 / 돌연변이를 롤백해야합니다. 반쯤 쿼리를 처리하지 못하는 RDBMS가 데이터베이스의 무결성을 손상시키지 않아야합니다. 해당 트랜잭션에서 프로그램 상태를 직접 변경하는 경우 오류 발생시이를 "변경 취소"해야합니다 (여기서 범위 가드는 RAII에 유용 할 수 있습니다).

훨씬 간단한 대안은 원래 프로그램 상태를 변경하지 않습니다 . 사본을 변경 한 다음 성공하면 사본을 원본으로 교체하십시오 (스왑이 발생하지 않도록 보장). 실패하면 사본을 폐기하십시오. 일반적으로 오류 처리에 예외를 사용하지 않는 경우에도 적용됩니다. "트랜잭션"사고 방식은 오류가 발생하기 전에 프로그램 상태 돌연변이가 발생한 경우 적절한 복구의 열쇠입니다. 그것은 전체적으로 성공하거나 전체적으로 실패합니다. 그것의 돌연변이를 만드는 데 반쯤 성공하지는 않습니다.

프로그래머가 오류 또는 예외 처리를 올바르게 수행하는 방법을 묻는 것을 볼 때 가장 자주 논의되는 주제 중 하나입니다. 그 운영. 순도 및 불변성은 스레드 안전성에 도움이되는만큼 예외 안전성을 달성하는 데 도움이 될 수 있습니다. 발생하지 않는 돌연변이 / 외부 부작용은 롤백 할 필요가 없습니다.

공연

예외를 사용할지 여부에 대한 또 다른 지침 요소는 성능이며, 강박 관념, 페니 핀칭, 반 생산적 방법을 의미하지는 않습니다. 많은 C ++ 컴파일러가 "제로 비용 예외 처리"를 구현합니다.

오류없는 실행을 위해 런타임 오버 헤드가 0이므로 C 리턴 값 오류 처리보다 훨씬 뛰어납니다. 트레이드 오프로서 예외의 전파에는 많은 오버 헤드가 있습니다.

내가 읽은 것에 따르면, 일반적인 경로 실행 경로에는 오버 헤드 (일반적으로 C 스타일 오류 코드 처리 및 전파와 함께 발생하는 오버 헤드)가 필요하지 않습니다. 이는 throwing그 어느 때보 다 비싸다는 의미 입니다.

"고가"는 정량화하기가 다소 어렵지만, 초보자에게는 아마도 꽉 찬 루프에서 백만 번 던지기를 원하지 않을 것입니다. 이러한 종류의 디자인은 예외가 항상 좌우로 발생하지 않는다고 가정합니다.

비 오류

그리고 그 성능 포인트는 오류가 아닌 것으로 나타났습니다. 우리가 모든 종류의 다른 언어를 보면 놀랍게도 모호합니다. 그러나 위에서 언급 한 제로 비용 EH 설계를 감안할 때 throw세트에서 찾을 수없는 키에 대한 응답으로 거의 원하지 않습니다. 논란의 여지가없는 오류 일뿐 아니라 (키를 검색하는 사용자가 세트를 빌드하고 항상 존재하지 않는 키를 검색 할 것으로 예상 할 수 있음), 그 맥락에서 막대한 비용이 소요될 수 있습니다.

예를 들어, 집합 교차 함수는 두 집합을 반복하고 공통 키를 검색하려고 할 수 있습니다. 키를 찾지 못하면 threw루프를 반복하고 절반 이상의 반복에서 예외가 발생할 수 있습니다.

Set<int> set_intersection(const Set<int>& a, const Set<int>& b)
{
     Set<int> intersection;
     for (int key: a)
     {
          try
          {
              b.find(key);
              intersection.insert(other_key);
          }
          catch (const KeyNotFoundException&)
          {
              // Do nothing.
          }
     }
     return intersection;
}

위의 예제는 절대적으로 말도 안되고 과장되었지만, 프로덕션 코드에서 일부 사람들은 C ++에서 예외를 사용하여 다른 언어를 사용하는 것을 보았습니다. 이것은 예외를 적절하게 사용하지 않는다는 합리적으로 실용적인 진술이라고 생각합니다 C ++에서. 위의 또 다른 힌트는 catch블록이 절대로 할 일이 없으며 그러한 예외를 강제로 무시하기 위해 작성되었다는 것입니다. 보통 C ++에서 예외가 매우 적절하게 사용되지 않는다는 힌트입니다 (보증자는 아니지만).

이러한 유형의 경우 실패를 나타내는 일부 유형의 반환 값 ( false잘못된 반복자 또는 nullptr컨텍스트에서 의미가있는 것)은 일반적으로 훨씬 더 적합하며, 오류가 아닌 유형이기 때문에 종종 더 실용적이고 생산적입니다. case는 일반적으로 비슷한 catch사이트 에 도달하기 위해 스택 해제 프로세스를 요구하지 않습니다 .

질문

예외를 피하려면 내부 오류 플래그를 사용해야합니다. 처리하기가 너무 귀찮습니까, 아니면 예외보다 더 잘 작동합니까? 두 경우를 비교하는 것이 가장 좋습니다.

C ++에서 예외를 피하는 것은 임베디드 시스템이나 사용을 금지하는 특정 유형의 경우 (모든 경우를 피하기 위해 길을 벗어나야하는 경우가 아니라면)에 비생산적 인 것처럼 보입니다. 그렇지 않으면 throw엄격하게 사용하는 것과 같은 라이브러리 및 언어 기능 nothrow new.

어떤 이유로 든 예외를 피해야한다면 (예 : C API를 내보내는 모듈의 C API 경계에서 작업) 많은 사람들이 동의하지 않을 수 있지만 실제로 OpenGL과 같은 전역 오류 처리기 / 상태를 사용하는 것이 좋습니다 glGetError(). 스레드 로컬 스토리지를 사용하여 스레드 당 고유 한 오류 상태를 가질 수 있습니다.

그 이유는 프로덕션 환경에서 팀이 오류 코드가 반환 될 때 불행히도 가능한 모든 오류를 철저히 확인하는 데 익숙하지 않다는 것입니다. 철저한 경우 일부 C API는 거의 모든 단일 C API 호출에서 오류가 발생할 수 있으며 철저한 검사에는 다음과 같은 것이 필요합니다.

if ((err = ApiCall(...)) != success)
{
     // Handle error
}

... 이러한 검사가 필요한 API를 호출하는 거의 모든 단일 코드 행. 그러나 나는 철저한 팀과 함께 일할 운명이 없었습니다. 그들은 종종 이러한 오류를 절반, 때로는 대부분의 경우 무시합니다. 그것은 예외에 대한 가장 큰 매력입니다. 이 API를 래핑 throw하고 오류가 발생 했을 때 균일하게 만들면 예외를 무시할 수 없으며 내 견해와 경험상 예외의 우수성이 있습니다.

그러나 예외를 사용할 수없는 경우 전역 스레드 당 오류 상태는 적어도 오류 코드를 나에게 반환하는 것과 비교할 때 적어도 이전 오류를 잡을 수있는 이점이 있습니다. 엉뚱한 코드베이스에서 잃어버린 대신 발생하여 어떤 일이 있었는지 완전히 잊어 버렸습니다. 오류가 발생하기 전 또는 이전 함수 호출에서 몇 줄이 발생했을 수 있지만 소프트웨어가 아직 충돌하지 않은 경우 뒤로 이동하여 오류가 발생한 위치와 이유를 파악할 수 있습니다.

포인터가 드물기 때문에 예외를 피하려면 내부 오류 플래그를 사용해야 할 것 같습니다.

포인터가 드물다고 말할 필요는 없습니다. C ++ 11 이후에는 컨테이너의 기본 데이터 포인터와 새로운 nullptr키워드 를 얻는 방법도 있습니다 . 예외가있을 때 RAII를 준수하는 것이 얼마나 중요한지 대신에 비슷한 것을 사용할 수 있다면 원시 포인터를 사용하여 메모리소유 / 관리 하는 것이 현명하지 않은 것으로 간주됩니다 unique_ptr. 그러나 메모리를 소유하지 않거나 관리하지 않는 원시 포인터는 (Sutter 및 Stroustrup과 같은 사람들로부터조차) 그렇게 나쁘게 간주되지 않으며 때로는 물건을 가리키는 방법 (물건을 가리키는 인덱스와 함께)으로 매우 실용적인 것으로 간주되지는 않습니다.

그것들은 무효화 된 후에 그것들을 역 참조하려고 시도하는지 감지하지 않는 표준 컨테이너 반복자 (적어도 릴리스에서는 확인 된 반복자가 없음)보다 안전하지 않을 것입니다. C ++은 여전히 ​​부끄럽게도 위험한 언어입니다. 특별히 사용하면 모든 것을 감싸고 소유하지 않은 원시 포인터조차 숨기고 싶지 않다면 말하고 싶습니다. 리소스는 RAII (일반적으로 런타임 비용 없음)를 준수한다는 점을 제외하고는 매우 중요하지만, 개발자가 명시 적으로 원하지 않는 비용을 피하기 위해 반드시 가장 안전한 언어를 사용하려는 것은 아닙니다. 다른 것을 교환하십시오. 권장되는 사용법은 매달려있는 포인터 및 무효화 된 반복자와 같은 것들로부터 당신을 보호하려고하지 않기 때문에 (그렇지 않으면 우리는 사용하도록 권장됩니다)shared_ptrStroustrup이 격렬하게 반대하는 모든 곳에서). 리소스가 제대로 해제 / 해제 / 파기 / 잠금 해제 / 정리되지 않을 때 보호하려고합니다 throws.


14

C ++의 고유 한 역사와 유연성으로 인해 원하는 기능에 대해 거의 모든 의견을 선포하는 사람을 찾을 수 있습니다. 그러나 일반적으로 수행하는 작업이 C와 비슷할수록 더 나쁜 아이디어입니다.

예외와 관련하여 C ++이 훨씬 느슨해 진 이유 중 하나는 return nil느낌이들 때마다 정확히 할 수 없기 때문입니다. nil대부분의 경우 및 유형과 같은 것은 없습니다 .

그러나 간단한 사실이 있습니다. 예외는 자동으로 작업을 수행합니다. 예외가 발생하면 RAII가 대신하고 컴파일러가 모든 것을 처리합니다. 당신이 오류 코드를 사용하는 경우, 당신은 그들을 확인하는 것을 기억해야합니다. 이는 본질적으로 예외를 오류 코드보다 훨씬 안전하게 만들어줍니다. 또한 더 표현력이 뛰어납니다. 예외를 던지면 오류가 무엇인지 알려주는 문자열을 얻을 수 있으며 "Z 대신 Y 값을 가진 잘못된 매개 변수 X"와 같은 특정 정보를 포함 할 수도 있습니다. 0xDEADBEEF의 오류 코드를 받으면 정확히 무엇이 잘못 되었습니까? 나는 확실히 문서가 최신의 완전하고 희망, 그리고 당신이 "잘못된 매개 변수"를 얻을 경우에도, 그것은 당신을 말하려고 결코 어떤매개 변수, 값, 값을 가져야합니다. 참고로 잡으면 다형성이 될 수 있습니다. 마지막으로, 생성자와 같이 오류 코드가 절대 불가능한 곳에서 예외가 발생할 수 있습니다. 그리고 일반적인 알고리즘은 어떻습니까? std::for_each오류 코드 는 어떻게 처리합니까? 전문가 팁 : 그렇지 않습니다.

예외는 모든면에서 오류 코드보다 훨씬 우수합니다. 실제 질문은 예외 대 주장에 있습니다.

여기 있습니다. 프로그램 작동을위한 사전 조건, 비정상 상태, 사전 점검 및 버그 등을 미리 알 수있는 사람은 없습니다. 이는 일반적으로 프로그램 논리를 모르면 주어진 실패가 어설 션인지 예외인지 미리 결정할 수 없음을 의미합니다. 또한 하위 작업 중 하나가 실패 할 때 계속할 수있는 작업 은 규칙 이 아니라 예외 입니다.

제 생각에는 예외가 있습니다. 반드시 즉각적인 것은 아니지만 결국은 아닙니다. 예외는 프로그램이 특정 시점에서 복구 할 수있을 것으로 예상되는 문제입니다. 그러나 해당 작업은 예외를 보장하는 문제에서 결코 복구 할 수 없습니다.

어설 션 오류는 항상 치명적이고 복구 할 수없는 오류입니다. 메모리 손상, 그런 종류의 것.

따라서 파일을 열 수 없으면 어설 션 또는 예외입니까? 글쎄, 일반 라이브러리에는 오류 처리 할 수 있는 많은 시나리오가 있습니다 ( 예 : 구성 파일로드) 대신 미리 작성된 기본값을 사용할 수 있으므로 예외라고 말하고 싶습니다.

각주로서, 나는 "Null Object Pattern"이라는 것이 언급되고 싶습니다. 이 패턴은 끔찍하다 . 10 년 후에는 다음 싱글턴이 될 것입니다. 적절한 null 객체를 생성 할 수있는 경우는 miniscule 입니다.


대안은 반드시 간단한 int는 아닙니다. Obj-C에서 익숙한 NSError와 비슷한 것을 사용할 가능성이 더 큽니다.
당 Johansson

그는 C가 아니라 목표 C와 비교하고있다. 그것은 차이이다. 그리고 그의 오류 코드는 선을 설명하고 있습니다. 당신이 말한 것은 정확하지만 어떻게 든이 질문에 대답하지는 않습니다. 악의는 없습니다.
Gangnus

Objective-C를 사용하는 사람은 물론 당신이 절대적으로 완전히 틀렸다고 말할 것입니다.
gnasher729

5

예외로 인해 모든 코드가 다음과 같이 표시되는 것을 피할 수 있습니다.

bool success = function1(&result1, &err);
if (!success) {
    error_handler(err);
    return;
}

success = function2(&result2, &err);
if (!success) {
    error_handler(err);
    return;
}

대신 하나의 예외 처리기가 위로 main또는 편리하게 배치 되어 다음과 같은 것을 얻습니다 .

result1 = function1();
result2 = function2();

어떤 사람들은 예외없이 접근 성능 혜택을 주장하지만, 내 의견으로는 가독성 문제는 모든 실행 시간을 포함 특히, 약간의 성능 향상을 능가 if (!success)당신이 사방에 뿌려해야 상용구, 또는 디버그 세그먼테이션 폴트 (segfault)에 열심히의 위험을 '당신이 돈 경우 이를 포함하고 예외 발생 가능성을 고려하는 것은 상대적으로 드물다.

Apple이 예외 사용을 권장하지 않는 이유를 모르겠습니다. 처리되지 않은 예외가 전파되는 것을 피하려고 시도하는 경우 실제로 널 포인터를 사용하여 예외를 나타내는 사람들이 실제로 수행하는 것이므로 프로그래머 실수로 인해 예외를 찾을 수없는 훨씬 유용한 파일 대신 널 포인터 예외가 발생합니다.


1
예외가없는 코드가 실제로 그렇게 보이는 경우 더 의미가 있지만 일반적으로 그렇지 않습니다. 이 패턴은 error_handler가 절대 반환하지 않으면 나타나지만, 그렇지 않은 경우는 거의 없습니다.
Per Johansson

1

당신이 참조하는 게시물 (예외 대 오류 코드)에서 미묘하게 다른 토론이 진행되고 있다고 생각합니다. 문제는 ERR001_FILE_NOT_WRITEABLE (또는 운이 좋지 않은 경우 약자)과 같은 이름으로 완성 된 #define 오류 코드의 전체 목록이 있는지 여부입니다. 그리고 그 스레드의 주요 요점은 당신이 polymporphic 언어로 프로그래밍하는 경우 객체 인스턴스를 사용하여 그러한 절차 적 구성이 필요하지 않다는 것입니다. 예외는 단순히 유형에 따라 발생하는 오류를 표시 할 수 있으며 인쇄 할 메시지 (및 기타 사항)와 같은 정보를 캡슐화 할 수 있습니다. 따라서 객체 지향 언어로 절차 적으로 프로그래밍해야하는지 여부에 대한 대화로 사용하겠습니다.

그러나 코드에서 발생하는 상황을 처리하기 위해 예외에 언제 얼마나 의존해야하는지에 대한 대화는 다릅니다. 예외가 발생하고 포착되면 기존 호출 스택과 완전히 다른 제어 흐름 패러다임을 도입하게됩니다. 예외 던지기는 기본적으로 호출 스택에서 벗어나고 불확실한 위치로 보냅니다 (클라이언트 코드가 예외를 처리하기로 결정한 곳). 이로 인해 예외 논리 를 추론하기가 매우 어렵습니다 .

따라서, jheriko에 의해 표현 된 것과 같은 감정은 최소화되어야한다는 정서가 있습니다. 즉, 디스크에 존재하거나 존재하지 않는 파일을 읽고 있다고 가정 해 봅시다. Jheriko와 Apple 및 자신이 생각하는대로 (나 자신을 포함하여) 생각하는 사람들은 예외를 던지는 것이 적절하지 않다고 주장 할 것입니다. 해당 파일이없는 것은 예외 가 아닙니다 . 예외는 정상적인 제어 흐름을 대체해서는 안됩니다. 부울과 같이 ReadFile () 메서드를 반환하는 것과 마찬가지로 반환 값 false에서 클라이언트 코드가 파일을 찾을 수 없도록하는 것도 쉽습니다. 그런 다음 클라이언트 코드는 사용자 파일을 찾을 수 없거나 해당 사례 또는 원하는 작업을 조용히 처리 할 수 ​​있습니다.

예외를 던지면 고객에게 부담이됩니다. 때로는 일반 호출 스택에서 그들을 빼내고 응용 프로그램이 충돌하지 않도록 추가 코드를 작성하도록하는 코드를 제공합니다. 이러한 강력하고 끔찍한 부담은 런타임에 또는 "초기 실패"철학의 이익을 위해 절대적으로 필요한 경우에만 부담해야합니다. 따라서 전자의 경우 응용 프로그램의 목적이 일부 네트워크 작동을 모니터링하고 누군가가 네트워크 케이블을 분리하는 경우 예외를 throw 할 수 있습니다 (치명적인 오류 신호). 후자의 경우, 메소드가 널이 아닌 매개 변수를 예상하고 널을 전달하는 경우 (부적절하게 사용되고 있음을 알리는 경우) 예외가 발생할 수 있습니다.

객체 지향 세계에서 예외 대신해야 할 일에 대해서는 절차 오류 코드 구성 이외의 옵션이 있습니다. 즉시 떠오르는 것은 OperationResult 또는 이와 같은 객체를 만들 수 있다는 것입니다. 메소드는 OperationResult를 리턴 할 수 있으며 해당 오브젝트는 조작의 성공 여부에 대한 정보 및 기타 원하는 정보 (예 : 상태 메시지,보다 미묘하게는 오류 복구 전략을 캡슐화 할 수 있음)에 대한 정보를 가질 수 있습니다. ). 예외를 throw하는 대신 이것을 반환하면 다형성이 가능하고 제어 흐름이 유지되며 디버깅이 훨씬 간단 해집니다.


나는 당신에게 동의하지만 그것이 내가 질문을하지 않은 가장 큰 이유입니다.
Per Johansson

0

Clean Code 에는 애플의 관점을 빼고이 주제에 대해 이야기 하는 멋진 장 들이 있습니다.

기본 아이디어는 함수에서 nil을 반환하지 않는 것입니다.

  • 많은 중복 코드를 추가합니다
  • 코드를 엉망으로 만듭니다-즉 : 읽기가 더 어려워집니다
  • 특정 프로그래밍 "종교"에 따라 종종 포인터가없는 오류가 발생하거나 액세스 위반이 발생할 수 있습니다.

다른 동반 아이디어는 예외를 사용하여 코드의 혼란을 더욱 줄이는 데 도움이되고 결국에는 관리 및 유지 관리 (특히 여러 모듈 및 플랫폼에서)를 추적하기 어려운 일련의 오류 코드를 작성하지 않고 예외를 사용한다는 것입니다. 고객이 해독하는 데 어려움을 겪는 대신 문제의 정확한 특성을 식별하고 디버깅을 간단하게하며 오류 처리 코드를 기본 try..catch문장 처럼 간단하게 줄일 수있는 의미있는 메시지를 작성 합니다.

COM 개발 시절에 모든 실패에서 예외가 발생하는 프로젝트가 있었고 각 예외는 Windows 표준 COM 예외 확장에 따라 고유 한 오류 코드 ID를 사용해야했습니다. 이전에는 오류 코드가 사용되었던 이전 프로젝트에서 보류되었지만 회사는 모든 객체 지향을 수행하고 작업을 너무 많이 수행하는 방식을 변경하지 않고 COM 대역을 뛰어 넘기를 원했습니다. 오류 코드 번호가 부족 해지는 데 4 개월이 걸렸고 예외를 사용하기 위해 많은 코드를 리팩터링해야했습니다. 미리 노력을 아끼고 예외를 신중하게 사용하는 것이 좋습니다.


감사하지만 NULL 반환을 고려하지 않습니다. 어쨌든 생성자 앞에서는 불가능한 것 같습니다. 내가 언급했듯이 객체에 오류 플래그를 사용해야 할 것입니다.
당 Johansson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.