Development Tip

프로그래머는 자신의 코드를 "문서화"하기 위해 부울 변수를 사용해야합니까?

yourdevel 2020. 10. 12. 08:17
반응형

프로그래머는 자신의 코드를 "문서화"하기 위해 부울 변수를 사용해야합니까?


저는 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)거나 복잡한 표현식이 필요하지 않도록 코드를 재고합니다.


임시 변수 대신 함수 / 메소드를 만드는 것이 더 낫다고 생각합니다. 이렇게하면 메서드가 짧아지기 때문에 가독성이 높아집니다. Martin Fowler의 저서 Refactoring에는 코드 품질을 개선하는 데 좋은 조언이 있습니다. 특정 예제와 관련된 리팩토링을 "Replace Temp with Query"및 "Extract Method"라고합니다.


개인적으로 이것은 좋은 습관이라고 생각합니다. 코드 실행에 미치는 영향은 미미하지만 적절하게 사용하면 제공 할 수있는 명확성은 나중에 코드를 유지 관리 할 때 매우 중요합니다.


이런 식으로 필요 이상으로 계산한다는 것을 기억하십시오. 코드에서 조건을 제거하기 때문에 항상 두 조건을 모두 계산합니다 (단락 없음).

그래서:

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

변형 후 :

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

대부분의 경우 문제는 아니지만 일부에서는 성능 저하 또는 기타 문제를 의미 할 수 있습니다 (예 : 두 번째 표현에서 첫 번째 표현이 실패했다고 가정 할 때).


메서드에 성공 알림이 필요한 경우 : (C #의 예)

bool success = false;

시작합니다. 코드를 다음과 같이 변경할 때까지 오류가 발생합니다.

success = true;

그런 다음 끝 :

return success;

당신 / 당신의 팀이 선호하는 스타일에 달려 있다고 생각합니다. "변수 소개"리팩토링이 유용 할 수 있지만 때로는 그렇지 않습니다. :)

And I should disagree with Kevin in his previous post. His example, I suppose, usable in case, when introduced variable can be changed, but introducing it only for one static boolean is useless, because we have parameter name in a method declaration, so why duplicate it in code?

for example:

void DoSomeMethod(boolean needDelete) { ... }

// useful
boolean deleteOnCompletion = true;
if ( someCondition ) {
    deleteOnCompletion = false;
}
DoSomeMethod(deleteOnCompletion);

// useless
boolean shouldNotDelete = false;
DoSomeMethod(shouldNotDelete);

In my experience, I've often returned to some old scripts and wondered 'what the hell was I thinking back then?'. For example:

Math.p = function Math_p(a) {
    var r = 1, b = [], m = Math;
    a = m.js.copy(arguments);
    while (a.length) {
        b = b.concat(a.shift());
    }
    while (b.length) {
        r *= b.shift();
    }
    return r;
};

which isn't as intuitive as:

/**
 * An extension to the Math object that accepts Arrays or Numbers
 * as an argument and returns the product of all numbers.
 * @param(Array) a A Number or an Array of numbers.
 * @return(Number) Returns the product of all numbers.
 */
Math.product = function Math_product(a) {
    var product = 1, numbers = [];
    a = argumentsToArray(arguments);
    while (a.length) {
        numbers = numbers.concat(a.shift());
    }
    while (numbers.length) {
        product *= numbers.shift();
    }
    return product;
};

I rarely create separate variables. What I do when the tests get complicated is nest the IFs and add comments. Like

boolean processElement=false;
if (elementIndex < 0) // Do we have a valid element?
{
  processElement=true;
}
else if (elementIndex==lastElementIndex) // Is it the one we want?
{
  processElement=true;
}
if (processElement)
...

The admitted flaw to this technique is that the next programmer who comes along may change the logic but not bother to update the comments. I guess that's a general problem, but I've had plenty of times I've seen a comment that says "validate customer id" and the next line is examining the part number or some such and I'm left to wonder where the customer id comes in.

참고URL : https://stackoverflow.com/questions/2478138/should-programmers-use-boolean-variables-to-document-their-code

반응형