누가 Exception.Message를 읽어야합니까?


27

예외를 설계 할 때 사용자 나 개발자가 이해해야하는 메시지를 작성해야합니까? 실제로 예외 메시지를 읽는 사람은 누구입니까?

예외 메시지가 전혀 유용하지 않다는 것을 알고 항상 작성하는 데 어려움을 겪고 있습니다. 일반적으로 예외 유형에 따라 작동하지 않는 이유와 사용자 정의 특성이 파일 이름, 색인, 키 등과 같은 정보를 추가 할 수 있습니다. 왜 메시지 자체에서이를 반복해야합니까? 자동 생성 된 메시지도 수행 할 수 있으며 포함해야 할 모든 것은 추가 속성 목록이있는 예외 이름입니다. 이것은 필기 텍스트만큼이나 유용합니다.

메시지를 전혀 쓰지 않고 의미있는 메시지를 다른 언어로 작성하는 대신 코드로 하드 ​​코딩하는 특수 예외 렌더러를 사용하는 것이 더 좋지 않습니까?


해당 질문 중 하나가 내 질문에 대한 답변을 제공하는지에 대한 질문을 받았습니다.

나는 둘 다 읽었으며 그들의 대답에 만족하지 못했습니다. 그들은 일반적으로 사용자 에 대해 이야기 하고 수신자보다 메시지 자체의 내용에 중점을두고 최종 사용자와 개발자 중 적어도 두 명이있을 수 있습니다. 예외 메시지를 작성할 때 어떤 대화를해야하는지 절대 알 수 없습니다.

심지어 유명한 메시지는 예외 유형의 이름을 다른 단어로 반복하기 때문에 실제 가치가 전혀 없다고 생각합니다. 완벽하게 자동으로 생성 할 수 있습니다.

나에게 예외 메시지는 독자의 차별화가 부족합니다. 완벽한 최종 사용자 용 및 개발자를위한 하나의 예외는 메시지 적어도 두 가지 버전을 제공해야합니다. 그것을 메시지라고 부르는 것은 너무 일반적입니다. 그런 다음 개발자 메시지를 영어로 작성해야하지만 최종 사용자의 메시지를 다른 언어로 번역해야 할 수도 있습니다. 이 메시지를 하나의 메시지로만 달성 할 수는 없으므로 예외는 최종 사용자 메시지에 방금 말했듯이 다른 언어로 제공 될 수있는 식별자를 제공해야합니다.

다른 모든 링크 된 질문을 읽으면 개발자가 아닌 최종 사용자가 예외 메시지를 읽게된다는 인상을받습니다 ... 단일 메시지는 케이크를 먹고 먹는 것과 같습니다.


4
프로그래머가 생각하는 두 가지 다른 질문이 있습니다. 중복인지 여부는 확실하지 않지만 반드시 읽어야하며 아마도 일부 또는 모든 우려 사항을 해결해야한다고 생각합니다 . 좋은 예외 메시지를 작성하는 방법많은 예외 메시지에 유용한 세부 정보가 포함되지 않은 이유 ?
Thomas Owens

2
@ThomasOwens 둘 다 읽었지만 예외 메시지의 특정 수신자를 다루지 않습니다. 그들은 일반적으로 사용자에 대해 이야기하지만 그는 누구입니까? 무엇이 잘못되었는지 분석해야하는 개발자 나 프로그래밍에 대해 이미 알고있는 것은 소프트웨어 사용자입니까? 나는 메시지를 쓸 때 누구를 다루어야하는지 확신 할 수 없다.
t3chb0t

2
여기에 좋은 대답은 그러한 질문 중 하나 또는 둘 다를 나타낼 수 있다고 생각하지만 중복되는 것은 아닙니다.
Monica와의 가벼움 경주

1
지구상에서 왜 이것이 중복으로 폐쇄 되었습니까? 그것이 다른 질문 (이것은 아닙니다)의 복제 였음에도 불구하고,이 질문은 분명히 더 나은 대답을 가지고 있습니다. 이것은 복제 된 것으로 표시된 다른 질문이어야합니다.
벤 애런 슨

