문제

내 동료는 그것을 말합니다 방법 인수로서의 부울은 허용되지 않습니다. 그들은 열거로 대체 될 것이다. 처음에 나는 어떤 혜택도 보지 못했지만 그는 나에게 모범을 보였다.

이해하기 쉬운 것은 무엇입니까?

file.writeData( data, true );

또는

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

이제 나는 그것을 얻었다! ;-)
이것은 두 번째 매개 변수로 열거되어 코드를 훨씬 더 읽기 쉽게 만드는 예입니다.

그렇다면이 주제에 대한 당신의 의견은 무엇입니까?

도움이 되었습니까?

해결책

부울은 "예/아니오"선택을 대표합니다. "예/아니오"를 대표하려면 부울을 사용하려면 자명해야합니다.

그러나 그것이 두 가지 옵션 중에서 선택하는 경우, 그 중 어느 것도 명백히 예 또는 아니오가 아니며, 열거는 때때로 더 읽기 쉬울 수 있습니다.

다른 팁

열거는 또한 향후 수정을 허용하며, 여기서 세 번째 선택 (또는 그 이상)을 원합니다.

문제를 가장 잘 모델링하는 것을 사용하십시오. 당신이주는 예에서, 열거는 더 나은 선택입니다. 그러나 부울이 더 나을 때 다른 시간이있을 것입니다. 당신에게 더 의미가 있습니다 :

lock.setIsLocked(True);

또는

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

이 경우 부울 옵션을 선택할 수 있습니다. 부울 옵션이 매우 명확하고 모호하지 않다고 생각하기 때문에 내 자물쇠에 두 개 이상의 상태가 없을 것이라고 확신합니다. 그럼에도 불구하고 두 번째 선택은 유효하지만 불필요하게 복잡합니다.

나는 당신이 이것을 거의 스스로 대답했다고 생각합니다. 최종 목표는 코드를 더 읽기 쉽게 만드는 것이라고 생각합니다.이 경우 열거는 그렇게했습니다. IMO는 항상 최종 목표를 보는 것이 최선입니다. 가이드 라인 IE 열거는 종종 일반 부종, int 등보다 코드에서 더 읽을 수 있지만 규칙에는 항상 예외가 있습니다.

Adlai Stevenson이 UN에서 Zorin 대사에게 제기 된 질문을 기억하십시오. 쿠바 미사일 위기?

"당신은 지금 세계 의견의 법정에 있으며 대답 할 수 있습니다. 예 혹은 아니오. 당신은 [미사일]이 존재한다는 것을 부인했으며, 내가 당신을 올바르게 이해했는지 여부를 알고 싶습니다 .... 그것이 당신의 결정이라면 지옥이 얼어 붙을 때까지 내 대답을 기다릴 준비가되어 있습니다. "

방법에 당신이 가진 깃발이 당신이 그것을 고정시킬 수있는 특성이라면 이진 결정, 그리고 그 결정은 할 것입니다 절대 3 방향 또는 N- 웨이 결정으로 바꾸어 부울로 가십시오. 표시 : 깃발이 호출됩니다 ISXXX.

무언가의 경우에 부울하지 마십시오. 모드 스위치. 항상 있습니다 하나 더 모드 처음에 방법을 쓸 때 생각했던 것보다.

1 개의 모드 딜레마는 예를 들어 UNIX를 괴롭 혔으며, 오늘날 파일 또는 디렉토리가 가능한 권한 모드는 파일 유형, 소유권 등에 따라 모드의 이상한 이중 의미를 초래할 수 있습니다.

나에게 부울이나 열거를 사용하는 것은 좋은 접근법입니다. Robert C. Martin 은이 사실을 매우 명확하게 포착합니다 클린 코드 팁 #12 : 부울 인수 제거:

부울 논쟁은이 기능이 하나 이상의 일을한다고 크게 선언합니다. 그들은 혼란스럽고 제거되어야합니다.

메소드가 둘 이상의 작업을 수행하면 예를 들어 두 가지 다른 방법을 작성해야합니다. file.append(data) 그리고 file.overwrite(data).

