2014-10-23 2 views
2

Exception 인스턴스를 메서드 인수로 처리하는 디자인 패턴을 찾고 있습니다. 예외를 메서드 인수로 처리

질문에 약간의 문맥을 넣으려면, 내가 GWT를 사용하여 일반적으로 유사한 형태로 제공 다양한 비동기 처리기가 있어요 : 그래서

public interface AsyncCallback<T> { 

    void onFailure(Throwable caught); 

    void onSuccess(T result); 

} 

을의 onFailure 방법은 I가 필요 Throwable 인스턴스를 수신 핸들.

지금, 나는 물론 수 내 처리 코드에서 예를

  • ConstraintViolationException
  • TimeoutException
  • NoSuchElementException

, 나는이 방법으로받을 수있는 예외의 번호를 가지고 다음을 작성하십시오 :

void handleException(final Exception e) { 
    if(e instanceof TimeoutException) { 
     handleTimeout(); 
    } else if (e instanceof NoSuchElementException) { 
     handleInvalidElement(); 
    } else { 
     stopAndCatchFire(); 
    } 
} 

하지만 내 눈에는 아주 추해 보입니다. 큰 if..else if 체인과 instanceof의 과도한 사용은 피하는 것이 좋습니다.

나는 어쩌면 나는 다음과 같은 것을 사용하여 Exception을 처리 할 수 ​​ try...catch 구조를 사용할 수 있다고 생각 :

void handleException(final Exception e) { 
    try { 
     throw e; 
    } catch (TimeoutException te) { 
     handleTimeout(); 
    } catch (NoSuchElementException nsee) { 
     handleInvalidElement(); 
    } catch (Exception ex) { 
     stopAndCatchFire(); 
    } 
} 

을하지만 이것은 어떻게 든 남용처럼 보인다. 두 번째 접근법에 대한 단점이나 첫 번째 사례를 피하기 위해 사용할 수있는 다른 접근법을 알고 있습니까?

+1

두 번째는 확실히 더 나쁜 패턴입니다. 그것은 또한 매우 부적당하다. – djechlin

+0

두 번째 모델은 성능이 좋지 않지만 (비용의 대부분이 예외를 구축하기 때문에 첫 번째 모델만큼 비싸지는 않지만) 개념적으로보기 흉한 모델입니다. 당신은 예외 이름을 얻고 그것에 대해'switch'를 수행하는 것을 고려할 수 있습니다 (서브 클래스를 처리하지는 않지만). –

+0

@djechlin interesting. 왜 그게 더 나쁜 패턴이라고 생각하니? 두 번째 경우의 성능은 의심의 여지없이 가난합니다. –

답변

3

처리 할 예외 유형으로 keying 된 exceptionHandler 사전을 가질 수 없습니까? 예외가 발생하면 예외 유형 처리기에 대한 사전을 찾습니다.존재하는 경우에는 기본 처리기를 사용하지 않는 경우 처리기에 예외를 전달합니다. 내가 첫 글자를 대문자로하지 않는 기억하지만 (

void handleException(final Exception e) { 
    if (handlers.containsKey(e.getType()) 
    { 
     handlers[e.getType()].handle(e); 
    } 
    else 
    { 
     defaultHandler.handle(e); 
    } 
} 

내 자바 약간 녹슨, 그래서 예는 C-삼각 돛하지만 번역 정도로 간단해야한다 :

그래서 핸들러는 다음과 같이된다 모든 것의 :))

이 접근법은 새로운 핸들러를 간단하게 추가 할 수 있다는 장점이 있습니다.

그러나 각 하위 유형을 명시 적으로 등록해야하므로 하위 유형에 대해 동일한 핸들러가있는 경우 문제가 발생합니다.

는 단순히 예외를 처리 할 수 ​​있는지 여부에 대한 결정을 할 책임이 각 핸들러를 만들어이 문제를 해결하기 위해 :

public interface ExceptionHandler 
{ 
    bool canHandle(Exception e); 
    void handle(Exception e) 
} 

그럼 그냥 목록에서 각각 처리 할 수있는 하나가 요청하는 반복 처리를 핸들러를 넣어 현재의 예외와 그것을 찾을 수있을 때, 그것을 처리 할 수 ​​있습니다.

