반환 값이없는 함수 / 메소드에서 NULL 또는 빈 값을 반환하는 것이 더 낫습니까?


135

나는 여기에 추천을 찾고 있습니다. 반환 값이 없거나 확인할 수없는 경우 NULL 또는 빈 값을 메서드에서 반환하는 것이 더 나은지 여부에 어려움을 겪고 있습니다.

다음 두 가지 방법을 예로 들어 보겠습니다.

string ReverseString(string stringToReverse) // takes a string and reverses it.
Person FindPerson(int personID)    // finds a Person with a matching personID.

에서 ReverseString(), 나는 반환 형식은 문자열이기 때문에 발신자가 기대되도록, 빈 문자열을 반환 말할 것입니다. 또한이 방법으로 호출자는 NULL이 반환되었는지 확인하지 않아도됩니다.

에서 FindPerson()NULL을 반환하는 것이 더 적합합니다. NULL 또는 비어있는 Person Object ( new Person())가 반환 되는지 여부에 관계없이 호출자는 Person 객체에 대해 아무것도 수행하기 전에 (Person 호출과 같은 UpdateName()) Person 객체가 NULL인지 비어 있는지 확인해야합니다 . 왜 여기서 NULL을 반환하고 호출자가 NULL 만 확인하면 안됩니까?

다른 사람이 이것으로 어려움을 겪고 있습니까? 도움이나 통찰력이 있으면 감사하겠습니다.


2
다를 수 있습니다. 또한 메소드가 선행 값이 올바르지 않은 값을 중지해야한다고 주장 할 수 있습니다 (예 : stringToReverse 매개 변수가 비어 있거나 널로 전달됨). 해당 검사를 수행하면 (예외를 다시 발생) 항상 null 이외의 값을 반환합니다.
Aaron McIver

파울러 POEAA-p. 496 개 기본 패턴 - 특수 케이스 (Null 개체) 블로흐 효과적인 자바, 제 2 판 항목 43 : 빈 배열이나 컬렉션이 아닌 null을 반환
보리스 Treukhov

1
@Boris 댓글이 없습니다. 실제로 방금 특별 사례를 답변으로 게시했습니다.
Thomas Owens

@ 토마스 나는 그것에 아무런 문제가 보이지 않습니다 :). 문제는 어쨌든 상식의 문제입니다.
보리스 Treukhov

흥미로운 의견은 Oracle 데이터베이스에서 NULL과 빈 문자열이 동일
하다는 것입니다.

답변:


77

StackOverflow는이 Q & A 에서이 정확한 주제에 대해 좋은 토론을 합니다. 최고 등급의 질문에서 kronoz는 다음과 같이 말합니다.

사용 가능한 데이터가 없음을 나타내려면 일반적으로 null을 반환하는 것이 가장 좋습니다.

빈 객체는 데이터가 반환되었음을 의미하지만 null을 반환하면 아무것도 반환되지 않았 음을 나타냅니다.

또한 개체의 멤버에 액세스하려고하면 null을 반환하면 null 예외가 발생하여 버그가있는 코드를 강조 표시하는 데 유용 할 수 있습니다. 빈 객체의 멤버에 액세스해도 버그가 발견되지 않을 수 있습니다.

개인적으로, 나는 문자열을 반환하는 함수에 대해 빈 문자열을 반환하여 시행해야 할 오류 처리량을 최소화하고 싶습니다. 그러나 귀하와 함께 일하는 그룹이 동일한 협약을 따르도록해야합니다. 그렇지 않으면이 결정의 이점이 달성되지 않습니다.

그러나 SO 답변의 포스터가 언급했듯이 데이터가 반환되는지 여부에 대한 의심이 없도록 객체가 예상되는 경우 null이 반환되어야합니다.

결국, 최선의 방법은 없습니다. 팀 합의를 구축하면 궁극적으로 팀의 모범 사례를 이끌어 낼 수 있습니다.