열거를 사용한다고해서 상황이 더 명확 해지지 않습니다. 아무것도 바꾸지 않고 여전히 깃발 논쟁입니다.

내가 나쁜 일이라는 두 가지 이유가 있습니다.

  1. 어떤 사람들은 다음과 같은 방법을 작성하기 때문에 다음과 같은 방법을 작성하기 때문입니다.

    ProcessBatch(true, false, false, true, false, false, true);
    

    매개 변수를 혼합하기가 너무 쉽기 때문에 이것은 분명히 나쁘고, 당신이 지정하는 것을 보면 전혀 모른다. 그래도 하나의 부리는 너무 나쁘지 않습니다.

  2. 간단한 예/아니오 브랜치에 의해 프로그램 흐름을 제어하면 awkard 방식으로 하나에 싸여있는 두 가지 완전히 다른 기능이 있음을 의미 할 수 있습니다. 예를 들어:

    public void Write(bool toOptical);
    

    실제로 이것은 두 가지 방법이어야합니다

    public void WriteOptical();
    public void WriteMagnetic();
    

    이들의 코드는 완전히 다를 수 있기 때문입니다. 그들은 모든 종류의 다른 오류 처리 및 검증을 수행해야 할 수도 있고 나가는 데이터를 다르게 형식화해야 할 수도 있습니다. 당신은 그것을 사용하는 것만으로 말할 수 없습니다 Write() 또는 Write(Enum.Optical) (물론 원하는 경우 내부 메소드를 writeOptical/mag를 호출 할 수 있습니다).

나는 그것이 단지 의존한다고 생각한다. 나는 #1을 제외하고 그것에 대해 너무 큰 거래를하지 않을 것입니다.

열거는 더 좋지만 부울 매개 변수를 "허용 할 수없는"것으로 부르지 않을 것입니다. 때로는 작은 부울을 던지고 계속 움직이는 것이 더 쉽습니다 (개인 방법을 생각하십시오).

부울은 Python 및 Objective-C와 같은 매개 변수를 명명 한 언어로는 괜찮을 수 있습니다. 이름은 매개 변수가 무엇을하는지 설명 할 수 있기 때문입니다.

file.writeData(data, overwrite=true)

또는:

[file writeData:data overwrite:YES]

나는 그것이 좋다는 것에 동의하지 않을 것이다 규칙. 분명히, Enum은 어떤 경우에는 더 나은 명시 적 또는 장황한 코드를 만듭니다. 그러나 일반적으로 도달하는 것 같습니다.

먼저 예를 들어 보겠습니다. 좋은 코드를 작성하는 프로그래머의 책임 (및 능력)은 부울 매개 변수를 가지고있어 실제로 위태롭지 않습니다. 당신의 예에서 프로그래머는 다음과 같은 글을 쓰면 장황 코드로 쓸 수있었습니다.

dim append as boolean = true
file.writeData( data, append );

아니면 더 일반적인 선호합니다

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

둘째 : 당신이 준 열거 예제는 당신이 const를지나 가기 때문에 "더 나은"것입니다. 대부분의 애플리케이션에서는 대부분의 시간이 적어도 일부 시간 매개 변수가 함수로 전달되지는 않지만 일부는 변수 일 가능성이 높습니다. 어떤 경우에는 두 번째 예제 (이름이 좋은 변수를 제공)가 훨씬 나아지고 Enum은 거의 이점을 거의주지 못했을 것입니다.

열거는 확실한 이점을 가지고 있지만 모든 부울을 열거로 교체하지 않아야합니다. 진실/거짓이 실제로 일어나고있는 일을 대표하는 가장 좋은 방법 인 많은 곳이 있습니다.

그러나 방법 인수로 사용하는 것은 약간 의심입니다. 단순히 그들이해야 할 일을 파헤 치지 않고 볼 수 없기 때문에, 그들이 진실/거짓이 무엇인지 알 수 있기 때문에 실제로 의미합니다

