예외 처리가 나쁜 이유는 무엇입니까?


90

Google의 Go 언어는 디자인 선택으로 예외가 없으며 Linux 명성의 Linus는 예외를 쓰레기라고 불렀습니다. 왜?


2
ZeroMQ의 제작자는 C ++로 작성하는 것이 실수라고 생각하는 방식에 대해 씁니다 (대부분 오류 처리 때문). 250bpm.com/blog:4
serbaut

이동은 예외가되지 않을 수 있습니다,하지만 당신은 (연기 문이 여전히 실행하는 동안)에서 "복구"할 수있는 "패닉"가 그 제공 로컬이 아닌 제어 흐름 ...
Kerrek SB

여기에 좋은 기사입니다 lighterra.com/papers/exceptionsharmful (예외가 유해 고려 처리)
masterxilo

Afaics, 예외는 상당한 상용구를 사용하여 Go에서 시뮬레이션 할 수 있지만이 점은 상용구를 수동으로 작성하는 것보다 구문 설탕에서 트랜스 파일하는 데 더 의미가있을 수 있습니다.
Shelby Moore III

답변:


82

예외는 throw되는 예외가 불변성을 깨고 객체를 일관성없는 상태로 남겨 두는 코드를 작성하는 것을 정말 쉽게 만듭니다. 그들은 본질적으로 당신이 만드는 대부분의 진술이 잠재적으로 던질 수 있다는 것을 기억하고 올바르게 처리하도록 강요합니다. 그렇게하는 것은 까다 롭고 직관적이지 않을 수 있습니다.

다음과 같은 것을 간단한 예로 고려하십시오.

class Frobber
{
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:
    void Frob()
    {
        m_NumberOfFrobs++;

        m_FrobManager.HandleFrob(new FrobObject());
    }
};

가정 FrobManager것이다 오른쪽이 외모 확인을? 아니면 아닐 수도 있습니다 ... 그렇다면 또는 예외가 발생하는 경우를 상상해보십시오 . 이 예에서 증분은 롤백되지 않습니다. 따라서이 인스턴스를 사용하는 사람 은 개체가 손상되었을 수 있습니다.deleteFrobObjectFrobManager::HandleFrob()operator newm_NumberOfFrobsFrobber

이 예제는 어리석은 것처럼 보일 수 있지만 (좋아요, 하나를 구성하기 위해 약간의 노력을 기울여야했습니다. :-)),하지만 핵심은 프로그래머가 예외를 계속 생각하지 않고 모든 상태 순열이 롤링되는지 확인하는 것입니다. 던질 때마다 이런 식으로 문제가 생깁니다.

예를 들어 뮤텍스를 생각하는 것처럼 생각할 수 있습니다. 중요한 섹션 내에서 데이터 구조가 손상되지 않았는지, 다른 스레드가 중간 값을 볼 수 없는지 확인하기 위해 여러 명령문에 의존합니다. 이러한 진술 중 하나가 무작위로 실행되지 않으면 고통의 세계에 빠집니다. 이제 잠금과 동시성을 제거하고 각 방법에 대해 그렇게 생각하십시오. 원한다면 각 방법을 객체 상태에 대한 순열 트랜잭션으로 생각하십시오. 메서드 호출을 시작할 때 개체는 깨끗한 상태 여야하고 마지막에는 깨끗한 상태 여야합니다. 그 사이에 변수 foo는 다음과 일치하지 않을 수 있습니다.bar, 그러나 귀하의 코드는 결국 그것을 수정할 것입니다. 예외의 의미는 귀하의 진술 중 하나가 언제든지 귀하를 방해 할 수 있다는 것입니다. 각 개별 메서드에서 문제가 발생하면 문제가 발생하면 롤백하거나 작업을 정렬하여 throw가 개체 상태에 영향을주지 않도록해야합니다. 잘못 이해하면 (그리고 이런 종류의 실수를하기 쉽습니다) 호출자는 결국 중간 값을 보게됩니다.

C ++ 프로그래머가이 문제에 대한 궁극적 인 해결책으로 언급하기를 좋아하는 RAII와 같은 메서드는이를 방지하기 위해 먼 길을갑니다. 그러나 그것들은 은총 알이 아닙니다. 던질 때 리소스를 해제 할 수는 있지만 객체 상태의 손상과 호출자가 중간 값을 보는 것에 대해 생각할 필요가 없습니다. 따라서 많은 사람들에게 코딩 스타일의 명목상 예외없다고 말하는 것이 더 쉽습니다 . 작성하는 코드의 종류를 제한하면 이러한 버그를 도입하기가 더 어렵습니다. 그렇지 않으면 실수하기가 매우 쉽습니다.

