스위치 케이스를 사용하는 동안 기본 케이스를 추가해야합니까?


41

최근 코드 검토 중에 수행 할 작업이 없더라도 블록이 사용되는 default모든 파일 에 사례 를 입력하라는 요청을 받았습니다 . 그것은 내가 사건 을 넣고 아무 것도 써야 한다는 것을 의미 합니다.switchdefaultdefault

이것이 옳은 일입니까? 어떤 목적으로 사용됩니까?


9
그것은 당신에게 달려 있습니다 ... 감독자의 코드 스타일을 의미합니다.
SD

1
기본 사례를 원하지 않는 경우도 있다고 생각합니다. 열거 형을 바꾸는 것을 고려하십시오. 스위치는 가능한 모든 값에 대한 사례를 정의합니다. 지금 열거에 값을 가산하는 것은 되어야 하는 스위치의 경우에는 첨가 될. 그렇게하지 않으면 이 새로운 열거 형 값을 위해 무언가를 하지만 코드는 그렇지 않으므로 오류가 발생할 수 있습니다 . 컴파일러는 그것에 대해 경고 할 수 있지만 (Java에 대해서는 확실하지 않습니다) 기본 사례 를 작성하지 않은 경우에만 가능합니다 . 또는 코드가 절대로 코드에 닿지 않을 때 기본 경우에 경고를 인쇄 할 수 있습니다.
leemes

6
나와 내 친구는 "개발자 예외"사건이 전화 - 코드에 뭔가 당신이해야 알고 일어날 때 결코 (때문에 논리 / 코드 이유) 발생하지, 우리가 슬로우 있어요는 "개발자 예외"를 추가합니다. 이런 식으로 이런 일이 발생하면 개발자 예외가 발생하고 적어도 어디에서 심각한 문제가 발생했는지 알고 있습니다.
Marco

답변:


31

default진술이 필요하지 않은 세 가지 경우가 있습니다 .

  1. 에 입력하는 값이 제한되어 있기 때문에 다른 경우는 없습니다 switch case. 그러나 이것은 시간이 지남에 따라 (의도적으로 또는 우발적으로) 변경 될 수 있으며, default case변경 사항 이있는 경우 _ 사용자에게 잘못된 값을 기록하거나 경고 할 수 있습니다.

  2. 당신은 어떻게 그리고 어디에서 switch case사용될 것인지 그리고 어떤 값들이 들어갈 것인지 를 안다 . 다시, 이것은 변경 될 수 있으며 추가 처리가 필요할 수 있습니다.

  3. 다른 경우에는 특별한 처리가 필요하지 않습니다. 이 경우 default case허용되는 코딩 스타일이므로 코드를 더 읽기 쉽기 때문에을 추가해야한다고 생각합니다 .

처음 두 경우는 가정을 기반으로합니다. 따라서 (정기 코드 검토가 있기 때문에 소규모가 아닌 팀에서 일한다고 가정하면) 이러한 가정을 감당할 수 없습니다. 누가 코드로 작업하거나 코드에서 함수 / 호출 메소드를 호출 할 것인지 알 수 없습니다. 마찬가지로 다른 사람의 코드로 작업해야 할 수도 있습니다. 동일한 코딩 스타일을 사용하면 다른 사람 (귀하의 코드 포함)을 쉽게 다룰 수 있습니다.


14
1과 2의 경우 기본 경우는 오류입니다. 코딩 스타일이 항상 기본값을 사용하는 경우 그렇게하지만 1과 2에서 오류가 발생하도록하십시오. 가능하면 컴파일 타임에 방출해야하지만 Java에서는 항상 가능하지는 않습니다. 적어도 사용자가 "이 값을 전달하여 발로 자신을 쏘고있다"는 메시지를받는 것이 중요하다고 생각합니다.
martiert

11
예를 들어 열거 형의 경우 누군가가 열거 형에 새 항목을 추가하는 경우 기본 사례는 throw new IllegalStateException("Unrecognised case "+myEnum)오류의 위치와 오류를 보여주는 것과 비슷한 작업을 수행해야하므로 기본 사례는 항상 좋습니다 .
Rich

