특정 문제에 대한 예외를 작성하시나요, 아니면 일반적인 예외를 작성하시나요?

StackOverflow https://stackoverflow.com/questions/21652

  •  09-06-2019
  •  | 
  •  

문제

유틸리티에 사용자 ID를 제공한 다음 해당 사용자에게 이메일을 보내는 코드가 있습니다.

emailUtil.sendEmail(userId, "foo");

public void sendEmail(String userId, String message) throws MailException {
    /* ... logic that could throw a MailException */
}

MailException 여러 가지 이유, 이메일 주소 문제, 메일 템플릿 문제 등으로 인해 발생할 수 있습니다.

내 질문은 이것입니다:이러한 모든 예외에 대해 새로운 예외 유형을 생성한 다음 개별적으로 처리합니까, 아니면 하나의 MailException을 생성한 다음 예외에 다른 작업을 수행할 수 있는 항목(설명 텍스트가 아닌 컴퓨터에서 읽을 수 있는 항목)을 저장합니까? 실제로 일어난 일을 바탕으로.

편집하다: 명확히 말하면 예외는 로그 및 기타 사항에 대한 것이 아니며 이는 코드가 로그에 반응하는 방식과 관련이 있습니다.메일 예제를 계속 진행하려면 메일을 보낼 때 이메일 주소가 없거나 이메일 주소가 없어서 실패할 수 있다고 가정해 보겠습니다. 유효한 이메일 주소가 아니면 실패할 수 있습니다.등.

내 코드는 이러한 각 문제에 대해 다르게 반응하기를 원합니다(주로 클라이언트에 반환된 메시지를 변경하지만 실제 논리도 변경함).

이러한 문제 각각에 대해 예외를 구현하거나 코드가 문제의 종류를 구별할 수 있도록 내부에 뭔가(열거형)가 있는 하나의 포괄적인 예외를 구현하는 것이 가장 좋을까요?

도움이 되었습니까?

해결책

나는 일반적으로 일반적인 예외로 시작하고 필요에 따라 하위 클래스를 분류합니다.필요한 경우 항상 일반 예외(및 하위 클래스로 분류된 모든 예외)를 포착할 수 있지만 특정 예외도 포착할 수 있습니다.

Java-API의 예로는 FileNotFoundException 또는 EOFException과 같은 하위 클래스가 있는 IOException이 있습니다.

이렇게 하면 두 가지 장점을 모두 얻을 수 있으며 다음과 같은 throw 절이 없습니다.

throws SpecificException1, SpecificException2, SpecificException3 ...

장군

throws GeneralException

충분합니다.그러나 특별한 상황에 대한 특별한 반응을 원할 경우 언제든지 특정 예외를 포착할 수 있습니다.

다른 팁

내 코드에서 대부분의 예외는 사용자에게 메시지를 표시하고 로그에 기록하는 예외 핸들러에 의해 포착되는 UI 계층까지 침투하는 것으로 나타났습니다.결국 예상치 못한 예외입니다.

가끔은 (당신이 원하는 것처럼) 특정 예외를 포착하고 싶을 때가 있습니다.그러나 이는 다소 드물며 논리를 제어하기 위해 예외를 사용한다는 것을 의미한다는 것을 알게 될 것입니다. 이는 비효율적이고(느리며) 종종 눈살을 찌푸리게 합니다.

따라서 예제를 사용하여 이메일 서버가 구성되지 않았을 때 일부 특수 논리를 실행하려면 emailUtil 객체에 다음과 같은 메소드를 추가할 수 있습니다.

공개 bool isEmailConfigured()

...특정 예외를 찾는 대신 먼저 호출하세요.

예외가 발생하면 상황이 완전히 예상치 못한 것이며 코드가 이를 처리할 수 없다는 의미입니다. 따라서 최선의 방법은 이를 사용자에게 보고하는 것입니다(또는 로그에 기록하거나 다시 시작하는 것).