C ++의 예외 안전 코딩에 대해 전체 책이 작성되었습니다. 많은 전문가들이 잘못 알고 있습니다. 정말 그렇게 복잡하고 뉘앙스가 너무 많다면 해당 기능을 무시해야한다는 좋은 신호일 수 있습니다. :-)


9
흥미로운 대답이지만 내 프로그래밍 경험에는 아무것도 반영하지 않습니다. 그래서 나는 문화에 따라 다르거 나 (예를 들어 Python보다 Java 또는 C ++에서 더 많은 문제가 될 수 있음) 도메인에 따라 다릅니다.
ddaa

42
try-catch-finally 패턴을 사용하여 관리되는 언어로 작성된 예외는 올바르게 작성된 경우 잘못된 상태를 유지해서는 안됩니다. finally 블록은 실행이 보장되기 때문에 객체를 그곳에서 할당 해제 할 수 있습니다. 나머지는 범위를 벗어나는 변수와 가비지 수집에 의해 처리되어야합니다.
Robert Harvey

7
@ddaa이 문제는 파이썬에서 확실히 가능합니다. 그 결과 일반적으로 버그를 재현하기가 어렵습니다. 아마도 당신은 특히 세심하거나 운이 좋았을 것입니다. 그러나 C ++의 문제에 더 가깝다는 것이 맞습니다. 불량 EH로 인한 가장 일반적인 버그는 메모리 누수입니다. 저는 누출이 가장 심각한 문제가 아니라는 점을 강조하려고했습니다. @Robert GC는 메모리 누수를 완화하지만 관리 코드가 프로그래머 오류에서 벗어날 수 있을지 확실하지 않습니다. 특히 누군가가 예외 안전에주의를 기울이지 않는데, 그들이 그들의 언어에 문제가 있다고 생각하지 않는다면 그것은 좋은 징조가 아닙니다.
asveikau

4
@lzprgmr 확실히 있습니다 : 예외를 사용하면 diff를 처리 할 수 ​​있습니다. diff에서 오류 유형. 코드의 장소. 연결 오류를 처리하려면 재 연결이 필요할 수 있지만 깊이 중첩 된 함수 중간에는 필요하지 않습니다. 당신은 연결 관리자 또는 다른 것에 버블 링하고 싶습니다. 그런 다음 반환 값을 처리하면 각 단일 호출에서 오류를 확인하고 수동으로 버블 링해야합니다 (예 : 연결 재설정 오류의 경우). 또한 반환 값은 중첩 된 호출에서 누적됩니다. func3은 -1을 반환하고, func2는 func3을 호출하고, 그의 오류에 -2를, func3에 대해 -1을 반환합니다.
abourget 2013 년

4
나는 투표를 거부했지만 이것이 예외가 무시되는 이유이기 때문에 반대했습니다. 그러나 제 생각에는 거의 모든 방법이나 코드가 실패 할 수 있습니다. 반환 값을 도입하여 각 오류 조건을 처리 할 수 ​​없습니다. 오류에 대한 정보를 잃게됩니다. 각각의 모든 문을 확인하고 정리를 수행하여 모든 것을 멋지게 동기화 할 수 있다고 생각하면 코드가 매우 복잡해집니다. 여러 문에서 오류를 포착하고 GC되지 않은 하나 또는 두 개의 리소스를 정리하는 것이 훨씬 깔끔합니다.
Maarten Bodewes

50

Go에 예외가없는 이유는 Go 언어 디자인 FAQ에 설명되어 있습니다.

예외도 비슷한 이야기입니다. 예외에 대한 많은 디자인이 제안되었지만 각각은 언어와 런타임에 상당한 복잡성을 추가합니다. 본질적으로 예외는 함수와 고 루틴에 걸쳐 있습니다. 그들은 광범위한 의미를 가지고 있습니다. 그들이 도서관에 미칠 영향에 대한 우려도 있습니다. 정의상 예외적이지만이를 지원하는 다른 언어에 대한 경험은 라이브러리 및 인터페이스 사양에 큰 영향을 미친다는 것을 보여줍니다. 일반적인 오류를 모든 프로그래머가 보상해야하는 특수 제어 흐름으로 바꾸지 않고 진정으로 예외적 일 수있는 디자인을 찾는 것이 좋을 것입니다.