이것이 일어나면 안된다는 것을 알고 있더라도 항상 else조항 이 있어야한다는 것을 의미합니까 if/else if? 나에게 좋은 생각처럼 보이지 않습니다 ...
jadkik94

2
내 일에서 일화를 추가 할 수 있다면 : 열거 형을 사용하여 일부 클래스를 인스턴스화하는 팩토리 메소드가 있습니다. 프로젝트에 새 클래스를 추가 할 때마다 열거 형에 값을 추가하고 스위치에 사례를 추가해야한다는 지침을 남겼습니다. 물론 코드를 닫은 지 일주일이 지나면 절대로 발생해서는 안되는 예외 중 하나와 함께 작동이 중지됩니다. 프로그래머에게 가서 "스위치에 사례를 추가하셨습니까?" 그리고 확실히, 그는하지 않았다. 그날 나는 "이 메시지를 받으면 코드를 마지막으로 접한 개발자를 비난한다"라는 예외를 변경했습니다.
Ziv

28

이것이 올바른 일입니까? 어떤 목적으로 사용됩니까?

회사 코딩 표준이 모든 switch진술에 대해 기본 사례를 요구하는 것은 드문 일이 아닙니다 . 그 이유 중 하나는 독자가 끝 부분을 쉽게 찾을 수 있기 때문 switch입니다. 또 다른 아마도 더 좋은 이유는 조건이 예상과 일치하지 않을 때 코드가 무엇을 해야하는지에 대해 잠시 생각하게하기 때문입니다. 요구 사유에 관계없이 회사 표준 인 경우 기밀 사유가없는 한이를 준수해야합니다.

switch가능한 모든 조건에 대해 사례를 포함 한다고 생각 assert되면 기본 사례에 진술서를 작성 하는 것이 좋습니다 . 이렇게하면 누군가 코드를 변경하고 실수로 switch다루지 않는 조건을 추가 할 때 코드의 assert해당 부분을 처리해야한다는 사실을 알게됩니다.

switch가능한 몇 가지 조건 만 다루지 만 다른 경우에는 특별한 조치를 취하지 않아도되는 경우 기본 사례를 비워 둘 수 있습니다. 이 경우 적중 조건이 수행 될 필요가 없으므로 기본 사례가 의도적으로 비어 있음을 나타 내기 위해 주석을 추가하는 것이 좋습니다.


1
무엇 assert입니까?
FLY

1
@FLY Java의 키워드이고 일반적으로 C, C ++ 등의 매크로입니다. 어쨌든 어설 션은 일부 가정이 참으로 발생하고 예외가 발생하거나 그렇지 않은 경우 오류가 발생하는지 테스트하는 데 사용됩니다.
Caleb

wikipedia에 대한 링크를 사용하여 이전 주석을 편집했습니다.
FLY

빈 케이스를 두지 마십시오. 스위치가 가능한 모든 조건을 다루지 않는 경우 두 번째 단락의 기본 사례에 어설 션을 추가 할 것을 제안한 것과 같은 이유로 기본 사례의 다른 조건을 주장해야합니다.
rold2007

12

순수한 열거 형을 "전환"하면 기본 폴 백이 위험합니다. 나중에 열거 형에 값을 추가하면 컴파일러는 새 값이 포함되지 않은 스위치를 강조 표시합니다. 기본 절이있는 경우 컴파일러는 침묵을 유지하며 누락 될 수 있습니다.


1
런타임이 아닌 컴파일 타임에 문제를 잡기 위해 +1
SylvainD

오해의 소지가있는 답변이 어떻게 투표되고 수용되는지 궁금합니다. 빠른 인터넷 검색은 Java 컴파일러에 이러한 종류의 경고가 있음을 보여줍니다. 왜 지구상에서 런타임에 오류를 기다리겠습니까?
Artur