예외 계층 구조와 오류 코드가 있는 예외를 갖는 것에 관해서는 일반적으로 후자를 수행합니다.완전히 새로운 클래스를 정의하는 대신 새로운 오류 상수만 정의해야 한다면 새로운 예외를 추가하는 것이 더 쉽습니다.그러나 프로젝트 전반에 걸쳐 일관성을 유지하려고 노력하는 한 그다지 중요하지 않습니다.

@크리스라이블리

예외 또는 "상태 코드"에 메시지를 전달할 수 있다는 것을 알고 있습니다.여기서 바퀴를 재발명하고 있습니다.

반환된 예외에 따라 수행할 작업을 CODE에서 결정해야 하는 경우 공통 기본 유형을 하위 클래스로 분류하는 잘 명명된 예외를 생성하는 것으로 나타났습니다.전달된 메시지는 "인간의 눈"으로만 간주되어야 하며 결정을 내리기에는 너무 취약합니다.컴파일러가 작업을 수행하도록 하세요!

확인된 예외를 인식하지 못하는 메커니즘을 통해 이를 더 높은 계층으로 전달해야 하는 경우 이를 포착할 수 있고 원래 원인에 따라 조치를 취할 수 있는 RuntimeException(MailDomainException)의 적절한 명명된 하위 클래스로 래핑할 수 있습니다.

이는 애플리케이션이 수행하는 작업에 따라 다릅니다.다음과 같은 경우 개별 예외를 발생시킬 수 있습니다.

  • 애플리케이션이 고가용성입니다.
  • 이메일을 보내는 것이 특히 중요합니다
  • 응용프로그램의 범위는 작고 이메일 전송이 큰 부분을 차지합니다.
  • 애플리케이션은 원격 사이트에 배포되며 디버깅을 위한 로그만 가져옵니다.
  • mailException에 캡슐화된 예외의 일부 하위 집합에서는 복구할 수 있지만 다른 예외에서는 복구할 수 없습니다.

대부분의 경우 예외 텍스트만 기록하고 이미 매우 세분화된 예외를 세분화하는 데 시간을 낭비하지 마십시오.

위의 조합이 가장 좋은 결과를 가져올 것이라고 생각합니다.

문제에 따라 다양한 예외를 발생시킬 수 있습니다.예를 들어이메일 주소 누락 = ArgumentException.

그러나 UI 레이어에서는 예외 유형을 확인하고 필요한 경우 메시지를 확인한 다음 사용자에게 적절한 메시지를 표시할 수 있습니다.저는 개인적으로 특정 유형의 예외가 발생하는 경우에만 사용자에게 정보 메시지를 표시하는 경향이 있습니다(내 앱에서는 UserException).물론 정규식으로 쉽게 확인할 수 있는 잘못된 형식의 이메일에 대한 필터가 아니라 정말 가능성이 없는 시나리오에서 예외가 생성되는지 확인하기 위해 스택에서 최대한 사용자 입력을 제거하고 확인해야 합니다.

또한 사용자 입력에서 예외를 포착하는 것이 성능에 미치는 영향에 대해 걱정하지 않습니다.예외로 인해 성능 문제가 발생하는 유일한 경우는 예외가 발생하여 루프나 유사한 상황에 빠질 때입니다.

예외를 사용하는 대신 실행에 문제가 있을 수 있는 메서드에서 상태 개체 목록을 반환하는 경향이 있습니다.상태 개체에는 심각도 열거(정보, 경고, 오류 등), "이메일 주소"와 같은 상태 개체 이름 및 "잘못 형식의 이메일 주소"와 같은 사용자가 읽을 수 있는 메시지가 포함되어 있습니다.

그런 다음 호출 코드는 UI까지 필터링할 항목과 자체적으로 처리할 항목을 결정합니다.

개인적으로 나는 일반적인 코드 솔루션을 구현할 수 없는 경우에만 예외가 적용된다고 생각합니다.성능 저하와 처리 제한이 나에게는 너무 과중합니다.

상태 개체 목록을 사용하는 또 다른 이유는 여러 오류(예: 유효성 검사 중)를 식별하는 것이 훨씬 더 쉽다는 것입니다.결국, 계속 진행하기 전에 처리해야 하는 예외는 하나만 발생시킬 수 있습니다.