제네릭과 마찬가지로 예외도 여전히 미해결 문제입니다.

즉, Go에서 만족 스럽다고 생각하는 방식으로 예외를 지원하는 방법을 아직 파악하지 못했습니다. 그들은 예외가 그 자체 로 나쁘다고 말하는 것이 아닙니다 .

업데이트-2012 년 5 월

Go 디자이너는 이제 울타리에서 내려 왔습니다. 그들의 FAQ는 다음과 같이 말합니다.

try-catch-finally 관용구 에서처럼 예외를 제어 구조에 결합하면 코드가 복잡해집니다. 또한 프로그래머가 파일을 열지 못하는 것과 같은 너무 많은 일반적인 오류를 예외적으로 분류하도록 장려하는 경향이 있습니다.

Go는 다른 접근 방식을 취합니다. 일반 오류 처리를 위해 Go의 다중 값 반환을 사용하면 반환 값을 오버로드하지 않고도 오류를 쉽게보고 할 수 있습니다. Go의 다른 기능과 결합 된 표준 오류 유형은 오류 처리를 즐겁게하지만 다른 언어의 오류 처리와는 상당히 다릅니다.

Go에는 또한 진정으로 예외적 인 조건에서 신호를 보내고 복구 할 수있는 몇 가지 내장 기능이 있습니다. 복구 메커니즘은 오류 후 해체되는 함수 상태의 일부로 만 실행됩니다. 이는 재앙을 처리하기에 충분하지만 추가 제어 구조가 필요하지 않으며 잘 사용하면 깨끗한 오류 처리 코드를 생성 할 수 있습니다.

자세한 내용은 지연, 패닉 및 복구 문서를 참조하십시오.

따라서 짧은 대답은 다중 값 반환을 사용하여 다르게 할 수 있다는 것입니다. (그리고 어쨌든 예외 처리의 한 형태가 있습니다.)


... 그리고 Linux 명성의 Linus는 예외를 쓰레기라고 불렀습니다.

Linus가 예외가 쓰레기라고 생각하는 이유를 알고 싶다면 주제에 대한 그의 글을 찾는 것이 가장 좋습니다. 지금까지 내가 추적 한 유일한 것은 C ++대한 두 개의 이메일에 포함 된이 인용문입니다 .

"전체 C ++ 예외 처리는 근본적으로 깨졌습니다. 특히 커널에서 깨졌습니다."

그는 특히 C ++ 예외에 대해 이야기하고 있으며 일반적인 예외는 아닙니다. (그리고 C ++ 예외 에는 올바르게 사용하기 까다로운 몇 가지 문제가있는 것 같습니다.)

내 결론은 Linus가 예외 (일반적으로)를 전혀 "쓰레기"라고 부르지 않았다는 것입니다!


30
나는 그들이 정보를 FAQ에 넣어서 숨기는 것이 싫다. :)
brian d foy

7
Linus는 "C ++은 끔찍한 언어입니다."로 이메일을 시작합니다. 그리고 그가 C ++와 C ++로 프로그래밍하기를 선택한 사람들을 얼마나 싫어하는지 계속해서 불평하고 있습니다. 결과적으로 나는 C ++에 대한 그의 다소 편향된 의견을 감안할 때 C ++의 예외에 대한 그의 의견을 신뢰할 수 있다고 생각하지 않습니다.
Pharap

1
@ Hi-Angel-내가 인용 한 텍스트에서 "일반적인 오류 처리를 위해 Go의 다중 값 반환을 사용하면 반환 값을 오버로드하지 않고도 오류를 쉽게보고 할 수 있습니다." . 그것이 관련되는 방법입니다. 어느 쪽이든, 저는 Go 디자이너의 이론적 근거를 인용하고 있습니다. 논쟁하고 싶다면 >> them <<과 논쟁하십시오.
Stephen C

1
@ Hi-Angel-저는 그 문단을 쓰지 않았습니다. 나는 단지 그것들을 인용했다. 그들에게 문제가 있다면 아마도 저자와 함께해야 할 것입니다. 이론적으로는 Go 언어에 대한 튜토리얼을 컨텍스트로 제공 할 수있었습니다. 그러나 솔직히 말해서 Go 용어를 이해하지 못하는 사람들은 Go 웹 사이트를 방문하여 모든 의미를 알아낼 수 있습니다.
스티븐 C