속성 (특히 C#3 객체 초기화기) 또는 키워드 인수 (LA Ruby 또는 Python)는 부울 인수를 사용하는 곳으로가는 훨씬 더 좋은 방법입니다.

C# 예 :

var worker = new BackgroundWorker { WorkerReportsProgress = true };

루비 예

validates_presence_of :name, :allow_nil => true

파이썬 예제

connect_to_database( persistent=true )

부울 메소드 논쟁이 어디에 있는지 생각할 수있는 유일한 것은 옳은 일은 속성이나 키워드 인수가없는 Java입니다. 이것이 내가 자바를 싫어하는 이유 중 하나입니다 :-(

많은 경우에 열거가 부울보다 더 읽기 쉽고 확장 가능하다는 것은 사실이지만, "부울이 허용되지 않는다"는 절대적인 규칙은 멍청하다. 그것은 융통성이없고 비생산적입니다. 그것은 인간의 판단의 여지를 남기지 않습니다. 그것들은 대부분의 언어가 유용하기 때문에 기본 내장 유형입니다. 다른 내장형 유형에 적용하는 것을 고려하십시오.

이 규칙은 버그 나 런타임 성능의 잠재력이 아닌 스타일의 문제 일뿐입니다. 더 나은 규칙은 "가독성의 이유로 부울에게 열거하는 선호"입니다.

.NET 프레임 워크를보십시오. 부울은 상당히 몇 가지 방법에서 매개 변수로 사용됩니다. .NET API는 완벽하지는 않지만 파라미터로 부울을 사용하는 것이 큰 문제라고 생각하지 않습니다. 툴팁은 항상 매개 변수의 이름을 제공하며 이러한 종류의 지침도 빌드 할 수 있습니다. 메소드 매개 변수에 대한 XML 주석을 작성하면 툴팁에 나타납니다.

또한 부울을 열거로 명확하게 리팩토링 해야하는 경우가 있다고 덧붙여 야합니다. 클래스에 두 개 이상의 부울이 있거나 방법 매개 변수가있을 때 모든 상태가 유효하지는 않습니다 (예 :이를 갖는 것이 유효하지 않습니다. 둘 다 참으로 설정).

예를 들어, 수업에 속성이있는 경우

public bool IsFoo
public bool IsBar

그리고 동시에 두 사람을 진실하게 만드는 것은 오류입니다. 실제로 가지고있는 것은 세 가지 유효한 상태이며 다음과 같은 것으로 더 잘 표현됩니다.

enum FooBarType { IsFoo, IsBar, IsNeither };

동료가 더 잘 준수하는 규칙은 다음과 같습니다.

  • 당신의 디자인에 독단적이지 마십시오.
  • 코드 사용자에게 가장 적합한 것을 선택하십시오.
  • 이번 달에 모양이 마음에 들기 때문에 별 모양의 페그를 모든 구멍으로 강타하려고 시도하지 마십시오!

부울은 프레임 워크의 기능을 확장하지 않는 경우에만 허용됩니다. 열거는 열거를 확장 할 수 있고 기능 호출의 이전 구현을 중단하지 않기 때문에 선호됩니다.

열거의 또 다른 장점은 읽기 쉽다는 것입니다.

메소드가 다음과 같은 질문을하는 경우

KeepWritingData (DataAvailable());

어디

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

부울 방법 논쟁은 절대적으로 완벽하게 이해되는 것 같습니다.

이 방법에 따라 다릅니다. 이 방법이 분명히 진실/거짓 일을하는 것이 좋으면 괜찮습니다. 예를 들어 아래는이 방법에 가장 적합한 디자인이라고 말하지는 않지만 사용법이 명백한 곳의 예일뿐입니다].

CommentService.SetApprovalStatus(commentId, false);

그러나 대부분의 경우 언급 한 예와 같이 열거를 사용하는 것이 좋습니다. .NET 프레임 워크 자체에는이 컨벤션을 따르지 않는 많은 예가 있지만,이 디자인 가이드 라인을주기에 상당히 늦게 도입했기 때문입니다.

그것은 조금 더 명확하게 만들어 지지만, 엔트리/과복과 같은 깎아 지른 부울 선택에서 과도하게 인터페이스의 복잡성을 크게 확장하기 시작합니다. 추가 옵션을 추가 해야하는 경우 (이 경우 생각할 수없는), 언어에 따라 항상 리팩터를 수행 할 수 있습니다.

열거는 확실히 코드를 더 읽기 쉽게 만들 수 있습니다. 아직도 조심해야 할 몇 가지가 있습니다 (적어도 .NET에서)

열거의 기본 저장은 int이므로 기본값은 0이므로 0이 현명한 기본값인지 확인해야합니다. (예 : structs는 생성 될 때 모든 필드가 0으로 설정되어 있으므로 0 이외의 기본값을 지정할 방법이 없습니다. 0 값이없는 경우 int에 캐스트하지 않고 열거를 테스트 할 수 없습니다. 나쁜 스타일.)

열거가 코드에 비공개 인 경우 (공개적으로 노출되지 않은 경우) 여기서 읽기를 중단 할 수 있습니다.

당신의 열거가 있다면 게시 외부 코드에 어떠한 방식 으로든 프로그램 외부에서 저장되면 명시 적으로 번호를 매기는 것을 고려하십시오. 컴파일러는 0에서 자동으로 번호를 매기지만, 열거를 값을주지 않고 재 배열하면 결함으로 끝날 수 있습니다.

합법적으로 쓸 수 있습니다

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

이를 방지하기 위해, (예 : 공개 API)를 확신 할 수없는 열거를 소비하는 모든 코드는 열거가 유효한지 확인해야합니다. 당신은 이것을 통해 이것을합니다

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

유일한 경고 Enum.IsDefined 반사를 사용하고 느린 것입니다. 또한 버전 관리 문제를 겪습니다. 열거 값을 자주 확인 해야하는 경우 다음을 수행 할 수 있습니다.

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

버전 관리 문제는 이전 코드가 가지고있는 2 개의 열거를 처리하는 방법 만 알고있을 수 있다는 것입니다. 세 번째 값을 추가하면 enum.isdefined는 사실이지만 이전 코드가 반드시 처리 할 수는 없습니다. 우회.

당신이 할 수있는 더 많은 재미가 있습니다 [Flags] 열거 및 이에 대한 검증 코드는 약간 다릅니다.

또한 이식성을 위해 전화를 사용해야합니다. ToString() 열거 및 사용 Enum.Parse() 다시 읽을 때. 둘 다 ToString() 그리고 Enum.Parse() 다룰수있다 [Flags] Enum도 마찬가지입니다. 따라서 사용하지 않을 이유가 없습니다. 당신은 또 다른 함정입니다. 이제 코드를 깨지 않으면 열거 이름을 바꿀 수 없기 때문입니다.

따라서 때로는 자신에게 물어볼 때 위의 모든 부분을 평가해야합니다. Bols만으로 도망 갈 수 있습니까?

IMHO는 열거가 2 개 이상의 옵션이 가능한 상황에 대해 명백한 선택 인 것 같습니다. 그러나 부울이 필요한 상황이 분명히 있습니다. 이 경우 나는 bool이 작동하는 열거를 사용하면 4가 할 때 7 단어를 사용하는 예가 될 것입니다.

부울은 두 가지 중 하나 일 수있는 명백한 토글 (즉, 전구의 상태)이 될 수있는 명백한 토글이있을 때 의미가 있습니다. 그 외에는 당신이 지나가는 것을 분명히하는 방식으로 글을 쓰는 것이 좋습니다. 지금 동기 쓰기를 허용하고 싶지 않더라도 (두 가지 옵션으로 제한됨), 그들이 언뜻보기에 무엇을하는지 알기 위해 더 많은 장황하게 만드는 것이 좋습니다.

즉, False and True (부울 0 및 1)를 사용할 수도 있고 나중에 더 많은 값이 필요한 경우 사용자 정의 값 (예 : 2 및 3) 및 이전 0/1 값을 지원하기 위해 함수를 확장하십시오. 코드가 깨지 말아야하므로 잘 포트를 올리십시오.

때로는 오버로드로 다른 동작을 모델링하는 것이 더 간단합니다. 예에서 계속하려면 다음과 같습니다.

file.appendData( data );  
file.overwriteData( data );

이 접근법은 여러 매개 변수가 있으면 저하되어 고정 된 옵션 세트를 허용합니다. 예를 들어, 파일을 여는 메소드는 파일 모드 (열/작성), 파일 액세스 (읽기/쓰기), 공유 모드 (없음/읽기/쓰기)의 여러 순열을 가질 수 있습니다. 총 구성 수는 개별 옵션의 직교 제품과 같습니다. 당연히 이러한 경우 여러 과부하가 적절하지 않습니다.

열거는 일부 언어 (예 : C#)에서 정확한 열거 값을 검증하는 것이 어려울 수 있지만, 경우에 따라 코드를 더 읽기 쉽게 만들 수 있습니다.

부울 매개 변수는 종종 새로운 오버로드로 매개 변수 목록에 추가됩니다. .NET의 한 가지 예는 다음과 같습니다.

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

후자의 오버로드는 첫 번째 버전의 .NET 프레임 워크에서 사용할 수있게되었습니다.

두 가지 선택만이있을 것이라는 것을 알고 있다면 부울은 괜찮을 것입니다. 기존 라이브러리는 새로운 열거 값을 지원하지 않을 수 있지만 버전화를 완전히 무시할 수는 없지만, 열거는 이전 코드를 깨뜨리지 않는 방식으로 확장 가능합니다.


편집하다

최신 버전의 C#에서는 IMO가 열거 할 수있는 것과 같은 방식으로 코드를 더 명확하게 할 수있는 이름의 인수를 사용할 수 있습니다. 위와 동일한 예제 사용 :

Enum.Parse(str, ignoreCase: true);

내가 열거가 좋은 방법이라는 데 동의하는 경우, 두 가지 옵션이있는 방법에서는 두 가지 옵션 만 열거없이 가독성을 가질 수 있습니다.)

예를 들어

public void writeData(Stream data, boolean is_overwrite)

열거를 좋아하지만 부울도 유용합니다.

이것은 오래된 게시물에 늦은 항목이며, 너무 멀리 떨어진 페이지 아래로 아무도 읽지 않을 것입니다. 그러나 아무도 이미 그것을 말하지 않았기 때문에 ....

인라인 댓글은 예상치 못한 것을 해결하는 데 먼 길을갑니다. bool 문제. 원래의 예는 특히 끔찍합니다. 함수 감소의 변수를 지정하려고한다고 상상해보십시오! 그것은 같은 것입니다

void writeData( DataObject data, bool use_append_mode );

그러나 예를 들어, 그것이 선언이라고 가정 해 봅시다. 그런 다음, 설명 할 수없는 부울 논쟁의 경우, 변수 이름을 인라인 주석에 넣습니다. 비교하다

file.writeData( data, true );

~와 함께

file.writeData( data, true /* use_append_mode */);

그것은 실제로 논쟁의 정확한 본질에 달려 있습니다. 예/아니오 또는 true/false가 아닌 경우 열거는 더 읽을 수있게합니다. 그러나 열거를 사용하면 기본 유형의 정의되지 않은 값이 전달 될 수 있으므로 인수를 확인하거나 허용 가능한 기본 동작을 가져야합니다.

예제에서 부울 대신 열거를 사용하면 메소드 호출을보다 읽을 수 있도록 도와줍니다. 그러나 이것은 메소드 호출의 인수라는 C#에서 내가 가장 좋아하는 소원 항목을 대체합니다. 이 구문 :

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

완벽하게 읽을 수 있고 프로그래머가해야 할 일을 수행 할 수 있습니다. 이는 IDE에서 어떻게 보이는지에 관계없이 메소드의 각 매개 변수에 가장 적합한 유형을 선택합니다.

C# 3.0은 생성자에서 명명 된 인수를 허용합니다. 나는 그들이 왜 방법으로 이것을 할 수 없는지 모르겠습니다.

부울 가치 true/false 뿐. 따라서 그것이 무엇을 나타내는지는 확실하지 않습니다. Enum 의미있는 이름을 가질 수 있습니다 OVERWRITE, APPEND, 등방이 더 좋습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top