2010-02-11 3 views
17

null 값을 반환하거나 API 메소드에서 예외를 throw하는 것이 더 좋습니까?java api design - NULL 또는 예외

null을 반환하면 되돌릴 수없는 null 검사가 필요하며 반환을 확인하지 않으면 주요 품질 문제가 발생합니다.

예외를 throw하면 사용자가 잘못된 조건을 작성하도록 강요되지만 Java 예외가 발생하여 호출자 코드가이를 처리하도록 강제하기 때문에 일반적으로 사용자 정의 예외를 사용하는 것은 나쁜 생각 일 수 있습니다 (특히 Java의 경우).

소리와 실용적인 조언이 있으십니까?

+0

Null 개체 패턴을 알고 있습니까? http://en.wikipedia.org/wiki/Null_Object_pattern –

답변

5

나는 대답이 전적으로 당신의 응용 프로그램의 문맥에 달렸다고 생각하며, 프로그래머 오류 대 "예외적 인 상황"이라고 생각하는 것. XML 파서를 작성하는 경우

예를 들어, 같은 메소드를 구현하도록 선택할 수 있습니다 :이 방법은 않고도, 논리의 단일 블록의 코드를 분석하여 메시지를 구현할 수

/** 
* Returns first child element with matching element name or else 
* throws an exception. Will never return null. 
*/ 
Element getMandatoryChildElement(Element parent, String elementName) 
throws MissingElementException; 

...로 각 요소 또는 속성을 검색 한 후 메시지가 올바른지 확인합니다.

+0

@Adamski - 나는 이것을 좋아한다. 그러나 호출자가 이미 Exception을 던지고 있다면,이 예외는 무시 될 것입니다. 예 : 호출자가 이미 Exception을 throw하기 때문에 NumberFormatException이 처리되지 않는 것을 보았습니다. 따라서 예외가 발생하지 않아야한다는 결론을 내릴 수 있습니까? –

+0

나는 엘리먼트가 발견되지 않으면, 호출자는 처음부터 메소드를 호출해서는 안된다. check 메소드를 사용할 수 있으므로 if (hasElement ('test')) getMandatoryChildElement ('test');를 작성할 수 있습니다. try-catch-try 다음 메소드의 코드보다 훨씬 낫다. '로드 파일'방법은 어떻게 작성 하시겠습니까? –

+0

@disown : 문제는 API에서 메소드를 제공하고 있습니다. 당신은 사용자를 알지 못하기 때문에 그가 나쁜 일을하지 않을 것이라는 것을 확실히하고 그가 틀린 것을 말할 때해야합니다. @ srini.venigalla : 발신자가 이미 Exception을 throw하면 조만간 어딘가에 잡을 것입니다. –

1

정말 상황을 어떻게 처리 할 것인가에 달려 있습니다. 정말로 에러 조건 인 경우는 예외를 슬로우합니다. null가 받아 들일 수있는 출력이면, 그것을 문서화 해, 유저가 처리하도록 (듯이)합니다.

6

null이 허용 가능한 반환 값일 경우 (즉, 오류 케이스가 아닌 올바른 입력으로 인해 발생할 수 있음) null; 그렇지 않으면 예외를 던집니다.

발신자가 예외를 처리해야하기 때문에 확인 된 예외가 좋지 않을 수 있다는 내용을 전혀 이해하지 못합니다. 이는 확인 된 예외의 전체적인 부분입니다. 제대로 처리되지 않고 코드로 전파되는 오류 조건을 방지합니다.

+0

@danben - 나는 6 개의 커스텀 예외를 던지는 API를 정말로 싫어하고 관련없는 예외 핸들러 스택을 추가해야합니다. 그 자체는 문제가 아니지만 API가 새로운 예외를 추가하면 모든 업스트림 체인을 업데이트해야합니다. 나는 그것이 필요한 것이거나 좋은 것 모두를 이해할 수 있지만 따라야 할 분명한 규칙을 찾고있었습니다. –

+1

