객체를 찾으면 반환 해야하는 메소드가 있습니다.
찾을 수 없으면 다음을 수행해야합니다.
- null을 돌려 준다
- 예외를 던지다
- 다른
객체를 찾으면 반환 해야하는 메소드가 있습니다.
찾을 수 없으면 다음을 수행해야합니다.
답변:
항상 값을 찾을 것으로 예상되면 누락 된 경우 예외를 처리하십시오. 예외는 문제가 있음을 의미합니다.
값이 없거나 존재할 수 있고 둘 다 응용 프로그램 논리에 유효하면 널을 리턴합니다.
더 중요 : 코드의 다른 곳에서 무엇을합니까? 일관성이 중요합니다.
GetPersonById(25)
그 사람이 삭제되었지만 GetPeopleByHairColor("red")
빈 결과를 반환하면 던집니다 . 그래서 매개 변수는 기대에 대해 뭔가를 말합니다.
실제로 오류 인 경우에만 예외를 처리하십시오. 객체가 존재하지 않을 것으로 예상되는 경우 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
find
하고 findOrFail
Laravel 웅변에서
TryFindObject
방법 에서 반환되는 다중 속성 객체를 정의하는 것이 답이 아니 겠습니까? 튜플은 여러 값을 캡슐화하는 객체를 정의하는 데 시간을 들이고 싶지 않은 프로그래머에게는 게으른 패러다임처럼 보입니다. 그것은 본질적으로 모든 튜플이 어쨌든 핵심입니다.
방금 이전에 언급 한 옵션을 요약하여 새로운 옵션을 던져보고 싶었습니다.
또는 다음 옵션을 결합 할 수 있습니다.
호출자가 갈 길을 결정할 수 있도록 오버로드 된 getter 버전을 여러 개 제공하십시오. 대부분의 경우 첫 번째 알고리즘 만 검색 알고리즘을 구현하고 다른 알고리즘은 첫 번째 알고리즘 만 둘러 쌉니다.
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
하나의 구현 만 제공하기로 선택한 경우에도 이와 같은 명명 규칙을 사용하여 계약을 명확하게하고 다른 구현도 추가하기로 결정할 때 도움이 될 수 있습니다.
당신은 그것을 과도하게 사용해서는 안되지만, 많은 다른 오류 처리 규칙을 가진 수백 개의 다른 응용 프로그램에서 사용할 도우미 클래스를 작성할 때 특히 도움이 될 수 있습니다.
Expected<T> findObject(String)
경우 Expected<T>
기능이있다 orNull()
, orThrow()
, orSupplied(Supplier<T> supplier)
, orDefault(T default)
. 이것은 오류 처리로부터 데이터를 얻는 것을 추상화합니다.
널 오브젝트 패턴을 사용하거나 예외를 던지십시오.
Person somePerson = personRepository.find("does-not-exist");
이 메소드가 ID의 null 객체를 반환한다고 가정 해 봅시다 does-not-exist
. 그렇다면 올바른 행동은 somePerson.getAge()
무엇입니까? 지금은 null 개체 패턴이 엔티티 조회에 적합한 솔루션이라고 아직 확신하지 않습니다.
예외를 던질 때의 장점 :
예제에 대한 자세한 설명은 http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/을 참조하십시오.
귀하의 언어와 코드가 LBYL (도약하기 전에) 또는 EAFP (허가보다 용서를 구하기 쉬운)로 홍보하는지에 따라 다릅니다.
LBYL은 값을 확인해야한다고 말합니다 (그래서 null을 반환)
한다고 EAFP는 작업을 시도하고 실패했는지 확인합니다 (예외 발생).
예외입니다. 예외 / 오류 조건에는 예외를 사용해야하며 검사를 사용할 때는 null을 반환하는 것이 가장 좋습니다.
Python의 EAFP 및 LBYL :
http://mail.python.org/pipermail/python-list/2003-May/205182.html
( 웹 아카이브 )
예외는 계약에 의한 설계와 관련이 있습니다.
객체의 인터페이스는 실제로 두 객체 간의 계약이므로 호출자가 계약을 충족해야합니다. 그렇지 않으면 수신자가 예외로 실패 할 수 있습니다. 가능한 두 가지 계약이 있습니다
1) 모든 입력 방법은 유효합니다.이 경우 객체를 찾을 수 없으면 null을 반환해야합니다.
2) 일부 입력 만 유효합니다. 즉, 찾은 객체가 생성됩니다. 이 경우 발신자가 입력이 올바른지 확인할 수있는 두 번째 방법을 제공해야합니다. 예를 들어
is_present(key)
find(key) throws Exception
두 번째 계약의 두 가지 방법을 모두 제공하는 경우에만 예외가 발생할 수 있습니다.
개체를 찾을 수 없다는 의미에 따라 다릅니다.
정상 상태 인 경우 null을 반환합니다. 이것은 가끔 발생할 수있는 일이므로 발신자가 확인해야합니다.
오류 인 경우 예외를 throw하면 호출자가 누락 된 개체의 오류 조건으로 수행 할 작업을 결정해야합니다.
대부분의 사람들은 일반적으로 예외가 발생했을 때 예외를 사용하는 것이 좋습니다.
여기 몇 가지 제안이 더 있습니다.
컬렉션을 반환하는 경우 null 반환을 피하고 빈 컬렉션을 반환하면 null 확인없이 열거를 쉽게 처리 할 수 있습니다.
여러 .NET API는 thrownOnError 매개 변수의 패턴을 사용하여 호출자가 실제로 예외적 인 상황인지 여부 또는 객체를 찾을 수 없는지 여부를 선택할 수 있습니다. Type.GetType이 이에 대한 예입니다. BCL의 또 다른 일반적인 패턴은 부울이 리턴되고 값이 출력 매개 변수를 통해 전달되는 TryGet 패턴입니다.
일부 상황에서는 기본 설정이거나 동작이없는 버전 일 수있는 Null 개체 패턴을 고려할 수도 있습니다. 핵심은 코드 기반에서 널 검사를 피하는 것입니다. 자세한 내용은 여기를 참조하십시오 http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
예외를 발생시키는 대신 널을 리턴하고 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()
}
...
객체에 대한 참조 를 반환하는 한 NULL을 반환하는 것이 좋습니다.
그러나 전체 피의 것을 돌려주는 경우 (C ++에서와 같이 : 'return & blah;'(또는 'blah'는 포인터)가 아닌 'return blah;'인 경우), NULL을 반환 할 수 없습니다. 이 경우 예외를 던지거나 성공 플래그가 설정되지 않은 빈 개체를 반환하면 문제에 어떻게 접근 할 수 있습니까?
예외가되어야합니다 뛰어난 . null 을 돌려주는 것이 유효한 경우는 null를 돌려줍니다 .
메소드가 컬렉션을 반환하면 빈 컬렉션을 반환합니다 (위와 같이). 그러나 Collections.EMPTY_LIST 등은 사용하지 마십시오! (자바의 경우)
메소드가 단일 오브젝트를 검색하는 경우 몇 가지 옵션이 있습니다.
널을 리턴하기로 결정한 경우주의하십시오. 프로젝트의 유일한 프로그래머가 아닌 경우 런타임에 NullPointerExceptions (Java 또는 다른 언어로 된)를 얻을 수 있습니다! 따라서 컴파일 타임에 확인되지 않은 null을 반환하지 마십시오.
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\"");
}
}