2
당신이 그 예외 메시지는 사용자를위한 전제하지 않는 한 나는 아직도 정말 많은 중복이 표시되지 않습니다 @MichaelT
벤 아 론슨

답변:


46

이 메시지는 다른 개발자를위한 것입니다

이러한 메시지는 개발자 가 응용 프로그램을 디버깅하는 데 도움 이되도록 읽습니다 . 두 가지 형태가 있습니다.

  • 액티브 디버깅. 실제로 코드를 작성하고 어떤 일이 발생하는지 파악하는 동안 디버거를 실행하고 있습니다. 이와 관련하여 도움이되는 예외는 무엇이 잘못되었는지 쉽게 이해하도록하거나 결국 대안을 제안함으로써 도움이 될 것입니다 (선택 사항 임에도 불구하고).

  • 패시브 디버깅. 코드가 프로덕션 환경에서 실행되고 실패합니다. 예외는 기록되지만 메시지와 스택 추적 만받습니다. 이와 관련하여 유용한 예외 메시지는 버그를 신속하게 지역화하는 데 도움이됩니다.

    이러한 메시지는 종종 기록되기 때문에 민감한 정보 (예 : 앱을 디버깅하는 데 유용한 경우에도 개인 키 또는 비밀번호)를 포함해서는 안됩니다.

예를 들어, IOSecurityException파일을 쓸 때 발생하는 예외 유형은 문제에 대해 명확하지 않습니다. 파일에 액세스 할 수있는 권한이 없기 때문입니까? 아니면 읽을 수는 있지만 쓸 수는 없습니까? 아니면 파일이 존재하지 않고 파일을 만들 수있는 권한이 없습니까? 또는 잠겨있을 수 있습니다 (이 경우에는 예외 유형이 다르지만 실제로 유형은 때로는 암호가 될 수 있습니다). 아니면 코드 액세스 보안으로 인해 I / O 작업을 수행하지 못할 수 있습니까?

대신 :

IOSecurityException : 파일을 찾았지만 해당 내용을 읽을 수있는 권한이 거부되었습니다.

훨씬 더 명시 적입니다. 여기서는 디렉토리에 대한 권한이 올바르게 설정되었음을 알지만 (그렇지 않으면 파일이 존재한다는 것을 알 수는 없지만) 파일 수준의 권한에 문제가 있습니다.

또한 아직 예외 유형이 아닌 추가 정보를 제공 할 수없는 경우 메시지를 비워 둘 수 있습니다. DivisionByZeroException메시지가 중복되는 좋은 예입니다. 반면에 대부분의 언어에서 메시지를 지정하지 않고 예외를 발생시킬 수 있다는 사실은 다른 이유로 인해 수행됩니다. 기본 메시지가 이미 사용 가능하거나 필요할 경우 나중에 생성되기 때문입니다. 메시지는 "OOPly" 말하기 와 같은 예외 유형에 포함 됩니다.

기술적 인 (종종 성능) 이유로 인해 일부 메시지는 원래보다 훨씬 더 암호화되어 있습니다. .NET NullReferenceException:

객체 참조가 객체의 인스턴스로 설정되지 않았습니다.

도움이되지 않는 메시지의 훌륭한 예입니다. 유용한 메시지는 다음과 같습니다.

product에서 호출 될 때 객체 참조 가 객체의 인스턴스로 설정되지 않았습니다 product.Price.

이러한 메시지는 최종 사용자를위한 것이 아닙니다!

최종 사용자에게는 예외 메시지가 표시되지 않습니다. 못. 일부 개발자는 결국 이러한 메시지를 사용자에게 보여 주지만 사용자 경험이 나쁘고 좌절됩니다. 다음과 같은 메시지 :

객체 참조가 객체의 인스턴스로 설정되지 않았습니다.

최종 사용자에게는 전혀 의미가 없으며 모든 비용을 피해야합니다.