1
".. 결과 코드가 복잡해졌습니다."오래 전에 저는 많은 문자열 연산을 사용하여 C 프로그램을 작성했습니다. 모든 방법은 메모리를 할당하고 할당이 성공했는지 확인했습니다. 대부분의 코드는 할당을 확인하는 것 같습니다. 복잡하지 않습니까? 예외가있는 C ++는 저에게 큰 도움이되었습니다.
robsosno

29

예외는 그 자체로 나쁘지는 않지만 많이 발생할 것이라는 것을 알고 있다면 성능 측면에서 비용이 많이들 수 있습니다.

경험상 예외는 예외 조건에 플래그를 지정해야하며 프로그램 흐름을 제어하는 ​​데 사용해서는 안된다는 것입니다.


9
@Robert : "프로그램 흐름을 제어하는 ​​데 사용해서는 안됩니다.", 저는 이런 식으로 생각하지 않았습니다. 새로운 관점 : P +1
okw

2
또한 언어에 따라 다릅니다. 예를 들어 Java로 프로그래밍하는 경우 예외를 피하는 것은 어렵습니다.
Charles Salvia

2
@Charles : 요점은 버그, 잘못 구성된 시스템 또는 부적절한 입력을 나타내는 상황에서 예외가 적절하다는 것입니다. 대부분의 Java 라이브러리 예외는 "일반 워크 플로"코드에서 피할 수 있습니다.
Artelius

6
비용이 많이 들지 않습니다. 예를 들어 실행 시간이 0 인 "try"를 구현하고 스택에서 보는 호출자 주소를 기반으로 테이블에서 예외 처리기를 "throw"조회하도록 할 수 있습니다. 사용 예외는 성능과 전혀 관련이 없습니다.
asveikau

Rephrased; 이 질문은 일반적으로 예외를 사용하거나 예외를 전혀 사용하지 않는다는 것을 분명히 암시합니다 (그들은 쓰레기이거나 언어에조차 없음). 귀하의 대답은 프로그램 제어 흐름에 사용될 때 예외가 성능에 나쁜 이유만을 보여줍니다.
Maarten Bodewes 2014

26

나는 "예외 상황에서만 예외를 던진다"에 동의하지 않는다. 일반적으로 사실이지만 오해의 소지가 있습니다. 예외는 오류 조건 (실행 실패)에 대한 것입니다.

사용하는 언어에 관계없이 Framework Design Guidelines : Conventions, Idioms, Patterns for Reusable .NET Libraries (2nd Edition)를 선택하십시오. 예외 발생에 대한 장은 피어가 없습니다. 초판 (제 2 판)의 일부 인용문 :

  • 오류 코드를 반환 하지 마십시오 .
  • 오류 코드는 쉽게 무시할 수 있으며 종종 무시됩니다.
  • 예외는 프레임 워크에서 오류를보고하는 주요 수단입니다.
  • 경험상 좋은 규칙은 메서드가 이름이 암시하는대로 수행하지 않는 경우 메서드 수준 실패로 간주되어 예외가 발생한다는 것입니다.
  • 가능하면 정상적인 제어 흐름에 예외를 사용 하지 마십시오 .

예외의 이점 (API 일관성, 오류 처리 코드 위치 선택, 견고성 향상 등)에 대한 메모 페이지가 있습니다. 여러 패턴 (Tester-Doer, Try-Parse)을 포함하는 성능 섹션이 있습니다.

예외와 예외 처리는 하지 나쁜. 다른 기능과 마찬가지로 오용 될 수 있습니다.


4
나는 그것에 동의하지 않습니다. 나는 예외에 반대하지 않으며 그 책은 필수품이지만 .NET 개발 및 C #에 편향되어 있습니다.

3
나는 이것이 고대라는 것을 알고 있으며, .NET 유형과 * nix 유형 사이에 일반적인 스타일 불일치가있을 것 같다고 언급하고 싶었습니다. 내가 리눅스 개발자로 사용한 모든 라이브러리는 리턴 코드를 사용하고, 내가 읽은 * nix 스타일 가이드 (예 : 내 회사 및 Google )는 단순히 "우리는 예외를하지 않는다"라고 말합니다. 흥미 롭다고 생각하세요.
jarvisteve jul.