나는이 행동에 대해 몰랐다. 내 아이디어 코드 샘플 ideone.com/WvytWq 가 달리 제안합니다. 당신이 사실이라고 가정하면 누군가 누군가 열거 형에 값을 추가하지만 코드를 다시 컴파일하지 않으면 어떻게됩니까?
emory


1
분명히 새 값은 기본 사례가없는 switch 문으로 처리되지 않습니다. 그러나 인터페이스가 변경 될 때 구현을 다시 컴파일하지 않으면 빌드 시스템이 실제로 손상됩니다.
Artur

9

(가) 자주 질문으로 여러면에서,이 질문은 동일 할 일을 내가해야 할 else의 말에 절을 if/ else if것을 커버 모든 옵션 사다리 .

대답은 문법적으로 말해서 그렇지 않습니다. 그러나 그러나 ...

default절은 (적어도) 두 가지 이유가있을 수있다 :

  1. 오류 처리기로서- 절대로 여기에 와서는 안됩니다! 할 수있는 주장이지만, 그렇다면 어떻게해야합니까? 데이터가 손상되거나 더 이상 데이터 유효성 검사가 제대로 포착되지 않으면 프로그램 실패로가는 경로가 아닙니다. 이 경우 빈 절이 아니어야합니다!
  2. 설계 / 코드 범위-가장 간단한 형태의 플로우 차트라도 if 문에서 항상 2 개의 경로가 있습니다 otherwise. 소스 코드에 이들을 포함시키지 않은 이유는 없습니다.

저의 철학은 항상 매우 간단합니다. 두 가지 옵션 중 최악의 시나리오를 평가하고 가장 안전합니다. 빈 else또는 default절의 경우 최악의 옵션은 다음과 같습니다.

  • 다음과 같은 것들을 포함 시키십시오 : 여분의 "중복"코드의 3 ~ 4 줄.
  • 다음을 포함하지 마십시오 : 불량 데이터 또는 예기치 않은 조건이 포착되지 않아 잠재적으로 프로그램 오류가 발생할 수 있습니다.

과감한? 어쩌면 ...하지만 내 소프트웨어가 잘못되면 사람들을 죽일 수 있습니다. 오히려 그 위험을 감수하고 싶지 않습니다.


여담으로, MISRA-C 가이드 라인은 {제휴에 대한 프로필을보고} 추천서 default모든을 위해 절을switch


사다리 끝에서만이 아닙니다. 질문 : 어떻게 내가 필요 else애프터을 if. 그러나 당신이 말했듯이, 아닙니다.
ott--

오류 처리기로서 빈 기본값을 피하는 약간 수정 된 양식을 제안합니다. 사람들을 죽이는 것에 관해서는, 나는 그것이 실제로 중요하지 않다고 생각합니다-당신이 기본 조항을 가지고 있는지 여부와 관계없이 사람들은 죽었을 것입니다.
emory

좋은 점, @emory-그다지 명확하지는 않았지만 ... 편집 :)
Andrew

6

Java는 '기본'문을 사용하도록 강요하지 않지만 코드에 도달 할 수없는 경우에도 (현재) 항상 하나를 갖는 것이 좋습니다 . 몇 가지 이유가 있습니다.

도달 할 수없는 기본 절을 사용하면 값을 고려한 코드의 독자에게 표시하고 수행중인 작업을 알 수 있습니다. 또한 다음과 같은 향후 변경도 허용합니다. 새 열거 형 값이 추가되면 스위치가 새 값을 자동으로 무시해서는 안됩니다. 대신 예외를 던지거나 다른 것을 할 수 있습니다.

전달 된 예기치 않은 값 (열거를 전환하지 않는 경우)을 잡으려면 예를 들어 예상보다 크거나 작을 수 있습니다.

'기본'동작을 처리하기 위해-스위치가 특별한 동작을하는 곳. 예를 들어, 변수는 스위치 외부에서 선언되었지만 초기화되지 않았으며 각 경우마다 다른 것으로 초기화됩니다. 이 경우 기본값은 기본값으로 초기화되어 스위치 직후의 코드에서 오류가 발생하거나 예외가 발생하지 않습니다.