@ srini.venigalla - 일반적으로 5 분의 1이 너무 많습니다. 어떤 ** 커스텀 ** 예외를 반드시 가질 필요는 없다는 것을 명심하라 - 당신은 당신의 필요에 맞는'IllegalArgumentException' 또는 뭔가를 던질 수있다. – danben

+0

AxisException, SoapException 또는 WhateverException과 같은 사용자 지정 검사 예외를 사용하면 어떤 이점이 있습니까? 당신이 추론 할 수있는 것은 stacktrace에서 알았던 lib의 예외가 있다는 것입니다. 범용 오류 처리를 원할 경우 클라이언트에 쉽게 추가됩니다. –

1

예기치 않은 내부 라이브러리 오류가있는 경우 런타임 예외가 전파됩니다. 라이브러리 코드에 버그가 있으면 클라이언트가 중단 될 것으로 예상됩니다. 라이브러리의 버그를 수정하십시오. 모든 것을 잡아 내지 않고 라이브러리 관련 예외를 반환하지 마십시오. 아무런 효과가 없습니다.

가끔씩 잘못 될 것으로 예상되는 경우 API에이를 빌드하십시오. 이는 정상적인 프로그램 흐름에 예외를 사용하지 않아야한다는 원칙에 기반합니다. 예를 들어

:

ProcessResult performLibraryTask(TaskSpecification ts) 

당신이 ProcessResult을 가질 수 있습니다이 방법은 오류 상태 표시 :

ProcessResult result = performLibraryTask(new FindSmurfsTaskSpecification(SmurfColor.BLUE)); 
if (result.failed()) { 
    throw new RuntimeException(result.error()); 
} 

이러한 접근 방식은 NULL을 반환 방식과 유사합니다,하지만 당신은 다시 더 많은 정보를 보낼 수 있습니다 고객.

편집 : 합의 된 프로토콜을 준수하지 않는, 당신은 당신이 문서화 할 수 런타임 오류를 던질 수있는 상호 작용을위한

. 예를 들면 다음과 같습니다.