1
프레임 워크는 최종 사용자 애플리케이션과는 다르게 예외를 처리해야합니다. 프레임 워크는 예외를 던지는 것 외에 다른 오류를 처리하는 방법이 없습니다. 소비자 애플리케이션은 그렇게합니다.
0x6C38

11

golang의 관점에서 볼 때 예외 처리가 없으면 컴파일 프로세스가 간단하고 안전하게 유지됩니다.

Linus의 관점에서 나는 커널 코드가 코너 케이스에 관한 것임을 이해합니다. 따라서 예외를 거부하는 것이 합리적입니다.

코드에서 예외는 현재 작업을 바닥에 내려도 괜찮고 일반적인 경우 코드가 오류 처리보다 더 중요하다는 점입니다. 그러나 컴파일러에서 코드 생성이 필요합니다.

예를 들어 웹 및 데스크톱 응용 프로그램 코드와 같은 대부분의 고급 사용자 용 코드에서는 문제가 없습니다.


그러나 커널 코드에 대한 진실은 장기 실행 네이티브 서버 프로세스에도 해당됩니다.
Lothar

11

예외는 그 자체로 "나쁜"것이 아니라 때때로 나쁜 경향이있는 예외가 처리되는 방식입니다. 이러한 문제 중 일부를 완화하기 위해 예외를 처리 할 때 적용 할 수있는 몇 가지 지침이 있습니다. 이들 중 일부는 다음을 포함합니다 (하지만 이에 국한되지 않음).

  1. 프로그램 흐름을 제어하기 위해 예외를 사용하지 마십시오. 즉, "catch"문에 의존하여 논리 흐름을 변경하지 마십시오. 이것은 로직 주변의 다양한 세부 사항을 숨기는 경향이있을뿐만 아니라 성능 저하로 이어질 수 있습니다.
  2. 반환 된 "상태"가 더 합리적 일 때 함수 내에서 예외를 throw하지 마십시오. 예외적 인 상황에서만 예외를 throw하십시오. 예외를 만드는 것은 비용이 많이 들고 성능 집약적 인 작업입니다. 예를 들어, 파일을 열기 위해 메서드를 호출했는데 해당 파일이 존재하지 않는 경우 "FileNotFound"예외가 발생합니다. 고객 계정이 있는지 확인하는 메서드를 호출하는 경우 부울 값을 반환하고 "CustomerNotFound"예외는 반환하지 마십시오.
  3. 예외 처리 여부를 결정할 때 예외에 대해 유용한 작업을 수행 할 수없는 경우 "try ... catch"절을 사용하지 마십시오. 예외를 처리 할 수없는 경우 호출 스택을 버블 링하도록해야합니다. 그렇지 않으면 예외가 처리기에 의해 "삼켜 질"수 있고 세부 정보가 손실됩니다 (예외를 다시 던지지 않는 한).

2
상태를 반환하는 것은 까다로운 일입니다. 성공시 Customer 엔터티를 반환하거나 실패시 null을 반환하는 GetCustomer 메서드가있는 코드를 너무 많이 보았습니다. 여러 경우에 호출 코드는 결과를 확인하지 않았지만 즉시 고객에게 액세스했습니다. 이것은 대부분의 시간 동안 작동했습니다 ...
TrueWill

3
그러나 GetCustomer가 null을 반환하는 대신 예외를 throw하는 경우 클라이언트 코드는 여전히 예외를 처리해야합니다. null을 확인하든 예외를 처리하든 책임은 클라이언트 코드에 있습니다. 제대로 작동하지 않으면 조만간 무언가가 폭발 할 것입니다.
Chris

1
@TrueWill 언어 지원 템플릿 / 제네릭은 반환하여이 문제를 해결하는 것이 Option<T>아니라 null요즘. 예를 들어 Java 8에 도입되어 Guava (및 기타)에서 힌트를 얻었습니다.
Maarten Bodewes

@owlstead 네. 아마도 모나드를 사랑하십시오. 당신의 언어가 그것을 지원하고 패턴 매칭을 제공한다면 그것은 좋은 방법입니다.
TrueWill 2014 년

@owlstead 다시 말하지만, Chris가 말한 것은 여전히 ​​강력합니다. 사용자는 .orElse (defaultObject) 함수 또는 해당 언어가 결정한 관용구를 호출하는 것을 기억해야합니다. 결국에는 오류 처리 방법이 아니라 궁극적으로 프로그래머가 문제입니다.
Pharap