사용자가 잘못된 목적지 주소와 차단하려는 언어가 포함된 이메일을 제출한다고 상상해 보십시오.잘못된 형식의 이메일 예외를 발생시킨 다음 문제를 해결하고 다시 제출한 후 잘못된 언어 예외를 발생시키나요?사용자 경험 관점에서 볼 때 모든 것을 한 번에 처리하는 것이 더 나은 방법입니다.

업데이트: 답변 결합

@홍옥:내 요점은 작업을 평가할 수 있다는 것입니다. 이 경우 이메일을 보내고 여러 가지 실패 이유를 다시 보낼 수 있습니다.예를 들어 "잘못된 이메일 주소", "빈 메시지 제목" 등이 있습니다.

예외를 제외하고는 한 가지 문제를 여과한 다음 사용자에게 두 번째 문제를 발견한 시점에 다시 제출하도록 요청하는 것으로 제한됩니다.이것은 정말 나쁜 UI 디자인입니다.

바퀴의 재발견..혹시.그러나 대부분의 애플리케이션은 사용자에게 가능한 최상의 정보를 제공하기 위해 전체 트랜잭션을 분석해야 합니다.첫 번째 오류로 인해 컴파일러가 중단되었다고 상상해 보십시오.그런 다음 오류를 수정하고 다시 컴파일을 누르면 다른 오류로 인해 다시 중지됩니다.엉덩이가 정말 아프네요.나에게는 이것이 바로 예외 발생의 문제이고 따라서 다른 메커니즘을 사용하겠다고 말한 이유입니다.

실제로 OO 방식은 아니지만 예외 유형이 적은 경향이 있습니다.대신에 예외를 분류하는 사용자 정의 예외에 열거형을 넣었습니다.대부분의 경우 파생 예외 유형에서 재정의하거나 사용자 정의할 수 있는 몇 가지 멤버를 보유하는 사용자 정의 기본 예외가 있습니다.

몇 달 전 나는 블로그에 올렸던 예외를 국제화하는 방법에 대한 아이디어입니다.여기에는 위에서 언급한 아이디어 중 일부가 포함됩니다.

예외를 찾는 코드 실행을 구별할 수 있지만 "catch 예외 유형 계층 구조 모드" 또는 "if(...) else...예외 코드 모드"에 의해 수행되는지 여부는 중요하지 않습니다.

하지만 라이브러리처럼 다른 사람이 사용할 소프트웨어를 개발하는 경우에는 자신의 예외 유형을 만들어서 다른 사람들이 자신의 소프트웨어가 일반 예외가 아닌 다른 예외를 던질 수 있다는 점을 알아채는 것이 유용하다고 생각합니다. 해결하세요.

라이브러리와 해당 메소드를 사용할 때 '예외'가 발생하면 항상 궁금합니다.이 예외의 원인은 무엇입니까?, 내 프로그램은 어떻게 반응해야 합니까?, javadoc이 있으면 원인이 설명될 수 있지만, 반드시 javadoc이 없거나 예외가 설명되지 않는 경우가 있습니다.WellChossenExceptionTypeName을 사용하면 너무 많은 오버헤드를 피할 수 있습니다.

이는 예외를 포착하는 코드가 예외를 구별해야 하는지 아니면 단지 예외를 사용하여 오류 페이지를 표시하는지에 따라 달라집니다.NullReference 예외와 호출 스택의 상위에 있는 사용자 정의 MailException을 구별해야 하는 경우 시간을 들여 작성하십시오.그러나 대부분의 프로그래머는 예외를 웹 페이지에 오류를 발생시키기 위한 수단으로 사용합니다.이 경우 새로운 예외를 작성하는 데 노력을 낭비하는 것뿐입니다.

난 그냥 지나갈 텐데

throw new exception("WhatCausedIt")

예외를 처리하려면 "WhatCausedIt" 대신 코드를 전달한 다음 스위치 문을 사용하여 다른 답변에 반응할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top