최악의 시나리오는 전역 try / catch를 사용하여 예외를 사용자에게 던지고 앱을 종료하는 것입니다. 사용자를 걱정하는 응용 프로그램 :

  • 우선 예외를 처리합니다. 대부분은 사용자를 방해하지 않고 처리 할 수 ​​있습니다. 네트워크가 다운 되었습니까? 몇 초 기다렸다가 다시 시도해보십시오.

  • 사용자가 응용 프로그램을 예외적 인 사례로 이끌지 못하게합니다. 사용자에게 두 개의 숫자를 입력하고 첫 번째 숫자를 두 번째 숫자로 나누도록 요청하는 경우 몇 초 후에 사용자를 비난 하기 위해 두 번째 경우에 0을 입력하게하는 이유는 무엇입니까? 텍스트 상자를 빨간색으로 강조 표시하고 (숫자가 0이 아니어야한다는 유용한 도구 설명과 함께) 필드가 빨간색으로 유지 될 때까지 유효성 검사 버튼을 비활성화하는 것은 어떻습니까?

  • 사용자에게 오류가 아닌 형태로 작업을 수행하도록 초대합니다. 파일에 액세스 할 수있는 권한이 충분하지 않습니까? 사용자에게 관리 권한을 부여하거나 다른 파일을 선택하도록 요청하지 않는 이유는 무엇입니까?

  • 아무것도 작동하지 않으면 사용자의 불만을 줄이기 위해 특별히 작성된 유용하고 친숙한 오류를 보여 주어 사용자가 잘못 된 것을 이해하고 결국 문제를 해결하도록 도와주고 향후 해당 오류를 방지 할 수 있도록 도와줍니다 (해당되는 경우).

    귀하의 질문에 예외적으로 두 가지 메시지, 즉 개발자를위한 기술적 인 메시지와 최종 사용자를위한 메시지를 두도록 제안했습니다. 이는 사소한 경우에 유효한 제안이지만 대부분의 예외는 사용자에게 의미있는 메시지를 생성 할 수없는 수준에서 생성됩니다. 가지고 DivisionByZeroException우리가 일어나는 예외를 방지 할 수 있고 그것을 자신을 처리 할 수없는 것을 상상한다. 부서가 발생하면 프레임 워크 (예외를 발생시키는 비즈니스 코드가 아닌 프레임 워크이므로)는 사용자에게 유용한 메시지가 무엇인지 알고 있습니까? 절대적으로하지:

    0으로 나누기가 발생했습니다. [승인]

    대신 예외를 던지고 비즈니스 컨텍스트를 알고 더 높은 수준에서 예외를 잡아서 최종 사용자를 실제로 돕기 위해 조치를 취할 수 있습니다.

    D13 필드는 E6 필드의 값과 동일한 값을 가질 수 없습니다. 해당 값의 빼기가 제수로 사용되기 때문입니다. [승인]

    또는 아마도 :

    ATP 서비스에서보고 한 값이 로컬 데이터와 일치하지 않습니다. 로컬 데이터가 동기화되지 않았기 때문일 수 있습니다. 운송 정보를 동기화하고 다시 시도 하시겠습니까? [예 아니오]

이 메시지는 파싱 용이 아닙니다

예외 메시지는 프로그래밍 방식 으로 구문 분석 되거나 사용될 것으로 예상되지 않습니다 . 발신자가 추가 정보를 필요로한다고 생각되면 예외와 함께 메시지와 함께 추가하십시오. 메시지는 예고없이 변경 될 수 있으므로 중요합니다. 유형은 인터페이스의 일부이지만 메시지는 그렇지 않습니다. 예외 처리에 의존하지 마십시오.

예외 메시지를 상상해보십시오.

500 ms 동안 기다린 후 캐싱 서버 연결 시간이 초과되었습니다. 시간 초과를 늘리거나 성능 모니터링을 확인하여 서버 성능 저하를 식별하십시오. 캐싱 서버의 평균 대기 시간은 6ms입니다. 지난 달 4ms 지난 주와 377ms 동안 마지막 시간 동안.

"500", "6", "4"및 "377"값을 추출하려고합니다. 구문 분석을 수행하는 데 사용할 접근 방식에 대해 약간 생각한 다음 읽기만 계속하십시오.

