@Nonnull로 주석이 달린 매개 변수가 null인지 확인하십시오.


19

우리는 FindBugs를 사용하고 매개 변수에 @Nonnull적절하게 주석을 달기 시작 했으며주기 초기에 버그를 지적하는 것이 좋습니다. 지금까지 우리는 nullGuava 를 사용 하기 위해 이러한 인수를 계속 확인 checkNotNull했지만 SOAP 요청 null과 같이 값을 확인하지 않고 값을 가져올 수있는 가장자리에서만 확인하는 것을 선호합니다 null.

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

나는 값 자체를 @Nonnull차단하지 않는다는 것을 이해 null합니다.

그러나 FindBugs는 값이 표시되지 않은 필드에서 마크 된 필드로 전송되는 곳을 가리킬 것이므로 전달 된 모든 곳 @Nonnull에서이 값을 확인하지 않고도 이러한 경우를 잡기 위해 의존 할 수는 없습니다 null. 시스템? 도구를 신뢰하고 이러한 자세한 검사를 피하고 싶습니까?

결론 :null 아래 의 두 번째 검사 를 제거하는 것이 안전 해 보이지만 나쁜 습관입니까?

이 질문은 아마도 null을 기대하지 않으면 null 검사해야 하지만 @Nonnull주석 과 관련하여 구체적으로 묻습니다 .

답변:


6

FindBug를 신뢰하지 않으면 어설 션을 사용하는 옵션 일 수 있습니다. 이렇게하면 사용자 MSalters가 언급 한 문제를 피할 수 있지만 여전히 확인해야합니다. 물론 이러한 빠른 접근 방식이 실현 가능하지 않은 경우 (예 : 예외를 포착해야하는 경우)이 접근 방식을 적용 할 수 없습니다.

그리고 나쁜 습관인지 아닌지에 대한 질문에 더 답하십시오. 글쎄, 이것은 논쟁의 여지가 있지만 나는 그렇게 생각하지 않을 것입니다. 이 FindBug 주석은 계약 원칙에 따른 설계에 따라 가벼운 사양으로 간주합니다.

계약에 의한 설계에서는 메소드와 호출자 사이에 계약을 설정합니다. 계약은 호출자가 메소드를 호출 할 때 이행하기로 동의하는 전제 조건과 그 전제 조건이 충족되면 실행 후 메소드에 의해 수행되는 사후 조건으로 구성됩니다.

이 개발 방법의 장점 중 하나는 소위 방어 프로그래밍 스타일 (모든 잘못된 매개 변수 값을 명시 적으로 확인하는 등)을 피할 수 있다는 것입니다. 대신 계약에 의존하고 중복 검사를 피하여 성능과 가독성을 높일 수 있습니다.

계약은 계약이 깨졌을 때 프로그램이 실패하기를 원하는 위에서 언급 한 실패 우선 원칙에 따라 런타임 어설 션 검사에 사용될 수 있으며, 오류의 원인을 식별 할 수있는 단서를 제공합니다. (사전 조건 실패는 호출자가 잘못한 것을 의미하며 사후 조건 실패는 주어진 메소드의 구현 오류를 나타냄)

또한 계약을 정적 분석에 사용할 수 있으며, 소스 코드를 실제로 실행하지 않고도 결론을 도출하려고합니다.

@nonnull 주석은 FindBugs 도구에서 정적 분석에 사용되는 전제 조건으로 볼 수 있습니다. 런타임 어설 션 검사와 같은 접근 방식, 즉 실패 우선 전략을 선호하는 경우 어설 션 문을 기본 제공 Java로 사용하는 것이 좋습니다. 또는 JML (Java Modeling Language)과 같은 행동 인터페이스 사양 언어를 사용하여보다 정교한 사양 전략에 적응할 수도 있습니다.

JML은 특수 Java 주석에 스펙이 포함 된 Java의 확장입니다. 이 접근법의 장점은 구현 세부 사항이 아닌 스펙에만 의존하고 언급 된 런타임 어설 션 검사 도구와 같이 스펙을 사용하는 다른 도구를 사용하는 개발 접근법을 사용하여 정교한 스펙을 사용할 수 있다는 것입니다. 단위 테스트 또는 문서의 자동 생성.

@nonnull이 (가벼운) 계약이라는 나의 견해를 공유한다면,이 원칙의 기본 아이디어는 방어 적 프로그래밍을 피하는 것이기 때문에 추가 점검을 추가하지 않는 것이 일반적입니다.


2
이것이 내가 @Nonnull계약서 사양으로 사용하는 방식과 정확히 같습니다. 계약 뒤에있는 수표를 제거해 왔으며 지금까지 아무런 문제가 없었습니다.
David Harkness

4

글쎄, 왜 쓰지 않는지 생각 해봐

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

프로그래밍은 흑 마법이 아닙니다. 변수가 갑자기 널이되지 않습니다. 변수가 Null이 아니며 변수가 변경되지 않았다는 것을 알고 있으면 확인 하지 마십시오 .

당신이 그것을 확인하면, 미래의 일부 프로그래머 (아마도 당신)는 그 확인이 왜 있는지 알아내는 데 많은 시간을 할애 할 것입니다. 수표는 반드시 이유가 있어야합니다. 그래서 당신은 무엇을 간과합니까?


3
@Nonnull계약은 호출자가 null생성자에게 전달해서는 안된다고 규정 하고 FindBugs는 정적 분석을 사용하여 특히 null표시되지 않은 값을 전달하는 호출을 허용 할 수있는 호출을 찾습니다 @Nonnull. 그러나 발신자는 nullFindBugs의 경고 를 전달 하고 무시할 수 있습니다.
David Harkness

프로그래밍은 이상적으로 흑 마법이 아닙니다. 불행히도, 특히 동시성 코드를 사용하여 작업 할 때 경고와 놀라움이 많이 있습니다. ♬ ~ ᕕ (ᐛ) ᕗ
Tim Harper
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.