[boolean] 프로그래머는 코드를 “문서화”하기 위해 부울 변수를 사용해야합니까?

저는 McConell의 Code Complete를 읽고 있으며 그는 부울 변수를 사용하여 코드를 문서화하는 방법에 대해 설명합니다. 예를 들어, 대신 :

if((elementIndex < 0) || (MAX_ELEMENTS < elementIndex) ||
   (elementIndex == lastElementIndex)){
       ...
}

그는 다음과 같이 제안합니다.

finished = ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
repeatedEntry = (elementIndex == lastElementIndex);
if(finished || repeatedEntry){
   ...
}

이것은 저에게 논리적이고 좋은 관행이며 매우 자기 문서화라는 인상을줍니다. 그러나 나는 거의 본 적이 없기 때문에이 기술을 정기적으로 사용하는 것을 주저합니다. 희귀하다는 이유로 혼란 스러울 수도 있습니다. 그러나 내 경험은 아직 그다지 방대하지 않기 때문에이 기술에 대한 프로그래머의 의견을 듣고 싶습니다. 누군가이 기술을 정기적으로 사용하는지 아니면 코드를 읽을 때 자주 본 적이 있는지 알고 싶습니다. 이것이 채택 할 가치있는 컨벤션 / 스타일 / 기술입니까? 다른 프로그래머가 이해하고 감사할까요, 아니면 이상하다고 생각할까요?



답변

너무 중첩되고 복잡한 표현식을 지역 변수에 할당 된 더 간단한 하위 표현식으로 분할 한 다음 다시 합치는 것은 매우 일반적이고 널리 사용되는 기술입니다. 하위 표현식 및 / 또는 전체 표현식이 부울인지 다른 유형에 대해. 잘 선택된 이름을 사용하면 이런 종류의 세련된 분해가 가독성을 높일 수 있으며, 좋은 컴파일러는 원래의 복잡한 표현과 동일한 코드를 생성하는 데 문제가 없어야합니다.

Haskell과 같이 그 자체로 “할당”이라는 개념이없는 일부 언어는 “부 표현식에 이름 제공”기술 ( where하스켈 의 절) 을 사용할 수 있도록 특수 구조를 도입 하기도합니다. 문제의 기술에 대한 인기!-)


답변

일반적으로 부울 논리를 재사용 가능한 메서드로 래핑하지만 (여러 위치에서 호출되는 경우) 사용했습니다.

가독성을 높이고 논리가 변경되면 한 곳에서만 변경하면됩니다.

다른 사람들은 그것을 이해하고 이상하다고 생각하지 않을 것입니다 (즉, 수천 줄 함수를 작성하는 사람들을 제외하고).


답변

가능한 한 그렇게하려고합니다. 물론, 코드의 “추가 라인”을 사용하고 있지만 동시에 두 값을 비교하는 이유를 설명하고 있습니다.

귀하의 예에서 저는 코드를보고 스스로에게 “값이 0보다 작은 이유를 보는 사람이 무엇입니까?”라고 자문합니다. 두 번째에서 당신은 이것이 발생했을 때 일부 프로세스가 완료되었음을 분명히 말하고 있습니다. 두 번째 질문에서는 당신의 의도가 무엇인지 추측하지 마십시오.

저에게 가장 큰 것은 다음과 같은 방법을 볼 때 DoSomeMethod(true); 입니다. 자동으로 true로 설정되는 이유는 무엇입니까? 다음과 같이 훨씬 더 읽기 쉽습니다.

bool deleteOnCompletion = true;

DoSomeMethod(deleteOnCompletion);


답변

제공된 샘플 :

finished = ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
repeatedEntry = (elementIndex == lastElementIndex);
if(finished || repeatedEntry){
   ...
}

가독성을 높이고 부울 논리를 보존하는 메서드를 사용하도록 다시 작성할 수도 있습니다 (Konrad가 지적했듯이).

if (IsFinished(elementIndex) || IsRepeatedEntry(elementIndex, lastElementIndex)){
   ...
}

...

private bool IsFinished(int elementIndex) {
    return ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
}

private bool IsRepeatedEntry(int elementIndex, int lastElementIndex) {
    return (elementIndex == lastElementIndex);
}

물론 두 가지 추가 방법 인 대가가 따릅니다. 이 작업을 많이 수행하면 코드를 더 읽기 쉽게 만들 수 있지만 클래스의 투명성은 떨어집니다. 그러나 다시 추가 메서드를 도우미 클래스로 이동할 수도 있습니다.


답변

이것이 잘못되는 것을 볼 수있는 유일한 방법은 부울 조각에 의미가있는 이름이없고 어쨌든 이름이 선택되는 경우입니다.

//No clue what the parts might mean.
if(price>0 && (customer.IsAlive || IsDay(Thursday)))

=>

first_condition = price>0
second_condition =customer.IsAlive || IsDay(Thursday)

//I'm still not enlightened.
if(first_condition && second_condition)

“모든 코드에 주석 달기”, “3 개 이상의 부분이있는 모든 if- 기준에 명명 된 부울 사용”과 같은 규칙을 만드는 것이 일반적이기 때문에 다음과 같은 의미 상 비어있는 주석 만 가져 오는 것이 일반적이기 때문에 이것을 지적합니다.

i++; //increment i by adding 1 to i's previous value


답변

이렇게함으로써

finished = ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
repeatedEntry = (elementIndex == lastElementIndex);
if(finished || repeatedEntry){
   ...
}

뇌 에서 논리 를 제거하고 코드에 넣습니다. 이제 프로그램 당신이 의미하는 바를 알고 있습니다. 이름을
지을 때마다 물리적 표현 을 제공합니다 . 존재합니다.
조작하고 재사용 할 수 있습니다.

전체 블록을 술어로 정의 할 수도 있습니다.

bool ElementBlahBlah? (elementIndex, lastElementIndex);

그 기능에서 (나중에) 더 많은 일을합니다.


답변

표현식이 복잡하면 bool예 를 반환하는 다른 함수로 이동 isAnEveningInThePubAGoodIdea(dayOfWeek, sizeOfWorkLoad, amountOfSpareCash)하거나 복잡한 표현식이 필요하지 않도록 코드를 재고합니다.