9

일반적인 주장은 특정 코드에서 어떤 예외가 나올지 (언어에 따라 다름), gotos 와 너무 비슷 하여 정신적으로 실행을 추적하기 어렵게 만드는 방법 이 없다는 것 입니다.

http://www.joelonsoftware.com/items/2003/10/13.html

이 문제에 대한 합의는 확실히 없습니다. Linus와 같은 하드 코어 C 프로그래머의 관점에서 예외는 확실히 나쁜 생각이라고 말할 수 있습니다. 하지만 일반적인 자바 프로그래머는 매우 다른 상황에 처해 있습니다.


1
C 코드에는 다른 방식으로 예외가 있습니다. 사소하지 않은 함수에 대한 모든 호출을 ifs로 래핑해야하므로 해당 언어를 사용하는 것이 골칫거리입니다!
RCIX

1
setjmp/ longjmp물건 도 있는데 , 꽤 나쁩니다.
Tim Sylvester

9
Duct Tape 프로그래머를 소중히 여기고 단위 테스트가 필요하다고 생각하지 않는 사람의 조언을 정말로 받고 싶습니까? joelonsoftware.com/items/2009/09/23.html
TrueWill

4
이것은 주제에 대한 논쟁이 성격 참조로 대체되는 토론에서 고전적인 실수 (또는 속임수)입니다. 그것은 보통 타락한 토론의 신호입니다.
Petr Gladkikh 2012

1
@PetrGladkikh 토론 Linus의 의견을 언급하는 OP로 시작 되었습니다. 치트는 권위에 대한 호소의 오류로 알려져 있습니다. 토론은 거기에서 올라갈 수 있으며 Linus가 자신의 성격을 언급함으로써 예외를 좋아하지 않는 이유에 대한 질문에 대답하는 것은 "속임수"가 아닙니다.
Jim Balter

7

예외는 나쁘지 않습니다. 그들은 C ++의 가장 우아한 점인 C ++의 RAII 모델과 잘 어울립니다. 예외적으로 안전하지 않은 코드가 이미 많이있는 경우 해당 컨텍스트에서 나쁘다. 리눅스 OS와 같이 정말 낮은 수준의 소프트웨어를 작성한다면 그것은 나쁘다. 많은 오류 반환 검사로 코드를 버리는 것을 좋아한다면 도움이되지 않습니다. 예외가 발생했을 때 (C ++ 소멸자가 제공하는) 리소스 제어에 대한 계획이 없다면 잘못된 것입니다.


7
RAII는 예외없이 유용합니다.
Mark Ransom

4
그러나 예외는 RAII (또는 기타 자동 리소스 관리) 없이는 유용하지 않습니다.
Greg Rogers

+1은 예외가 적절하지 않고 예외가 본질적으로 나쁘지 않은 상황을 지적합니다.
Pharap

4

따라서 예외에 대한 훌륭한 사용 사례는 ....

프로젝트에 참여하고 있고 모든 컨트롤러 (약 20 개의 다른 주요 컨트롤러)가 액션 메서드를 사용하여 단일 수퍼 클래스 컨트롤러를 확장한다고 가정 해 보겠습니다. 그런 다음 모든 컨트롤러는 한 경우에는 객체 B, C, D를 호출하고 다른 경우에는 F, G, D를 호출하여 서로 다른 작업을 수행합니다. 수많은 리턴 코드가 있고 모든 컨트롤러가이를 다르게 처리하는 많은 경우 예외가 여기에서 구출됩니다. 나는 그 모든 코드를 깨고 "D"에서 적절한 예외를 던졌고, 슈퍼 클래스 컨트롤러 액션 메서드에서 잡았고 이제 우리의 모든 컨트롤러는 일관성이 있습니다. 이전에 D는 최종 사용자에게 알리고 싶지만 할 수 없었던 여러 가지 오류 사례에 대해 null을 반환했습니다.

예, 각 레벨과 리소스 정리 / 누수에 대해 걱정해야하지만 일반적으로 컨트롤러 중 어느 누구도 이후에 정리할 리소스가 없었습니다.

감사합니다. 예외가 있었거나 큰 리팩터링을했고 간단한 프로그래밍 문제에 너무 많은 시간을 낭비했을 것입니다.