8
개인적으로, 나는 문자열을 반환하는 함수에 대해 빈 문자열을 반환하여 시행해야 할 오류 처리량을 최소화하고 싶습니다. 이 주장을 이해하지 못했습니다. null 확인은 최대 10 자 미만입니까? 왜 우리는 이런 식으로 역 굽힘 노동입니까?
Aaron McIver

19
아무도 그것이 다시 굽힘 노동이라고 말했다. 그러나 그것은 이다 노동. 코드에 특별한 경우를 추가하여 테스트 할 하나 이상의 분기를 의미합니다. 또한 코드 흐름을 방해합니다. for x in list_of_things() {...}아마 다음보다 더 빨리 grokl = list_of_things(); if l != null {...}
Bryan Oakley

5
@Bryan : 빈 값 목록과 빈 문자열 사이에는 큰 차이가 있습니다. 문자열은 문자 목록을 거의 나타내지 않습니다.
케빈 클라인

3
@kevin cline : 물론입니다. 그러나 문자열의 경우 해당 문자열이 null인지 여부에 관계없이 로그에 표시되도록 할 수 있습니다. 빈 문자열을 인쇄하여 실제 의도를 혼란스럽게 만들 수 있도록 null인지 확인해야합니다. 또는 웹 페이지에 추가하려는 사용자 제공 콘텐츠가 포함 된 데이터베이스 필드와 같은 것일 수 있습니다. 그것은 할 쉽게 emit(user.hometown)보다if user.hometown == null { emit("") else {emit(user.hometown)}
브라이언 오클리

1
여분의 타이핑 (큰 문제는 아님)뿐만 아니라 가독성에 영향을 미칩니다. 나는 개인적으로 많은 수의 null 검사를 방해하는 코드를 찾습니다.
ToddR

82

내가 작성한 모든 코드 null에서 함수에서 돌아 오는 것을 피 합니다. Clean Code 에서 읽었습니다 .

사용의 문제점 null은 인터페이스를 사용하는 사람 null이 가능한 결과인지 여부와 not null참조 유형 이 없기 때문에 확인해야하는지 여부를 알 수 없다는 것 입니다.

F #에서는 또는 option형식이 될 수 있는 형식을 반환 할 수 있으므로 호출자가 확인해야합니다.some(Person)none

유사한 C # (anti-) 패턴은 다음과 같은 Try...방법입니다.

public bool TryFindPerson(int personId, out Person result);

지금은 사람들이 말한 알고 싫어Try... 출력 매개 변수를 가진 것은 순수 함수의 아이디어를 나누기 때문에 패턴을하지만,보다 정말 다를 바 없다 :

class FindResult<T>
{
   public FindResult(bool found, T result)
   {
       this.Found = found;
       this.Result = result;
   }

   public bool Found { get; private set; }
   // Only valid if Found is true
   public T Result { get; private set;
}

public FindResult<Person> FindPerson(int personId);

... 솔직히 말하면 모든 .NET 프로그래머는 Try...패턴이 .NET 프레임 워크에서 내부적으로 사용되므로 패턴 에 대해 알고 있다고 가정 할 수 있습니다 . 그것이 그들이 의미 설명서를 읽을 필요가 없습니다 기능의 일부 순정 주의자의 견해 (이해를 지키는 것보다 나에게 더 중요하다, 그것이 무엇을 이해하는 result입니다 out매개 변수가 아닌 ref매개 변수).

그래서 TryFindPerson당신이 그것을 찾을 수없는 것이 완전히 정상임을 나타내는 것처럼 보이기 때문에 갈 것입니다.

반면에 호출자가 personId존재하지 않는 것을 제공해야 할 논리적 이유가 없다면 아마도 다음과 같이 할 것입니다.

public Person GetPerson(int personId);

... 잘못된 경우 예외가 발생합니다. Get...접두사는 발신자가 성공한다 알고 있다는 것을 의미한다.


28
+1, 아직 깨끗한 코드를 참조하지 않은 경우이 질문에 대답하겠습니다. 나는 "만약 당신의 기능이 그 이름으로 무엇을 하는가하면 예외를 던진다"라는 만트라가 마음에 든다. 수십 줄마다 null을 확인하는 것보다 Muuuch가 더 좋습니다.
Graham

13
나는 사람들에 대한 지식에 대해 아무 것도 가정하지 않았습니다.
CaffGeek

5
"널 (null) 사용의 문제점은 널 (null) 참조 유형이 없기 때문에 인터페이스를 사용하는 사람이 널 (null)이 가능한 결과인지 여부와이를 확인해야하는지 여부를 알 수 없다는 것입니다." 참조 유형은 null 일 수 있으므로 항상 null이 가능한 결과라고 가정 할 수 있습니까?
Tommy Carlier

4
함수가 포인터 (C / C ++) 또는 객체에 대한 참조 (Java)를 반환하면 항상 null을 반환한다고 가정합니다.
Giorgio

7
"null을 사용할 때의 문제는 인터페이스를 사용하는 사람이 null이 가능한 결과인지 알지 못한다는 것입니다. 그리고 [...]"메소드가 null을 반환 할 수 있으면 명시 적으로 API 계약의 일부로 언급되었습니다.
Zsolt Török

28

엔터프라이즈 애플리케이션 아키텍처의 패턴 에서 Martin Fowler의 특수 사례 패턴을 시도 할 수 있습니다 .

Null은 다형성을 물리 치기 때문에 객체 지향 프로그램에서 어색한 것입니다. 일반적으로 항목이 정확한 유형인지 하위 클래스인지 걱정하지 않고 주어진 유형의 변수 참조에서 foo를 자유롭게 호출 할 수 있습니다. 강력한 형식의 언어를 사용하면 컴파일러에서 호출이 올바른지 확인할 수도 있습니다. 그러나 변수에 null이 포함될 수 있으므로 null에 메시지를 호출하여 런타임 오류가 발생할 수 있으며, 이는 친절하고 친숙한 스택 추적을 제공합니다.

변수가 null 일 수 있으면 null 테스트 코드로 변수를 둘러싸 야 null이 있으면 올바른 작업을 수행해야합니다. 종종 많은 상황에서 올바른 것이 동일하므로 코드 중복의 죄를 저지르는 많은 장소에서 유사한 코드를 작성하게됩니다.

널 (null)은 이러한 문제의 일반적인 예이며 다른 것들은 정기적으로 발생합니다. 숫자 시스템에서는 무한대를 다루어야합니다. 무한대는 일반적인 실수의 불변을 깰 수있는 덧셈과 같은 특별한 규칙이 있습니다. 비즈니스 소프트웨어에서 가장 초기에 경험 한 것 중 하나는 완전히 알려지지 않은 유틸리티 고객과 "사용자"라고 불렀습니다. 이들 모두는 일반적인 유형의 동작을 변경합니다.

null 또는 홀수 값을 반환하는 대신 호출자가 기대하는 것과 동일한 인터페이스를 가진 특수 사례를 반환합니다.


이 시나리오에 부딪 쳤지 만 소프트웨어가 릴리스 된 후에 만 ​​가능합니다. 내 테스트 데이터는 결코 트리거하지 않았으므로 약간 파란색이었고 디버그가 어려웠습니다. 특수 사례 패턴으로 해결하지는 않았지만 알고있는 것이 좋습니다.
samis

14

ReverseString()반전 된 문자열을 반환하고에 IllegalArgumentException전달 된 if를 던질 것이라고 생각 합니다 Null.

나는 항상 무언가를 찾을 수 있어야 NullObject 패턴을FindPerson() 따르 거나 무언가를 찾지 못하는 것에 대한 검사되지 않은 예외를 제기 해야 한다고 생각 합니다 .

다루어야하는 Null것은 피해야하는 것입니다. 데 Null언어는 호출 된 억 달러 실수 는 발명가의에 의해!

나는 그것을 10 억 달러의 실수라고 부릅니다. 그것은 1965 년에 null 참조의 발명이었다. 당시 나는 객체 지향 언어 (ALGOL W)로 참조 할 수있는 최초의 포괄적 인 타입 시스템을 설계하고 있었다.

필자의 목표는 컴파일러가 자동으로 검사를 수행하여 모든 참조 사용이 절대적으로 안전하도록하는 것이 었습니다. 그러나 구현하기가 쉽기 때문에 null 참조를 넣는 유혹에 저항 할 수 없었습니다.

이로 인해 수많은 오류, 취약성 및 시스템 충돌이 발생하여 지난 40 년간 수십억 달러의 고통과 피해를 초래했을 수 있습니다.

최근에는 Microsoft의 PREfix 및 PREfast와 같은 여러 프로그램 분석기가 참조를 확인하는 데 사용되었으며 null이 아닐 수있는 위험이있는 경우 경고를 표시합니다. Spec #과 같은 최신 프로그래밍 언어는 널이 아닌 참조에 대한 선언을 도입했습니다. 이것이 1965 년에 거부 한 해결책입니다.

토니 호 아레


11

옵션을 돌려줍니다 . NullPointerException의 위험없이 다른 유효하지 않은 값을 반환하면 (모음에 빈 값을 가질 수있는 것과 같은) 모든 이점이 있습니다.


1
흥미 롭군 Java에서 옵션을 구현하는 방법은 무엇입니까? 그리고 C ++에서?
Giorgio

1
@Giorgio, Java의 경우 Google의 Guava 라이브러리에는 Optional 이라는 클래스가 있습니다.
Otavio Macedo

1
C ++의 경우boost::optional<T>
MSalters

8

나는이 주장의 양면을 보았고 코드를 깨끗하게 유지하고 여분의 오류 처리 블록을 피하기 위해 다소 영향력있는 목소리 (예 : Fowler)가 null을 반환하지 말 것을 주장합니다.

그러나 나는 null을 반환하는 지지자들과 함께하는 경향이 있습니다. 나는 메소드를 호출하고 함께 대응에서 중요한 차이가 찾을 수 있는 데이터가없는 I 와 함께 응답 나는이 빈 문자열이가 .

Person 클래스를 참조하는 토론 중 일부를 보았으므로 클래스의 인스턴스를 찾으려고하는 시나리오를 고려하십시오. 파인더 속성 (예 : ID)을 전달하면 클라이언트는 즉시 null을 확인하여 값이 없는지 확인할 수 있습니다. 이는 예외적 인 것은 아니지만 예외적 인 것은 아니지만 명확하게 문서화해야합니다. 예, 이것은 클라이언트 측에서 약간의 엄격함을 요구하며, 아니오, 전혀 나쁜 일이라고 생각하지 않습니다.

이제 유효한 Person 객체를 반환하는 대안을 생각해보십시오. 모든 값 (이름, 주소, favoriteDrink)에 널을 넣습니까, 아니면 유효하지만 비어있는 오브젝트로 값을 채우겠습니까? 고객은 이제 실제 개인을 찾지 못했다고 어떻게 판단합니까? 이름이 null 대신 빈 문자열인지 확인해야합니까? 이런 종류의 일이 실제로 null을 확인하고 이동 한 것보다 더 많은 코드 혼란과 조건문으로 이어지지 않습니까?

다시 말하지만,이 논쟁의 어느 쪽에도 동의 할 수있는 점이 있지만, 이것이 대부분의 사람들에게 가장 합리적이라는 것을 알았습니다 (코드를보다 유지 보수 가능하게 만듭니다).


차이는 "않습니다이다 FindPerson또는 GetPerson널 (null)을 반환하거나 키가 존재하지 않는 경우 예외를 throw?" API 사용자로서 나는 모르고 설명서를 확인해야합니다. 반면에 bool TryGetPerson(Guid key, out Person person), 문서를 확인하도록 요구하지 않으며 예외가 아닌 상황에 해당하는 예외가 발생하지 않는다는 것을 알고 있습니다. 그것이 내가 대답하려고하는 요점입니다.
Scott Whitlock

4
나는 사람들이 예외에 너무 붙어 있다고 생각합니다. 예외는 나쁘고 리소스 소비입니다. 말할 것도없이 사람들은 아무것도 해결하지 않고 진술을 시도하고 포착합니다. 예외는 근본적으로 잘못되었다는 명백한 징후입니다. 예를 들어, 널 참조는 널 오브젝트를 참조하는 것이 명확하지 않기 때문에 예외를 발생시킵니다. 사람을 찾았는지 여부를 확인하는 데 잘못 사용합니다.
Vladimir Kocjancic 님이

1
@VladimirKocjancic : 전적으로 동의합니다 : 예외는 소프트웨어 버그, 하드웨어 오류, 시스템 구성 오류와 같은 예외적 인 상황에 사용해야합니다. (와 같은 findPerson) 부분 함수를 계산하는 경우 결과가 나타나지 않는 것이 절대적으로 정상입니다. 예외가 발생하지 않아야합니다.
조르지오

6

항목의 존재 여부를 알아야하는 경우 null을 반환합니다. 그렇지 않으면 예상 데이터 형식을 반환하십시오. 항목 목록을 반환하는 경우 특히 그렇습니다. 일반적으로 호출자가 목록을 원한다고 가정하면 안전합니다. 목록을 반복하고 싶을 것입니다. 널 (null)을 반복하려고 시도하지만 비어있는 목록을 반복 할 때는 많은 (대부분? 전부?) 언어가 실패합니다.

나는 이와 같은 코드를 시도하고 사용하는 것이 실망 스럽지만 실패하기 만했다.

for thing in get_list_of_things() {
    do_something_clever(thing)
}

물건 이없는 경우를 위해 특별한 경우를 추가 할 필요는 없습니다 .


7
목록 또는 다른 값 그룹이 예상되는 경우 항상 정확한 이유로 빈 목록을 반환하도록 선택합니다. 기본 작업 (빈 목록에 반복)은 거의 항상 맞으며, 그렇지 않으면 호출자가 목록이 비어 있는지 명시 적으로 확인할 수 있습니다.
TMN

5

메소드의 의미에 따라 다릅니다. 메소드는 "Null이 아님"만 허용하도록 지정할 수 있습니다. Java에서는 일부 메타 데이터 주석을 사용하여 선언 할 수 있습니다.

string ReverseString(@NotNull String stringToReverse)

어떻게 든 반환 값을 지정해야합니다. 선언하면 NotNull 값만 허용하고 빈 문자열을 반환해야합니다 (입력도 빈 문자열 인 경우).

두 번째 경우는 의미 상 약간 복잡합니다. 이 방법이 기본 키로 사람을 반환하고 사람이 존재할 것으로 예상되는 경우 더 좋은 방법은 예외를 throw하는 것입니다.

Person FindPerson(int personID)

추측 된 ID (나에게 이상한 것)로 사람을 검색하면 해당 메소드를 @Nullable로 선언하는 것이 좋습니다.


3

가능하면 Null Object 패턴을 사용하는 것이 좋습니다. 메소드를 호출 할 때 코드를 단순화하고 못생긴 코드를 읽을 수 없습니다.

if (someObject != null && someObject.someMethod () != whateverValue)

예를 들어, 메소드가 어떤 패턴에 맞는 객체 컬렉션을 반환하는 경우 빈 컬렉션을 반환하는 것이 returning보다 의미가 null있으며이 빈 컬렉션을 반복하면 성능에 거의 영향을 미치지 않습니다. 또 다른 경우는 데이터를 기록하는 데 사용되는 클래스 인스턴스를 반환 null하고 반환되는 참조가 항상 사용자인지 확인하지 않기 때문에 Null 객체를 반환하는 방법 입니다 null.

반환 null이 의미가 있는 경우 ( findPerson ()예 : 메소드 호출 ) 객체가 존재하면 ( personExists (int personId)예를 들어) 반환하는 메소드를 적어도 제공하려고합니다 . 다른 예제는 Java 의 containsKey ()메소드입니다 Map. 원하는 객체를 사용할 수 없을 가능성이 있음을 쉽게 알 수 있으므로 발신자의 코드를 더 깨끗하게 만듭니다 (사람이 없거나 키가지도에 없음). null내 의견으로 는 참조가 난독 화 되는지 끊임없이 확인합니다 .


3

다음 조건이 적용되는 경우에만 null을 반환하는 것이 가장 좋습니다.

  • 정상 작동 에서는 널 결과가 예상됩니다 . 합리적인 상황에서 사람을 찾지 못할 수도 있으므로 findPerson ()이 null을 반환하는 것이 좋습니다. 그러나 실제로 예상치 못한 실패 (예 : saveMyImportantData ()라는 함수) 인 경우 예외가 발생합니다. 이름에 힌트가 있습니다-예외는 예외적 인 상황입니다!
  • null은 "찾을 수 없음 / 값 없음" 을 의미하는 데 사용됩니다 . 다른 의미가 있다면 다른 것을 반환하십시오! 좋은 예는 Infinity 또는 NaN을 반환하는 부동 소수점 연산입니다.이 값은 특정 의미를 가진 값이므로 여기서 null을 반환하면 매우 혼란 스러울 수 있습니다.
  • 이 함수는 findPerson ()과 같은 단일 값을 반환합니다 . findAllOldPeople ()과 같이 컬렉션을 반환하도록 설계된 경우 빈 컬렉션이 가장 좋습니다. 이에 대한 추론은 컬렉션을 반환하는 함수가 null을 반환해서는 안된다는 것 입니다.

또한 함수가 널을 리턴 할 수 있다는 사실문서화 해야합니다 .

이 규칙을 따르면 널은 대부분 무해합니다. null 확인을 잊어 버린 경우 일반적으로 NullPointerException이 즉시 발생합니다. 이는 일반적으로 수정하기 매우 쉬운 버그입니다. 이 빠른 실패 접근 방식은 시스템 주위에 조용히 전파되어 예외를 발생시키지 않고 데이터를 손상시킬 수있는 가짜 반환 값 (예 : 빈 문자열)을 사용하는 것보다 훨씬 낫 습니다.

마지막으로 이러한 규칙을 질문에 나열된 두 기능에 적용하면

  • FindPerson- 사람을 찾을 수없는 경우이 함수가 널을 리턴하는 것이 적절합니다.
  • ReverseString- 문자열을 전달하면 결과를 찾지 못할 것 같습니다 (빈 문자열을 포함하여 모든 문자열을 되돌릴 수 있기 때문에). 따라서 null을 반환해서는 안됩니다. 문제가 발생하면 (메모리가 부족합니까?) 예외가 발생합니다.

1

내 의견으로는 NULL 반환, 빈 결과 반환 (예 : 빈 문자열 또는 빈 목록) 및 예외 발생 사이에는 차이가 있습니다.

나는 일반적으로 다음과 같은 접근법을 취합니다. 함수 또는 메소드 f (v1, ..., vn) 호출을 함수의 응용 프로그램으로 간주합니다.

f : S x T1 x ... x Tn -> T

여기서 S는 "세계의 상태"T1, ..., Tn은 입력 매개 변수의 유형이며 T는 리턴 유형입니다.

먼저이 함수를 정의하려고합니다. 함수가 부분적 인 경우 (즉, 정의되지 않은 입력 값이있는 경우) NULL을 반환하여 신호를 보냅니다. 계산이 정상적으로 종료되기를 원하고 요청한 함수가 주어진 입력에 정의되어 있지 않다고 알려주기 때문입니다. 예를 들어 빈 문자열을 반환 값으로 사용하면 함수가 입력에 정의되어 있고 빈 문자열이 올바른 결과 일 수 있기 때문에 모호합니다.

부분 함수를 적용하고 있기 때문에 호출 코드에서 NULL 포인터에 대한 추가 검사 가 필요하다고 생각하며 주어진 입력에 대해 함수가 정의되지 않은 경우 함수를 호출하는 것이 호출 된 메소드의 작업입니다.

나는 계산을 수행 할 수없는 오류에 대해 예외를 사용하는 것을 선호합니다 (즉, 답을 찾을 수 없었습니다).

예를 들어 Customer 클래스가 있고 메소드를 구현하려고한다고 가정합니다.

Customer findCustomer(String customerCode)

코드로 애플리케이션 데이터베이스에서 고객을 검색합니다. 이 방법에서는

  • 쿼리가 성공하면 Customer 클래스의 객체를 반환합니다.
  • 쿼리에서 고객을 찾지 못하면 null을 반환합니다.
  • 데이터베이스에 연결할 수 없으면 예외를 처리하십시오.

null에 대한 추가 검사, 예 :

Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
    ...
}

내가하고있는 일의 의미의 일부이며 코드를 더 잘 읽기 위해 "건너 뛰지"않을 것입니다. 코드를 단순화하기 위해 문제의 의미를 단순화하는 것이 좋은 방법이라고 생각하지 않습니다.

물론 null 검사가 자주 발생하기 때문에 언어가 특별한 구문을 지원하면 좋습니다.

클래스의 null 객체를 다른 모든 객체와 구별 할 수있는 한 Null 객체 패턴 (Laf에서 제안한대로)을 사용하는 것도 고려할 것입니다.


0

컬렉션을 반환하는 메서드는 빈 상태로 반환되지만 다른 개체는 null을 반환 할 수 있습니다. 컬렉션의 경우 개체가 생길 수 있지만 요소가 없으므로 호출자는 크기가 아닌 두 가지에 대해서만 유효성을 검사하기 때문입니다.


0

나에게는 두 가지 경우가 있습니다. 어떤 종류의 목록을 반환하는 경우 목록에 무엇이든 넣지 않으면 항상 목록을 반환해야합니다.

토론을 볼 수있는 유일한 경우는 단일 항목을 반환 할 때입니다. 나는 그러한 상황에서 실패가 발생할 경우 null을 반환하는 것을 선호한다는 것을 알게되었습니다.

null 객체를 반환하고 호출자가 실제 객체를 필요로한다면 예상치 못한 동작을 생성하는 null 객체를 사용해보십시오. 상황을 처리하는 것을 잊어 버린 경우 일상이 호황을 누리는 것이 더 낫습니다. 뭔가 잘못되면 최대한 빨리 예외를 원합니다. 이런 식으로 버그를 전달할 가능성이 줄어 듭니다.


0

사람들이 Maybe형식 생성자 에 대해 이미 말한 내용에 추가 :

NPE를 위험에 빠뜨리지 않는 것 외에 또 다른 큰 이득은 의미 적입니다. 순수 함수를 다루는 함수 세계에서 우리는 적용될 때 반환 값정확히 동일한 함수를 만들려고 합니다 . 경우를 고려하십시오 String.reverse(): 이것은 특정 문자열이 주어진 문자열의 역 버전을 나타내는 함수입니다. 모든 문자열을 뒤집을 수 있기 때문에이 문자열이 존재한다는 것을 알고 있습니다 (문자열은 기본적으로 정렬 된 문자 집합 임).

이제는 findCustomer(int id)어떻습니까? 이 기능은 주어진 ID를 가진 고객을 나타냅니다. 이것은 존재하거나 존재하지 않는 것입니다. 그러나 기능이 하나의 리턴 값을 기억, 그래서 당신은 정말이 기능은 지정된 ID를 가진 고객을 반환 "말할 수 없다 또는 그것을 반환 null.

이것은 nullnull 객체 를 반환 하고 반환하는 주요 문제 입니다. 그들은 오도합니다. null고객이 아니며 실제로 "고객 부재"도 아닙니다. 아무것도 없습니다. NOTHING에 대한 유형이없는 포인터 일뿐입니다. 매우 낮은 수준이며 매우 추악하고 오류가 발생하기 쉽습니다. null 객체도 여기에 오해의 소지가 있습니다. null 고객은 고객입니다. ID가없는 고객이 아니며 ID를 요청한 고객이 아니기 때문에 반품이 잘못되었습니다. 이것은 내가 요청한 고객이 아니지만 여전히 고객을 반환했다고 주장합니다. ID가 잘못되었습니다. 분명히 이것은 버그입니다. 메소드 이름과 서명이 제안한 계약을 위반합니다. 클라이언트 코드는 디자인에 대한 것을 가정하거나 문서를 읽도록 요구합니다.

이 두 가지 문제는 모두로 해결됩니다 Maybe Customer. 갑자기 "이 기능은 주어진 ID를 가진 고객을 나타냅니다"라고 말하지 않습니다. "이 함수는 주어진 ID를 가진 고객을 나타내는 경우이를 나타냅니다 . 이제는 그 기능에 대해 매우 명확하고 분명 합니다 . 존재 하지 않는 ID를 가진 고객을 요청하면을 받게됩니다 Nothing. 이상 null?를 NPE 위험합니다. 그러나 또한의 유형 때문에 다만 Nothing단지 아니다 Maybe. 그것은이다 Maybe Customer. 그것은 의미 론적 의미를 가지고있다. 그것은 구체적으로 고객이 존재하지 않음을 나타내는 "고객의 부재"를 의미한다.

null의 또 다른 문제는 물론 모호하다는 것입니다. 고객을 찾지 못했거나 DB 연결 오류가 있었습니까? 아니면 해당 고객을 볼 수 없습니까?

이와 같은 여러 오류 사례를 처리하는 경우 해당 버전에 대해 예외를 발생 시키거나 (이 방법을 선호하는 경우) Either CustomerLoadError Customer잘못되었거나 잘못 반환 된 고객을 나타내는을 반환 할 수 있습니다. Maybe Customer잘못 될 수있는 것을 지정할 수 있는 동시에 모든 장점이 있습니다.

내가 추구하는 가장 중요한 것은 서명으로 함수의 계약을 포착하는 것입니다. 사물을 가정하지 말고, 약탈하는 규칙에 의존하지 말고, 명시 적이어야합니다.


0

1) 함수의 의미가 아무것도 반환 할 수없는 경우 호출자는 테스트해야합니다. 그렇지 않으면 그는 예를 들어갑니다. 당신의 돈을 가지고 아무도에게주지 마십시오.

