검색 메소드가 'null'을 리턴하거나 리턴 값을 생성 할 수없는 경우 예외를 발생시켜야합니까? [닫은]
객체가 발견되면 반환 해야하는 메소드가 있습니다.
찾을 수 없으면 다음을 수행해야합니다.
- null을 돌려 준다
- 예외를 던지다
- 다른
항상 값을 찾을 것으로 예상되면 누락 된 경우 예외를 처리하십시오. 예외는 문제가 있음을 의미합니다.
값이 없거나 존재할 수 있고 둘 다 응용 프로그램 논리에 유효하면 널을 리턴합니다.
더 중요 : 코드의 다른 곳에서 무엇을합니까? 일관성이 중요합니다.
실제로 오류 인 경우에만 예외를 처리하십시오. 객체가 존재하지 않을 것으로 예상되는 경우 null을 반환합니다.
그렇지 않으면 그것은 선호의 문제입니다.
일반적으로 메소드가 항상 오브젝트를 리턴해야하는 경우 예외와 함께 진행하십시오. 가끔 null을 예상하고 특정 방식으로 처리하려는 경우 null로 이동하십시오.
무엇을 하든지 세 번째 옵션 인 "WTF"라는 문자열을 반환하는 것이 좋습니다.
null이 오류를 나타내지 않으면 null을 반환합니다.
null이 항상 오류이면 예외를 throw합니다.
널이 예외 인 경우 두 루틴을 코딩하십시오. 한 루틴은 예외를 발생시키고 다른 루틴은 출력 매개 변수로 오브젝트를 리턴하고 오브젝트를 찾을 수없는 경우 false를 리턴하는 부울 테스트 루틴입니다.
Try 루틴을 잘못 사용하는 것은 어렵습니다. null을 확인하는 것을 잊어 버리는 것은 정말 쉽습니다.
따라서 null이 오류이면 그냥 작성하십시오.
object o = FindObject();
null이 오류가 아닌 경우 다음과 같은 코드를 작성할 수 있습니다.
if (TryFindObject(out object o)
// Do something with o
else
// o was not found
방금 이전에 언급 한 옵션을 요약하여 새로운 옵션을 던져보고 싶었습니다.
- null을 돌려 준다
- 예외를 던지다
- null 객체 패턴을 사용
- 부울 매개 변수를 메소드에 제공하여 호출자가 예외를 던지 길 원하는지 선택할 수 있습니다.
- 추가 매개 변수를 제공하여 호출자가 값을 찾지 못하면 다시 얻는 값을 설정할 수 있습니다
또는 다음 옵션을 결합 할 수 있습니다.
호출자가 갈 길을 결정할 수 있도록 오버로드 된 getter 버전을 여러 개 제공하십시오. 대부분의 경우 첫 번째 알고리즘 만 검색 알고리즘을 구현하고 다른 알고리즘은 첫 번째 알고리즘 만 둘러 쌉니다.
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
하나의 구현 만 제공하기로 선택하더라도 이와 같은 명명 규칙을 사용하여 계약을 명확하게하고 다른 구현도 추가하기로 결정하는 데 도움이 될 수 있습니다.
당신은 그것을 과도하게 사용해서는 안되지만, 많은 다른 오류 처리 규칙을 가진 수백 가지 응용 프로그램에서 사용할 도우미 클래스를 작성할 때 특히 도움이 될 수 있습니다.
널 오브젝트 패턴을 사용하거나 예외를 던지십시오.
사용중인 API와 일관성을 유지하십시오.
"물건을 찾을 수없는 예외적 인 경우"입니까? 프로그램의 정상적인 과정에서 발생할 것으로 예상되는 경우 예외가 발생하지 않아야합니다 (예외 동작이 아니기 때문에).
짧은 버전 : 예외 동작을 사용하여 프로그램의 정상적인 제어 흐름을 처리하지 말고 예외적 인 동작을 처리하십시오.
앨런
귀하의 언어와 코드가 LBYL (도약하기 전에 살펴보기) 또는 EAFP (허가보다 용서를 구하기 쉬운)로 홍보하는지에 따라 다릅니다.
LBYL은 값을 확인해야하므로 null을 반환합니다.
EAFP는 작업을 시도하고 실패했는지 확인합니다 (예외 발생).
위의 내용에 동의하지만 예외 / 오류 조건에는 예외를 사용해야하며 검사를 사용할 때 null을 반환하는 것이 가장 좋습니다.
Python의 EAFP 및 LBYL :
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( 웹 아카이브 )
예외를 던질 때의 장점 :
- 호출 코드의보다 깨끗한 제어 흐름. null을 확인하면 try / catch에서 기본적으로 처리되는 조건부 분기가 삽입됩니다. null 확인은 무엇을 확인하고 있는지를 나타내지 않습니다. 예상 오류를 찾고 있기 때문에 null을 확인하고 있습니까? 아니면 null을 확인하여 다운 체인에서 더 이상 전달하지 않습니다. ?
- "널"의 의미에 대한 모호성을 제거합니다. 널을 오류를 나타내거나 실제로 값에 저장된 것을 널입니까? 그 결정을 근거로 단 하나의 말이있을 때는 말하기 어렵다.
- 응용 프로그램에서 메서드 동작 간의 일관성이 향상되었습니다. 예외는 일반적으로 메소드 시그니처에 노출되므로 애플리케이션의 메소드가 처리해야하는 에지 사례와 애플리케이션이 예측 가능한 방식으로 반응 할 수있는 정보를 더 잘 이해할 수 있습니다.
예제에 대한 자세한 설명은 http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/을 참조하십시오.
예외는 계약에 의한 설계와 관련이 있습니다.
객체의 인터페이스는 실제로 두 객체 간의 계약이므로 호출자가 계약을 충족해야합니다. 그렇지 않으면 수신자가 예외로 실패 할 수 있습니다. 가능한 두 가지 계약이 있습니다
1) 모든 입력 방법은 유효합니다.이 경우 객체를 찾을 수 없으면 null을 반환해야합니다.
2) 일부 입력 만 유효합니다. 즉, 찾은 객체가됩니다. 이 경우 발신자가 입력이 올바른지 확인할 수있는 두 번째 방법을 제공해야합니다. 예를 들어
is_present(key)
find(key) throws Exception
두 번째 계약의 두 가지 방법을 모두 제공하는 경우에만 예외를 발견 할 수 있습니다.
나는 null을 반환하고 호출자를 사용하여 적절하게 처리하는 것을 선호합니다. (더 나은 단어가없는 경우) 예외는 내가 절대적으로 '확실한'경우이 방법은 객체를 반환한다는 것입니다. 이 경우 실패는 예외적이어야하며 던져야합니다.
개체를 찾을 수 없음을 의미합니다.
정상 상태 인 경우 null을 반환합니다. 이것은 때때로 발생할 수있는 일이므로 발신자가 확인해야합니다.
오류 인 경우 예외를 throw하면 호출자가 누락 된 개체의 오류 조건으로 수행 할 작업을 결정해야합니다.
대부분의 사람들은 일반적으로 예외가 발생했을 때 예외를 사용하는 것이 좋습니다.
여기 몇 가지 제안이 더 있습니다.
컬렉션을 반환하는 경우 null 반환을 피하고 빈 컬렉션을 반환하면 null 확인없이 열거를 쉽게 처리 할 수 있습니다.
여러 .NET API는 thrownOnError 매개 변수의 패턴을 사용하여 호출자가 실제로 예외 상황인지 여부 또는 객체를 찾을 수 없는지 여부를 선택할 수 있습니다. Type.GetType이 이에 대한 예입니다. BCL의 또 다른 일반적인 패턴은 부울이 리턴되고 값이 출력 매개 변수를 통해 전달되는 TryGet 패턴입니다.
경우에 따라 기본 설정이거나 동작이없는 버전 일 수있는 Null 개체 패턴을 고려할 수도 있습니다. 핵심은 코드 기반에서 널 검사를 피하는 것입니다. 자세한 내용은 여기를 참조하십시오 http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
일부 기능에서 매개 변수를 추가합니다.
..., bool verify = true)
True는 throw를 의미하고 false는 일부 오류 반환 값을 반환합니다. 이런 식으로이 기능을 사용하는 사람은 두 가지 옵션이 있습니다. 오류 처리를 잊어 버린 사람들을 위해 기본값은 true입니다.
예외를 발생시키는 대신 널을 리턴하고 API 문서에서 널 리턴 값의 가능성을 명확하게 문서화하십시오. 호출 코드가 API를 존중하지 않고 null 경우를 확인하면 어쨌든 일종의 "널 포인터 예외"가 발생합니다. :)
C ++에서는 객체를 찾는 메소드를 설정하는 3 가지 맛을 생각할 수 있습니다.
옵션 A
Object *findObject(Key &key);
객체를 찾을 수 없으면 null을 반환합니다. 좋고 간단합니다. 나는 이것과 함께 갈 것이다. 아래의 대안은 매개 변수를 싫어하는 사람들을위한 것입니다.
옵션 B
void findObject(Key &key, Object &found);
객체를받을 변수에 대한 참조를 전달하십시오. 객체를 찾을 수 없을 때 메소드에서 예외가 발생했습니다. 이 규칙은 실제로 객체를 찾을 수 없을 것으로 예상되는 경우 더 적합 할 수 있습니다. 따라서 예기치 않은 경우임을 나타내는 예외를 발생시킵니다.
옵션 C
bool findObject(Key &key, Object &found);
객체를 찾을 수 없으면이 메소드는 false를 리턴합니다. 옵션 A에 비해이 방법의 장점은 한 번의 명확한 단계로 오류 사례를 확인할 수 있다는 것입니다.
if (!findObject(myKey, myObj)) { ...
null이 예외적 인 행동으로 간주되지 않는 경우에만 참조하십시오. 나는 try 메서드를 사용하고 있습니다. 여기에서 언급 된 것처럼 "책을 읽거나"도약하기 전에 볼 필요가 없습니다.
그래서 기본적으로:
bool TryFindObject(RequestParam request, out ResponseParam response)
이는 사용자의 코드도 명확하다는 것을 의미합니다
...
if(TryFindObject(request, out response)
{
handleSuccess(response)
}
else
{
handleFailure()
}
...
클라이언트 코드가 found와 not found의 차이점을 아는 것이 중요하고 이것이 일상적인 동작으로 간주되는 경우 null을 반환하는 것이 가장 좋습니다. 그러면 클라이언트 코드가 수행 할 작업을 결정할 수 있습니다.
일반적으로 null을 반환해야합니다. 메소드를 호출하는 코드는 예외를 던지거나 다른 것을 시도할지 여부를 결정해야합니다.
또는 옵션을 반환
옵션은 기본적으로 클라이언트가 부스 케이스를 처리하도록하는 컨테이너 클래스입니다. 스칼라는이 개념을 가지고 있습니다. API를 찾으십시오.
그런 다음이 객체에 T getOrElse (T valueIfNull)과 같은 메소드가 있습니다. 그러면 찾은 객체를 반환하거나 클라이언트가 지정하는 대안을 반환합니다.
불행히도 JDK는 일관성이 없습니다. 자원 번들에서 기존 키가 아닌 키에 액세스하려고하면 예외가 발생하지 않으며 map에서 값을 요청하면 존재하지 않으면 null이됩니다. 따라서 찾은 값이 null 일 수 있으면 승자 답변을 다음과 같이 변경하고 찾지 못하면 예외를 발생시키고 그렇지 않으면 null을 반환합니다. 따라서 가치를 찾을 수없는 이유를 알아야 할 경우 항상 예외를 제기하십시오.
객체에 대한 참조 를 반환하는 한 NULL을 반환하는 것이 좋습니다.
그러나 전체 피의 것을 돌려주는 경우 (C ++에서와 같이 : 'return & blah;'(또는 'blah'는 포인터)가 아닌 'return blah;'인 경우) NULL을 반환 할 수 없습니다. 이 경우 예외를 던지거나 성공 플래그가 설정되지 않은 빈 개체를 반환하면 문제에 어떻게 접근 할 수 있습니까?
예외 처리에서 오버 헤드를 언급 한 사람은 없다고 생각하지 마십시오. 실제 앱 종료 또는 프로세스 중지 이벤트가 아닌 한 예외를로드하고 처리하는 데 추가 리소스가 필요합니다. 호출 환경이 적절하다고 해석 할 수있는 가치.
나는 여기에 합의 인 것처럼 보인다 ( "찾을 수 없음"이 정상적인 결과 일 경우 null을 반환하거나 상황의 의미가 객체를 항상 찾도록 요구하면 예외를 던진다).
그러나 특정 상황에 따라 세 번째 가능성이 있습니다. 메소드는 "찾을 수 없음"조건에서 일종의 기본 오브젝트를 리턴 할 수 있으므로 호출 코드가 널 점검이나 예외 포착없이 항상 유효한 오브젝트를 수신 할 수 있습니다.
null을 반환하면 예외는 정확히 다음과 같습니다. 코드에서 예상하지 못한 작업입니다.
예외가되어야합니다 뛰어난 . null 을 돌려주는 것이 유효한 경우는 null를 돌려줍니다 .
null 반환을 선호합니다-
발신자가 확인하지 않고 사용하면 예외가 바로 발생합니다.
발신자가 실제로 사용하지 않으면 try
/ catch
블록에 세금을 부과하지 마십시오
메서드가 컬렉션을 반환하면 빈 컬렉션 (위와 같이)을 반환합니다. 그러나 Collections.EMPTY_LIST 등은 사용하지 마십시오! (자바의 경우)
메소드가 단일 오브젝트를 검색하는 경우 몇 가지 옵션이 있습니다.
- 메소드가 항상 결과를 찾아야하고 객체를 찾지 않는 실제 예외 사례 인 경우 예외를 처리해야합니다 (Java : 점검되지 않은 예외를 참조하십시오).
- (Java에만 해당) 메소드가 확인 된 예외를 처리하는 것을 허용 할 수있는 경우 프로젝트 특정 ObjectNotFoundException 등을 처리하십시오. 이 경우 예외 처리를 잊어 버린 경우 컴파일러에서 알려줍니다. (이것은 Java에서 찾을 수없는 항목을 처리하는 것이 좋습니다.)
- 실제로 괜찮다고 말하면 객체를 찾을 수없고 메소드 이름이 findBookForAuthorOrReturnNull (..)과 같으면 null을 반환 할 수 있습니다. 이 경우입니다 강력 널 확인없이 정적 수표 또는 컴파일러 검사, 결과의 역 참조 느릅 나무 방지의 일종을 사용하는 recomminded. Java의 경우 예를 들어 가능합니다. FindBugs ( http://findbugs.sourceforge.net/manual/annotations.html의 DefaultAnnotation 참조 ) 또는 IntelliJ-Checking.
널을 리턴하기로 결정한 경우주의하십시오. 프로젝트의 유일한 프로그래머가 아니라면 런타임에 NullPointerExceptions (Java 또는 다른 언어로 된)을 얻을 수 있습니다! 따라서 컴파일 타임에 확인되지 않은 null을 반환하지 마십시오.
라이브러리 또는 예외를 발생시키는 다른 클래스를 사용하는 경우 다시 던져야 합니다. 다음은 예입니다. Example2.java는 라이브러리와 유사하며 Example.java는 오브젝트를 사용합니다. Main.java는이 예외를 처리하는 예제입니다. 호출 측에서 사용자에게 의미있는 메시지와 (필요한 경우) 스택 추적을 표시해야합니다.
Main.java
public class Main {
public static void main(String[] args) {
Example example = new Example();
try {
Example2 obj = example.doExample();
if(obj == null){
System.out.println("Hey object is null!");
}
} catch (Exception e) {
System.out.println("Congratulations, you caught the exception!");
System.out.println("Here is stack trace:");
e.printStackTrace();
}
}
}
Example.java
/**
* Example.java
* @author Seval
* @date 10/22/2014
*/
public class Example {
/**
* Returns Example2 object
* If there is no Example2 object, throws exception
*
* @return obj Example2
* @throws Exception
*/
public Example2 doExample() throws Exception {
try {
// Get the object
Example2 obj = new Example2();
return obj;
} catch (Exception e) {
// Log the exception and rethrow
// Log.logException(e);
throw e;
}
}
}
Example2.java
/**
* Example2.java
* @author Seval
*
*/
public class Example2 {
/**
* Constructor of Example2
* @throws Exception
*/
public Example2() throws Exception{
throw new Exception("Please set the \"obj\"");
}
}
실제로 객체를 찾을 지 여부에 따라 다릅니다. 당신이 생각의 학교를 따르면, 예외가 뭔가를 나타내는 데 사용되어야한다는 예외가 발생했습니다.
- 발견 된 개체; 객체 반환
- 개체를 찾을 수 없습니다. 예외를 던지다
그렇지 않으면 null을 반환합니다.
'Programming' 카테고리의 다른 글
포인터 "역 참조"는 무엇을 의미합니까? (0) | 2020.02.13 |
---|---|
매직 넘버는 무엇이며 왜 나쁜가요? (0) | 2020.02.13 |
JavaScript에서 특정 색인의 문자를 바꾸려면 어떻게해야합니까? (0) | 2020.02.13 |
HTML“no-js”클래스의 목적은 무엇입니까? (0) | 2020.02.12 |
파이썬에서 무한한 숫자를 어떻게 나타낼 수 있습니까? (0) | 2020.02.12 |