1
+1 내가 읽은 예외를 사용하는 가장 좋은 주장 중 하나입니다. 더 자세한 예제 (예 : UML 다이어그램, 의사 코드 또는 실제 코드)를 사용할 수 있지만 하위 클래스가 일관되게 수행되도록하는 요점은 좋은 것입니다. 또한 증거가 일화 적이라는 사실은 예외가 실제 상황에서 유용하고 유용성이 모든 언어 기능의 주요 목적임을 보여줍니다.
Pharap

추가로, 스칼라를 사용하는 경우 예외 또는 실제 응답을 나타내는 Try [ResponseType]을 대신 반환 할 수 있습니다. 그런 다음 시도에 넣는 것 이외의 실제 예외없이 위에서 생략 한 동일한 패턴을 따를 수 있습니다. 그런 다음 모든 방법이 필요하다고 생각하는 1 + n 응답 유형을 반환하는 것과 같습니다. 그러나 우리는 스칼라에서 Try와 매우 유사하게 작동하지만 더 많은 비동기 프로그래밍에 도움이되는 Future [response]를 반환합니다.
Dean Hiller 2015 년

2

이론적으로 그들은 정말 나쁩니다. 완벽한 수학적 세계에서는 예외 상황을 얻을 수 없습니다. 기능적 언어를 보면 부작용이 없으므로 예외적 인 상황에 대한 소스가 거의 없습니다.

그러나 현실은 또 다른 이야기입니다. 우리는 항상 "예기치 않은"상황이 있습니다. 이것이 우리에게 예외가 필요한 이유입니다.

ExceptionSituationObserver에 대한 구문 설탕으로 예외를 생각할 수 있다고 생각합니다. 예외 알림 만받습니다. 더 이상은 없습니다.

Go를 사용하면 "예기치 않은"상황을 처리 할 무언가를 소개 할 것입니다. 나는 그들이 그것을 예외로 덜 파괴적으로 들리게 만들고 응용 프로그램 로직으로 더 많이 들리도록 노력할 것이라고 생각할 수 있습니다. 그러나 이것은 단지 내 추측입니다.


2
"기능적 언어를보세요. 부작용이 없으므로 예외적 인 상황에 대한 소스가 거의 없습니다." 그것은 심한 과장입니다.
Stephen C

3
수학에서 5/0은 무엇입니까? Arcsin (200)? Sqrt (-1)? 수학에는 예외적 인 상황이 많이 있습니다.
Robert Fraser

3
이것은 실행적인 상황이 아닙니다 ... 그저 의미가 없습니다 ... 그리고 예외로 구현 될 수 있기 때문에 ... 또한 전제 조건의 바이럴 레이션으로 구현 될 수 있습니다. 따라서 기술 구현에 따라 달라집니다.
Mike Chaliy

3
@MikeChaliy-미안하지만 그것은 단지 궤변입니다. 그런 종류의 추론을 적용하여 예외 상황이 전혀 없다고 말할 수 있습니다. 실제로 의미가 없거나 명확한 값이없는 수학적 표현은 예외적입니다. 이것은 예외를 던지고 잡아서 처리해야한다는 것을 의미하지는 않지만, 그렇게하지 않으면 특수 값 (Inf 및 Nan과 같은) 또는 여러 값을 반환하는 연산이 필요합니다. 요컨대, 이러한 경우 에는 특별한 치료가 필요합니다 .
Stephen C

1
컴퓨터는 상태 머신입니다. 완벽한 수학 세계는 아닙니다.
Arunav Sanyal 2016 년

1

Java와 차례로 .net의 부분적 기반을 형성하는 C ++의 예외 처리 패러다임은 몇 가지 좋은 개념을 소개하지만 몇 가지 심각한 제한 사항도 있습니다. 예외 처리의 주요 설계 의도 중 하나는 메서드가 사후 조건을 충족하거나 예외를 throw하는지 확인하고 메서드가 종료되기 전에 발생해야하는 모든 정리가 발생하는지 확인하는 것입니다. 불행히도 C ++, Java 및 .net의 예외 처리 패러다임은 모두 예기치 않은 요인으로 인해 예상 정리가 수행되지 않는 상황을 처리하는 좋은 방법을 제공하지 못합니다. 이는 예기치 않은 일이 발생하면 모든 것이 갑자기 중단 될 위험이 있음을 의미합니다 (예외 처리에 대한 C ++ 접근 방식은 스택 해제 중에 발생 함).