+0

이제 아주 영리한 생각입니다! 내가 조사하고 너에게 돌아올거야. –

+0

이 방법을 사용하면 특정 예외의 각 하위 유형에 대한 핸들러가 필요하다는 점을 명심하십시오. 어떤 문제 일 수도 있고 아닐 수도 있습니다. – StuPointerException

+0

@StuPointerException 예, 각 처리기가 'canHandle' 메소드를 가지고있는 핸들러에 Spring 사용 패턴을 사용하려고합니다. 이것은 _ 하위 클래스 문제를 해결할 수 있어야합니다. –

1

하지만 내 눈에는 매우 추해 보입니다. 거대한 if..else는 instanceof의 과도한 사용과 결합 된 체인이 피해야하는 것으로 보입니다.

동의하지 않습니다. 이 코드 스 니펫은 의도 된대로 두 언어 구문을 정확하게 사용한다고 생각합니다. 코드가 관리하기 어렵게된다면 (너무 많은 절)이 방법의 특성보다는 오류 처리 방법에 전반적으로 질문해야합니다. 그 단계에서 AOP를 고려할 수 있습니다. 반면에, 두 번째 방법은 끔찍한

; 예외)에

+0

점 찍었습니다. AOP는 옵션이 아닙니다. GWT 코드이기 때문에 생각하지 않습니다. 그 점을 의미합니다. ** ** 정말 두렵습니다. –

+0

onFailure 메서드는 간단해야합니다. onFailure 메서드에 논리를 추가하면 실제로 호출 된 서비스에 속하는 스프레드 논리가 클라이언트 로직을 유지하기가 더 어려워 짐 – Gerbrand

+0

개인적으로 오류 처리 기능을 한 곳으로 캡슐화 했으므로 유지 관리가 더 쉬울 것입니다. 분명히 그것이 신 오브젝트가 될 위험이 있습니다. – StuPointerException

0

제어 흐름이 방지되어야하고, 확실히 onFailure에이어야한다. onFailure 메소드는 가능한 한 간단해야합니다.

예외 사례를 처리하기 위해 비동기 적으로 실행되는 코드를 수정하십시오. ElementNotFound-exception은 엘리먼트가 무엇인가하기 전에 존재 하는지를 체크함으로써 처리 될 수있다. 타임 아웃 예외는 try ... catch 블록에 의해 타임 아웃 (웹 서비스 또는 무언가를 호출) 할 수있는 코드를 둘러 쌈으로써 처리 될 수 있습니다. 그런 다음 result-type T를 확장하여 시간 초과가 발생했거나 필요한 경우 요소를 찾을 수 없다는 추가 정보를 포함시킵니다.

+1

나는 이것이 예외에 기반한 예제 제어 흐름이라고 생각하지 않지만, 첫 번째 진술 전체에 동의합니다. 오히려 조정 된 예외 처리기입니다. hich는 종종 좋은 것입니다. – StuPointerException

1

함수 내에서 예외 내에있는 if 문을 처리하면 더 우아하게 만들 수 있습니다.

void handleException(Exception e){ 
    handleOne(e) 
    handleTwo(e) 
    ... 
} 

더 예쁘게 보입니다. 물론 모든 함수는 항상 호출되지만 첫 번째 행은 if 문입니다. 유사 콘텐츠가 있습니다 (예 : 당신의 핸들 함수를 구아바 함수 객체로 만들고,리스트에 넣고, "true"를 반환 할 때까지 반복합니다. 뭔가 같은 :

public class handlerOne implements Function<Exception, Boolean> { 

    Boolean apply(Exception input) {   
     return handlerOne(); 
    } 
} 

그런 다음 핸들 기능이 될 수있는 일이 같은 :

void handleException(Exception e){ 
    list<Function<Exception, Boolean> list = Object.getHandlers(); //store your handlers somewhere 
    for(Function<Exception, Boolean> f : list){ 
     if(f.apply(e)){ 
      break 
     } 
    } 
} 

그런 식으로 당신이라고 작동 하나의 핸들러를 보장하고, 당신이 순서를 변경하여 순서를 제어 할 수 list iterator는 그것들을 순서대로 돌려주기 때문에.

관련 문제