if (currentPeriod().equals(SmurfColor.BLUE) && SmurfColor.GREEN.equals(taskSpecification.getSmurfColor()) { 
    throw new IllegalStateException("Cannot search for green smurfs during blue period, invalid request"); 
} 

계약 위반으로 인한 상호 작용이 원인이며 이로 인해 발생하지 않을 수 있습니다.

+0

나는 그것을 좋아하지만, null return과 같은이 접근법은 호출자의 자비를 요구한다. –

+0

동의 함. 정상적인 사용 중에 발생할 수있는 오류에 대한 제한을 설정해야하며 예외가 아닌 예외로 모델링해야합니다. 코딩 오류 (계약 위반) 또는 정상적인 사용 (메모리 부족, 널 포인터 역 참조)과 같은 상황에서 발생하지 않는 사항에 대해서는 예외를 사용해야합니다. –

2

내가 예를 들어, 데이터베이스 예에서 무언가를 가져 오기 "하는 getXXX"메소드에 null을 반환하는 경향이있다 : 당신이 필요로하는 경우 나,

를 null를 돌려 그러나하는 사용자 getUserByName (문자열 이름은) OK 무엇인지 예 : getDatabaseConnection()은 항상 연결을 반환해야하며 null을 반환하지 않아야합니다.

그리고 컬렉션이나 배열을 반환하는 메서드의 경우 절대 null을 반환하지 마십시오. 빈 컬렉션/배열을 대신 반환하십시오.

+0

나는 보통 null을 반환 할 수있는 메소드에 대해서는 findXXX를, 그렇지 않은 경우에는 getXXX를 사용한다. –

+0

@disown - 이것은 비표준이되고 Java Bean 라이브러리 및 코드의 사용을 허용하지 않습니다. – Robin

+0

@Robin : 데이터베이스 API를 작성하고 계신가요? Javabeans는 간단한 DTO 유형 클래스 용입니다. 당신은 진실하게 자바 bean spec에 따라 당신의 모든 메소드의 이름을 지정하지 않습니까? –

1

A가 다른 것에 동의하면 null이 허용 가능한 반환 값이면 반환하고 그렇지 않으면 반환하지 않습니다.

내가 추가하고 싶은 것은 체크 된 예외와 체크되지 않은 예외를 구별 할 수 있다는 것입니다. 어떤 경우에는 검사되지 않은 예외를 사용하는 것이 좋습니다. 어쨌든 API 사용자는 예외 상황을 처리하지 못할 수도 있습니다. Spring Framework는 체크되지 않은 예외를 매우 자주 사용하기 때문에 코드를 읽기 쉽게 만들지 만 가끔 오류를 추적하기는 어렵습니다.

6

Josh Bloch는 null 값 대신 빈 개체 또는 "단위"개체를 반환 할 것을 권장합니다. 유용한 Java tidbits에 대해서는 Effective Java을 확인하십시오.

3

Practial API Design에서 저자는 null 값 (see p.24)을 반환하지 말 것을 조언합니다.

그의 주요 포인트는 null 값과 더 많은 문서에 대한 수표의 확산으로 연결된다는 것입니다.

필드 (T. Hoare)의 기관에서 "Null References: The Billion Dollar Mistake"을 읽을 것을 적극 권장합니다.

+0

+1 - 당신 만이 null 문제와 memcpy 문제를 고치는 데 소비 된 시간에 가치를 둘 수 있다면 ... –

+0

억 달러 : P – Jeriko

+0

@Jeriko 당신 말이 맞아요. 결정된. – ewernli

4

내 요점은 반환 유형은 수집 또는 배열 때

이제까지 NULL을 반환하지 마십시오 것입니다. 반환 값이없는 경우 빈 콜렉션 또는 빈 배열을 반환합니다.

이렇게하면 null 확인이 필요하지 않습니다.

좋은 연습 :

public List<String> getStudentList() 
{ 
    int count = getStudetCount(); 
    List<String> studentList = new ArrayList<String>(count); 
    //Populate studentList logic 
    return studentList; 
} 

나쁜 연습 :. 아래 코드를 쓰지 마십시오.

public List<String> getStudentList() 
{ 
    int count = getStudetCount(); 
    if(count == 0) 
    { 
     return null; 
    } 
    //Populate studentList logic 
    return studentList; 
} 
+1

'studentList'가 불변이라고 가정하면 :'getStudentCount()'에 의해 반환 된'count'를 검사하고, 0 인 경우'Collections.emptyList()'를 사용하는 것이 좋습니다. 이것은 잠재적 인 최적화를 허용합니다 (즉, 매번 반환되는 캐시 된 빈 목록을 갖는). 'count'가 0이 아닌 경우, 반환 된리스트를'Collections.unmodifiableList (studentList)'래퍼로 래핑 해, 실수로 변경되지 않게합니다. – cdmckay

0

일반적으로 JDK 내에서 유사한 예를 봅니다.

접근 자의 경우 Null을 사용하는 것이 좋습니다.

누락되거나 알 수없는 데이터를 나타내는 데 Null을 사용해야합니다.

그 밖의 모든 것에 대해서는 일반적으로 처리 오류를 나타냅니다.

이제 런타임과 컴파일 시간의 두 가지 옵션이 있습니다. 다음은 유추를 찾는 방법에 대한 예입니다.

ArrayIndexOutOfBoundException에서 예제를 추출 할 수 있습니다. 요소에 액세스하거나 변형하는 것은 매우 일반적인 작업입니다.

확인 된 경우 소비 코드가 매우 어수선하게됩니다. 또한 일반적으로 개발자는 ArrayIndexOutOfBounException으로 이어질 수있는 상황을 인식하는 경향이 있으며 좋은 코드를 작성하여이를 피할 수 있습니다.

flipside에서 외부 종속성 (파일 누락 또는 충분한 권한 없음)으로 인해 파일을 여는 코드 조각이 있고 프로그램의 실수에 뿌리를두고 있지 않은 경우에는 좋은 생각입니다 예외를 확인했습니다.