예외 처리가 일반적으로 좋더라도 다른 문제를 정리할 때 발생하는 문제를 처리 할 수있는 좋은 수단을 제공하지 못하는 예외 처리 패러다임을 받아 들일 수없는 것으로 간주하는 것은 합리적이지 않습니다. 그렇다고해서 다중 실패 시나리오에서도 합리적인 동작을 보장 할 수있는 예외 처리 패러다임으로 프레임 워크를 설계 할 수 없다는 말은 아니지만 상위 언어 나 프레임 워크는 아직 그렇게 할 수 없습니다.


1

나는 다른 모든 답변을 읽지 않았기 때문에 이미 언급되었지만 한 가지 비판은 프로그램이 긴 사슬로 끊어져 코드를 디버깅 할 때 오류를 추적하기 어렵게 만든다는 것입니다. 예를 들어, Foo ()가 ToString ()을 호출하는 Wah ()를 호출하는 Bar ()를 호출하면 실수로 잘못된 데이터를 ToString ()으로 푸시하면 거의 완전히 관련이없는 함수 인 Foo ()의 오류처럼 보입니다.


0
  • 처리되지 않는 예외는 일반적으로 나쁩니다.
  • 잘못 처리 된 예외는 (물론) 나쁘다.
  • 예외 처리의 '양호 / 불량'은 상황 / 범위 및 적절성에 따라 달라지며이를 수행하기위한 것이 아닙니다.

0

좋아, 여기에 지루한 대답. 정말 언어에 따라 다릅니다. 예외로 인해 할당 된 리소스가 남겨질 수있는 경우이를 피해야합니다. 스크립팅 언어에서는 응용 프로그램 흐름의 일부를 버리거나 뛰어 넘습니다. 그것은 그 자체로 싫은 일이지만 예외와 함께 거의 치명적인 오류를 피하는 것은 허용되는 아이디어입니다.

오류 신호의 경우 일반적으로 오류 신호를 선호합니다. 모두 API, 사용 사례 및 심각도 또는 로깅이 충분한 지 여부에 따라 다릅니다. 또한 나는 행동을 재정의하려고 노력하고 있습니다 throw Phonebooks(). "예외"는 종종 막 다른 골목이지만 "전화 번호부"에는 오류 복구 또는 대체 실행 경로에 대한 유용한 정보가 포함되어 있습니다. (아직 좋은 사용 사례를 찾지 못했지만 계속 시도하십시오.)


0

나에게 문제는 매우 간단합니다. 많은 프로그래머가 예외 처리기를 부적절하게 사용합니다. 더 많은 언어 자원이 더 좋습니다. 예외를 처리 할 수 ​​있어야합니다. 잘못된 사용의 한 가지 예는 검증되지 않은 정수 여야하는 값이거나 0으로 나누기를 확인하지 않고 나누는 다른 입력입니다 ... 예외 처리는 더 많은 작업과 어려운 생각을 피하는 쉬운 방법 일 수 있습니다. 프로그래머는 더티 단축키를 사용하고 예외 처리를 적용하고 싶을 수 있습니다 ... "전문 코드는 절대 실패하지 않습니다"라는 문장은 알고리즘에 의해 처리 된 문제 중 일부가 그 자체로 불확실한 경우 환상 일 수 있습니다. 아마도 알려지지 않은 상황에서 본질적으로 예외 처리기를 사용하는 것이 좋습니다. 좋은 프로그래밍 관행은 논쟁의 여지가 있습니다.


문제는 코드가 실패 할 수 있는지 여부가 아닙니다 (또는 그렇게해서는 안됩니다). 더 큰 문제는 코드가 실패 할 경우 세부 사항에 관심을 갖는 정도입니다. 문서를로드하려고하는데 "데이터 읽기"메소드 중 하나가 실패하면 문서를로드 할 수 없다는 것과 상관없이 효과가 동일하기 때문에 종종 어떤 방법을 신경 쓰지 않습니다. 개념적으로 예외 처리는이를 위해 좋습니다. 문제는 .NET과 Java의 예외 처리 패러다임이 함께 ​​묶어야하는 "지루한"예외와하지 말아야하는 예외를 구별하는 좋은 방법을 제공하지 않는다는 것입니다.
supercat 2013-09-13
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.