기본값, 예외, 로깅 등을 아무것도 설정하지 않더라도 기본값이 절대 발생하지 않을 것이라고 생각한 의견조차도 코드의 가독성에 도움이 될 수 있습니다. 그러나 그것은 개인적인 취향에 달려 있습니다.


2

또한 사용하는 언어의 철학에 따라 달라집니다. 예를 들어, '충돌'에 대한 일반적인 접근 방식 인 Erlang에서는 기본 사례를 정의하지 않지만 case상황이 발생하지 않으면 명령문에서 오류가 발생하도록합니다.


0

모든 사례를 확실하고 영구적으로 다루지 않는 한 항상 기본값을 유지해야합니다. 비용이 들지 않으며 진화하는 프로그램에서 스위치 명세서를 유지하지 못하는 것에 대한 보험입니다.

다른 경우에 대해 신경 쓰지 않는다면 default : break; // do n't care 그러나 기본 기본값은 default와 같아야합니다. throw new Error ( "unexpected value");

마찬가지로, 삭제하려는 효과에 주석을 추가하지 않고 사소한 사례 구조를 "삭제"해서는 안됩니다. Java는 디자인 단계 에서이 문제를 해결했습니다.


-2

치다

enum Gender
{
       MALE ,
       FEMALE ;
}

void run ( Gender g )
{
      switch ( g )
      {
           case MALE :
                 // code related to males
                 break ;
           default :
                 assert Gender . FEMALE . equals ( g ) ;
                 // code related to females
                 break ;
      }
}

나는 이것이 MALE 사례, FEMALE 사례 및 예외를 던지는 기본 사례보다 우수하다고 주장합니다.

테스트 단계에서 컴퓨터는 g가 FEMALE인지 확인합니다. 생산 중에는 점검이 생략됩니다. (예, 미세 최적화!)

더 중요한 것은 100 % 코드 적용 목표를 유지하는 것입니다. 예외를 던지는 기본 사례를 작성했다면 어떻게 테스트 할 것입니까?


1
1. 미세 최적화가 필요 없음-지난 30 년 동안 컴파일러에서 데드 코드 제거가 사용되었으며 JIT에 의해 제거 될 것입니다. 2. 100 % 코드 적용 범위는 일반적으로 중요하지 않은 것으로 간주됩니다 (한편 100 % 적용 범위는 모든 에지 사례를 포착하지 못할 수 있으며, 다른 테스트에서는 올바른 프로그램에서 assert_not_reached 행을 포착하지 않습니다). 이 경우 기본 사례를 남기지 않으면 컴파일러 오류가 발생합니다. 반면에, 어설 션이 작동하는지 확인하는 방법은 무엇입니까 (문제가 발생하고 동일한 줄이 아닌 100 % 적용 범위로 숨겨집니다. 약속합니다).
Maciej Piechotka

1
3. 언제 Gender . FEMALE . equals ( FEMALE ) ;평가 false합니까? 당신은 의미 Gender.FEMALE.equals (g)하지만 당신은 열거 형에 대한 참조에 의존 할 수 있기 때문에 그냥 쓸 수 있습니다 g == Gender.FEMALE. 4. (개인 의견) 그러한 코드는 읽기가 훨씬 어렵고 약간 더 혼란스러운 오류가 발생합니다.
Maciej Piechotka

@MaciejPiechotka 좋은 캐치에 대해 g. 그렇습니다. 미세 최적화는 이점이 아니지만 단점도 아닙니다. 100 % 코드 범위는 목표 중 하나 인 혜택 iff이며 코드 범위 도구는 어설 션을 확인하지 않습니다 (그렇지 않아야 함).
emory

그렇다면 왜 내 목표 중 하나가 될까요? '흥미로운'부분은 모든 에지 사례에 대해 테스트되어야하며 (코드 라인에 매핑되는지 여부에 관계없이) '보링'부분은 건너 뛰어 테스트 시간을 절약 할 수 있습니다. IMHO 코드 적용 범위는 테스트의 잘못된 메트릭입니다.
Maciej Piechotka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.