당신은 아이디어가 있습니까? 큰.

이제 원래 개발자가 오타를 발견했습니다.

Connecting to the caching sever timed out after waiting [...]

해야한다:

                            ↓
Connecting to the caching server timed out after waiting [...]

또한 개발자는 월 / 주 / 1 시간이 특별히 관련이 없다고 생각하므로 추가 변경도 수행합니다.

캐싱 서버의 평균 대기 시간은 6ms입니다. 지난 달 5ms. 지난 24 시간 동안 377ms 마지막 한 시간 동안.

파싱은 어떻게됩니까?

구문 분석 대신 예외 속성을 사용할 수 있습니다 (데이터를 직렬화하는 즉시 원하는 것을 포함 할 수 있음).

{
    message: "Connecting to the caching [...]",
    properties: {
        "timeout": 500,
        "statistics": [
            { "timespan": 1, "unit": "month", "average-timeout": 6 },
            { "timespan": 7, "unit": "day", "average-timeout": 4 },
            { "timespan": 1, "unit": "hour", "average-timeout": 377 },
        ]
    }
}

이 데이터를 지금 사용하는 것이 얼마나 쉬운가요?

경우에 따라 (예 : .NET 내에서) 메시지가 사용자 언어로 번역 될 수도 있습니다 (IMHO, 개발자가 영어로 읽을 수 있기 때문에 해당 메시지를 번역하는 것은 절대적으로 잘못되었습니다). 그러한 메시지를 파싱하는 것은 거의 불가능합니다.


2
최종 사용자에 대한 좋은 지적. 최종 사용자에게는 보안상의 이유로 예외 메시지가 표시되지 않아야한다고 덧붙입니다. 비 레이맨 사용자에게 오류의 정확한 특성을 알면 악용 될 수 있습니다. 최종 사용자는 자신이하고있는 작업의 맥락에서 오류를 알고 있어야합니다.
Neil

1
@ Neil : 그것은 너무 이론적입니다. 실제로 사용자에게 로그를 숨기는 이점은 온라인 로깅의 복잡성보다 중요합니다. 사용자 친화적 측면을 계산하지 않습니다. 새 Windows VM에 Visual Studio를 설치한다고 가정하십시오. 갑자기 설치가 실패합니다. 로그로 가서 문제를 직접 진단 (스택 교환 및 블로그의 도움으로)하거나 Microsoft가 문제를 해결하고 핫픽스를 게시 할 때까지 기다리시겠습니까?
Arseni Mourzenko

4
"object reference ..."메시지가 도움이되지 않는다는 것을 모두가 알고 있다고 생각합니다. 그러나 관련 질문은 원하는 메시지를 생성하는 지터가 생성하려는 머신 코드입니까? 이 연습을 수행하면 예외가 아닌 모든 경우에 부과 되는 막대한 성능 비용 없이 메시지를 쉽게 생성 할 수 없음을 신속하게 알 수 있습니다 . 부주의 한 개발자 작업을 매우 쉽게 수행 할 수 있다는 이점은 최종 사용자의 성능 저하로 인해 지불되지 않습니다.
Eric Lippert

7
보안 예외와 관련하여 예외의 정보가 적을수록 좋습니다. 내가 가장 좋아하는 일화는 베타 버전 .NET 1.0에서는 "파일 C : \ foo.txt 파일의 이름을 결정할 권한이 없습니다"와 같은 예외 메시지가 표시 될 수 있다는 것입니다. 자세한 예외 메시지에 감사드립니다!
Eric Lippert

2
최종 사용자에게 자세한 오류 메시지를 표시하지 않는 것에 동의하지 않습니다. 게임 / 소프트웨어를 시작하지 못하게하는 암호 오류 메시지가 여러 번 나에게 발생했지만 Google에서 쉽게 해결할 수있는 방법이 있습니다. 이 오류 메시지가 없으면 해결 방법을 찾을 수있는 방법이 없습니다. "추가 정보"버튼 아래에 세부 정보를 숨기는 것이 더 낫습니까?
BlueRaja-대니 Pflughoeft