2) 의미 적으로 항상 무언가를 반환하는 함수를 만드는 것이 좋습니다.

로거를 사용하면 로거가 정의되지 않은 경우 로그하지 않는 로거를 반환하는 것이 좋습니다. 컬렉션을 반환 할 때 빈 집합이 집합이 아니고 집합이 아니기 때문에 컬렉션을 반환하는 것은 거의 의미가 없습니다.

A를 사람이 예를 들어, 내가 방법을 "최대 절전 모드"갈 것 (부하, IIRC 대 얻을 수 있지만, 거기는 게으른 로딩을위한 프록시 객체 복잡하다) 두 가지 기능, null을 반환하고 두 번째 그 발생을 갖는.


-1
  • 응용 프로그램에서 데이터를 사용할 수 있지만 데이터를 사용할 수없는 경우 NULL을 반환해야합니다. 예를 들어, 우편 번호를 기준으로 CITY를 반환하는 서비스는 도시를 찾을 수없는 경우 null을 반환해야합니다. 그런 다음 호출자는 null 또는 처리를 처리하도록 결정할 수 있습니다.

  • 두 가지 가능성이 있으면 빈 목록을 반환해야합니다. 사용 가능한 데이터 또는 사용 가능한 데이터가 없습니다. 예를 들어, 인구가 특정 수보다 큰 경우 CITY를 반환하는 서비스입니다. 주어진 기준을 만족하는 데이터가 없으면 빈 목록을 반환 할 수 있습니다.


-2

NULL을 반환하는 것은 객체 지향 세계에서 끔찍한 디자인 입니다. 간단히 말해서 NULL 사용법은 다음과 같습니다.

  • 임시 오류 처리 (예외 대신)
  • 모호한 의미
  • 빠른 실패 대신 느리게
  • 컴퓨터 사고 대 객체 사고
  • 변경 가능하고 불완전한 객체

자세한 설명은이 블로그 게시물을 확인하십시오. http://www.yegor256.com/2014/05/13/why-null-is-bad.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.