2

이에 대한 대답은 전적으로 예외에 달려 있습니다.

가장 중요한 질문은 "문제를 해결할 수있는 사람은 누구입니까?"입니다. 파일을 여는 동안 파일 시스템 오류로 인해 예외가 발생한 경우 최종 사용자에게 해당 메시지를 제공하는 것이 좋습니다. 메시지에는 오류 수정 방법에 대한 자세한 정보가 포함되어있을 수 있습니다. DLL을로드하는 플러그인 시스템이있는 작업에서 결정적인 사례를 생각할 수 있습니다. 사용자가 명령 행에서 오타를 작성하여 잘못된 플러그인을로드 한 경우 기본 시스템 오류 메시지에는 실제로 문제점을 정정 할 수있는 유용한 정보가 포함되어 있습니다.

그러나 대부분의 경우 잡히지 않은 예외는 사용자가 해결할 수 없습니다. 대부분은 코드를 변경하는 것과 관련이 있습니다. 이 경우 메시지 소비자는 분명히 개발자입니다.

예외를 올바르게 처리하고보다 친근한 예외를 처리 할 수있는 기회가 있기 때문에 예외가 발견 된 경우 더 복잡합니다. 필자가 작성한 한 스크립팅 언어는 예외적으로 개발자를위한 메시지 인 예외를 던졌습니다. 그러나 스택이 풀릴 때 스크립팅 언어 내에서 사용자가 읽을 수있는 스택 추적을 추가했습니다. 내 사용자는 메시지를 거의 접할 수 없었지만 스크립트에서 스택 추적을보고 95 %의 시간에 무슨 일이 있었는지 알아낼 수있었습니다. 나머지 5 %는 그들이 나를 불렀을 때 스택 추적뿐만 아니라 무엇이 잘못되었는지 알아내는 데 도움이되는 개발자가 준비한 메시지를 받았습니다.

전체적으로 예외 메시지를 알 수없는 내용으로 취급합니다. 구현에 대해 더 많이 알고있는 다른 업스트림 사용자가 내 소프트웨어를 예외로 처리했습니다. 때로는 알 수없는 내용이 최종 사용자에게 유용 할 때가 있습니다. 때로는 그렇지 않습니다.


1
"파일을 여는 동안 파일 시스템 오류로 인해 예외가 발생한 경우 최종 사용자에게 해당 메시지를 제공하는 것이 좋습니다."파일 시스템 오류를 발생 시키면 컨텍스트를 알 수 없습니다. 사용자 작업이거나 완전히 관련되지 않은 것일 수 있습니다 (사용자가 눈치 채지 않고도 앱이 일부 구성을 백업하는 것처럼). 즉, 오류 메시지 를 표시하는 try / catch 블록이 있으며 이는 예외 메시지를 직접 표시하는 것과는 매우 다릅니다 .
Arseni Mourzenko

@MainMa 컨텍스트를 명시 적으로 알지 못하지만 많은 힌트가 있습니다. 예를 들어, 파일을 여는 중이고 "IOError : permission denied"가 예외 인 경우 사용자가 2와 2를 함께 모아 문제의 파일을 파악할 수있는 적절한 기회가 있습니다. 내가 가장 좋아하는 편집기는이 작업을 수행합니다. 플러 프가없는 대화 상자에 예외 텍스트가 출력됩니다. 반면에, 애플리케이션을로드 할 때 많은 이미지를로드하는 동안 "권한이 거부되었습니다"라는 메시지가 표시되면 사용자가 정보로 무언가를 할 수 있다고 가정하는 것이 훨씬 합리적이지 않습니다.
Cort Ammon-복원 모니카

요점을 주장하면서, 사용자에게 NullReferenceException을 표시하는 데 아무런 가치가 없었습니다. 단지 그 메시지를 표시하는 단순한 행동은 소프트웨어가 복구 방법에 대한 단서 가 없다는 것을 보여줍니다 ! 이 예외 메시지는 최종 사용자에게 유용하지 않습니다.
Cort Ammon-복원 모니카
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.