주석 처리 된 짧은 고급 코드 대 주석 처리되지 않은 더 긴 이해하기 쉬운 코드-선호되는 것은 무엇입니까?


18

때때로 알고리즘은 두 가지 방식으로 작성 될 수 있습니다.

  • 짧고 멋진 길; 또는
  • 더 길고 이해하기 쉬운 방법.

예를 들어, C에서 문자열 source을 복사하는 길고 쉬운 방법은 dest다음과 같습니다.

*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);

여기에 짧고 멋진 방법이 있습니다.

// Copy string source to dest
while (*dest++ = *source++);

나는 항상 멋진 코드를 피해야한다는 말을 듣고 읽었으며 동의하는 경향이 있습니다. 그러나 의견을 고려하면 어떻게 될까요? 위의 예에서와 같이 주석 처리되지 않은, 더 길고 이해하기 쉬운 코드와 잘 작성된 짧고 멋진 코드가 있다고 가정하십시오. 비 팬시 코드가 여전히 선호됩니까?

편집 : 많은 사람들이 변수 이름에 대해 언급 했으므로 다른 예제를 선호 할 때 그 요소를 고려하지 않도록 예제 코드를 수정했습니다. 첫 번째 예제에서 이중 할당을 제거하려고 시도했지만 코드를 읽기 어렵게 만들었습니다.

아마도 많은 사람들이 '팬시'코드가 더 긴 코드보다 더 읽기 쉽고 이해하기 쉽기 때문에 이것이 최상의 예가 아닐 수도 있습니다. 아이디어는 매우 짧지 만 복잡한 코드보다 이해하기 훨씬 쉬운 하나의 긴 코드를 갖는 것이 었습니다.

EDIT2가 : 저는 여기에서 가져온 새로운 examle의 SO :

멋진 버전의 댓글 :

//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );

주석 처리되지 않은 긴 버전 :

int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}

2
@gablin : "goodly"는 한 단어이지만 "good"과 약간 다른 의미의 형용사이며 더 이상 널리 사용되지 않습니다 (적어도 미국에서는) "good"의 부사 형식은 "well" "잘 주석 처리 된 코드"와 같이
John M Gant

@ 존 : 물론 그렇습니다. 그에 따라 질문을 업데이트했습니다. 감사.
gablin

2
숏 웨이 '팬시'는 어떤 식으로? 그것은 C를 알고 있다고 주장하는 사람이라면 누구나 문제없이 읽을 수 있어야하는 C 코드의 교과서입니다. 간결함은 '공상'을 의미하지 않습니다.
JBR 윌킨슨

@JBRWilkinson : 질문의 수정 된 부분에서 말했듯이이 예제는 "팬시"버전이 그렇게 멋진 것은 아니기 때문에 좋은 예가 아닙니다. 목표는 주석이 있지만 짧고 이해할 수없는 방법을 사용하고 주석이없는 길지만 훨씬 더 읽기 쉬운 방법을 사용하는 것이 었습니다.
gablin

@gablin : 편집 한 내용이 현재 답변을 손상시킵니다.
Maniero

답변:


28

나는 일반적으로 멋진 코드를 자체 방법으로 추출하는 것을 선호합니다.

멋진 코드에 주석을 달기보다는 메소드 이름만으로도 명확 해집니다.

char *copy_string(char *s, const char *t) {    
    while (*s++ = *t++); 
    return s;
}

3
좋은 지적입니다. 자체 포함 코드를 제거하는 것이 주석보다 훨씬 낫습니다. 컴파일러는 필요한 경우 인라인하는 방법을 알고 있습니다.
dbkk

아, 그래, 그 말을 쓸모 없게 만드는 좋은 방법입니다. 그러나 이것에도 불구하고 항상 더 긴 코드보다 멋진 코드를 선호합니까?
gablin

일반적으로 그렇습니다. 짧고 이름이 잘 알려진 메소드는 코드를보다 쉽게 ​​읽고 유지 관리 할 수 ​​있다고 생각합니다. 고유 한 방법으로 계산 된 복잡성은 재사용을보다 접근 가능하고 명백하게 만듭니다. 예외는 항상 있으며 궁극적으로 항상 코드에 따라 다릅니다.
Mongus Pong

분명히 함수의 이름은 'strcpy'?
JBR 윌킨슨

해당 코드에 오류가 있습니다. 무엇을 반환합니까? 무엇을 돌려 주어야합니까? 그냥 무효화 방법으로 만들고 그것으로 끝내십시오;)
Christian Mann

10

나는 더 긴 버전입니다. 일부 프로그래머가 읽기가 더 어렵다는 점을 제외하고는 짧은 버전의 코드 문제는 대부분 코드를보기 만하면 실수를 발견하기가 어렵다는 것입니다.

실제 사례가 있습니다. 우리 제품에는 다음과 같은 코드 스 니펫이 있습니다.

if (++someCounter < MAX_VALUE) {
    // Do something that has to be done only MAX_VALUE times
}

이 코드는 처음에는 완벽하게 합리적으로 보이지만, 오랜 시간이 지나면이 카운터가 오버플로되어 조건을 위반합니다 (실제 시나리오에서는 고객의 생산 시스템을 OOM으로 분쇄했습니다). 이 코드는 "정교하지는 않지만"수행해야 할 작업을 수행하는 것이 분명합니다.

if (someCounter < MAX_VALUE) {
    ++someCounter;
    // Do whatever it is we came here for
}

그리고이 코드를 작성한 개발자는 충분하지 않다고 말할 수 있습니다 (사실은 그렇지는 않지만 다소 밝은 사람입니다). 코드를 올바르게 얻으려면 뭔가 잘못하고 있습니다. 귀하의 코드는 가능한 한 현명하고 현명하지 않은 사람을 위해이 코드를 유지해야하는 사람을 위해 가능한 한 완벽해야합니다.

그래서-나는 단순성과 명확성을 위해 모두입니다.

편집 : 아, 그리고 의견에 관해서는 중요하지 않습니다. 많은 사람들이 어쨌든 주석을 읽지 못하고 ( http://www.javaspecialists.co.za/archive/Issue039.html ) 주석없이 코드를 이해하지 못하는 사람들은 주석을 충분히 이해하지 못하므로 그것을 유지할 수 있습니다. 도움말 사람들이 할 수있는 목표는 코멘트 그게 도움이되지 수, 즉 특정 코드가 "올바른"입니다.


1
"고객의 생산 시스템을

"일부 프로그래머가 읽기가 더 어렵다는 점을 제외하고는 짧은 버전의 코드 문제"-모든 코드는 "일부 프로그래머에게는"읽기가 어려울 수 있습니다. 멍청한 프로그래머를 찾아야합니다. 코드를 가장 낮은 분모로 멍청하게 만들지 마십시오.
quant_dev

@quant_dev : 반대로, "디버깅은 처음에 코드를 작성하는 것보다 두 배나 어렵습니다. 따라서 코드를 최대한 영리하게 작성하면 정의에 따라 디버그하기에 충분히 똑똑하지 않습니다." — Brian W. Kernighan
Michael Borgwardt

@MichaelBorgwardt 나는 가능한 모든 상황에 Kernighan의 dictum을 맹목적으로 적용하지 않을 것입니다. OPs 예제는 "가능한 한 영리하게"작성된 기능이지만 디버깅이 필요한 경우 디버깅하기가 매우 쉽습니다. 반면에 복잡한 비트 트위들 링 oneliners는 매우 영리하지만 디버그하기가 더 어려울 것입니다. (또한 Kernighan은 코딩 기술 = 디버깅 기술이라고 가정합니다. 반드시 그런 것은 아닙니다. 필자가 쓸 수 없었던 코드를 성공적으로 디버깅했습니다.)
quant_dev

6

나는 일반적으로 더 긴 버전을 선호합니다. 떠오르는 두 가지 주요 이유 :

  • 더 많은 사람들이 적은 노력으로 그것을 이해 할 가능성이 높습니다 (이 문자열 사본과 같은 "표준"예가 아니라고 가정).
  • 개별 명령문에 중단 점을 배치하고 디버거를 사용하여 단계별로 진행할 수 있습니다.

두 세계를 최대한 활용하려면 코드를 함수로 묶으십시오.이 함수의 이름은 다음과 같습니다.

void copy_string(char *s, char *t)
{
    *s = *t;
    while (*t != '\0') {
        t++;
        s++;
        *s = *t;
    }
}

이를 수행하지 않는 유일한 이유는 성능이 문제였으며 프로파일 링이 실제로 함수 오버 헤드가 중요한 것으로 나타났기 때문입니다.


1
인라인이 아닌가?
Antsan

실제로 인라인에는 헤더 파일에 함수 본문을 노출 해야하는 것과 같은 자체 문제가 있습니다. 어쨌든 현명한 컴파일러는 자동으로 합리적인 위치에 자동으로 인라인하지 않습니까?
Paul Stephenson

4

가장 명확한 것은 무엇이든. 종종 두 번째 예제와 같이 주석이 필요없는 이해하기 쉬운 코드 스 니펫입니다.

독자가 한 번에 머리에 두는 것이 적기 때문에 일반적으로 짧은 코드 스 니펫은 이해하기 쉽습니다. 분명히, 코드가 지나치게 난독 화 될 때 한계가 있으며, 공백을 강화하는 선명도를 다듬어야한다는 의미는 아닙니다.

주석은 코드에서 명백한 내용을 언급해서는 안되며, 독자가 동일한 내용을 두 번 읽게 만듭니다. 나에게 첫 번째 스 니펫은 설명이 필요합니다. 개발자 do...while가 중복 된 *s = *t;할당 을 제거하기 위해 루프를 사용하지 않은 이유는 무엇 입니까? 문자열 복사본을 구현하고 있음을 깨닫기 위해 더 많은 코드를 구문 분석해야합니다. 주석은 짧은 코드보다이 긴 코드에 더 유용합니다.

두 번째 스 니펫에 대한 주석은 while 루프가 실제로 관용적이기 때문에 거의 중복되지 않지만 코드 자체가 코드보다 높은 수준에서 수행하는 것은 유용한 주석입니다.


개발자 (me)는 do ... while내가 질문을 쓸 때 그것을 생각하지 않았기 때문에 단순히 사용 하지 않았습니다. 지적 해 주셔서 감사합니다. ^^ 두 번째 스 니펫은 당신에게 명백 할 수도 있지만, 그것은 저에게는 아닙니다.
gablin

4

문제는 short fancy code프로그래머 수준에 크게 의존하기 때문에 명확한 정의가 없다는 것입니다 . 어떤 사람들은 while(*s++ = *t++);표현을 이해하는데 아무런 문제가 없지만 다른 사람들은 그렇게 할 것입니다.

개인적으로 나는 while(*s++ = *t++);완벽하게 읽을 수 있고 더 길면 더 읽기 어렵습니다. 그러나 다른 사람들은 동의하지 않을 수 있습니다.

어쨌든, 그것은 상식을 사용하는 문제입니다. 가독성은 분명히 우선 순위가되어야하지만 코드가 길어질수록 코드를 읽을 수 없게되는 시점이 있습니다. 자세한 정보는 종종 내 경험의 가독성을 감소시킵니다.


이러한 답변 중 많은 주제의 주제는 "개발자가 C로 strcpy ()를 작성하는 표준 방법을 인식하지 못할 수 있습니다"라는 것입니다.
AShelly

해서는 안됩니다-더 이상 좋은 프로그래머가 없다는 것을 의미하지는 않습니다. a) 더 이상 C를 가르치지 않고 b) C의 강도도 약점이라는 것을 의미합니다. C에서 연습 할 수있는 사람은 꽤 신비
롭고

그래서 우리는 일상 업무에 또 다른 도전을합니다. 코드 검토가 건설적인 상태로 유지되도록 직접 동료의 일반적인 언어 이해 수준을 추측해야합니다. "올바른", 더 명확한 의도 표현 인 전투에 빠지지 마십시오.
frogstarr78

2

나는 대부분의 다른 답변에 동의하지 않아야합니다. (적어도이 경우) 더 짧은 코드가 더 좋다고 생각합니다. 귀하의 주장과 달리, 더 긴 코드는 적어도 독자 에게는 "더 간결 하지 " 않습니다 . 코드가 이해하기 어렵거나 올바른 작동을 보장하기는하지만 더 길어지고 싶을 것 같습니다.

특히 루프 외부에서 문자열의 첫 번째 바이트를 다른 바이트에 대한 할당과 별도로 할당 하면 모든 바이트가 올바르게 복사되도록 읽기에 훨씬 더주의를 기울여야합니다. 짧은 버전의 기본 동작 순서는 훨씬 쉽게 확인할 수 있습니다. 유일한 문제는 서식에 있습니다. 의도적으로 비어있는 루프 본문이있는 경우 다음과 같이 명확하게하는 것이 가장 좋습니다.

while (*dest++ = *source++)
    ;

또는:

while (*dest++ = *source++)
    ; /* no body */

일부 사람들은 대신 중괄호를 사용하는 것을 선호합니다.

while (*dest++ = *source++)
    {}

원하는 정확한 형식에 관계없이 다음과 같은 문제로 인해 많은 실수가 발생했습니다.

if (x>y);
     x = z;

... 1) 흐름 제어에 의해 실제로 제어되는 것이 분명하고 2) 코드에 의해 제어되는 것을 알고 코드를 작성했음을 분명히하는 것이 중요합니다. 따라서 읽는 사람은 시간을 낭비하지 않습니다. 그들이 방금 버그를 발견했는지 알아 내기 위해.


예,이 특정 예를 되돌아 보면 '팬시'버전은 아마도 더 긴 버전보다 더 읽기 쉽습니다. 더 좋은 예를 생각할 수 있다면 지금은 할 수 없습니다. 그러나 나는 더 이상 길을 벗어나지 않았다. 그것은 적어도 처음에는 문자열 사본을 쓰는 방법이다. 최선의 방법은 아니지만 의도적으로 필요 이상으로 길게 만들지는 않았습니다.
gablin

2
Keep it simple, stupid!

확인 다른 프로그래머는 코드가 않습니다 및 더 나은 것이 있다면 무엇인지 이해할 수 한 눈에 (좋은 이름과 의견이 자신에 온 곳이다).

멋진 비트 꼬기 쿵푸와 인라인 어셈블리는 모두 (아마도 불필요하고 조기에 최적화 된) 최적화라는 이름에서 훌륭하지만 2 개월 후 버그를 발견했을 때 작성한 코드 이해할 수 없을 때도 있습니다. 요점은 무엇입니까? 시간과 노력이 필요합니다.

나는 종종 이런 상황에서 파이썬선을 언급합니다 . 특히:

Explicit is better than implicit.
Simple is better than complex.

1

프로덕션 소프트웨어에 멋진 코드를 작성하지 마십시오. 실제로 쓸 수있어서 기분이 좋으며 더 짧습니다. 멋진 코드를 작성하면 "WTF / 분"값이 크게 증가합니다. 즉, 품질이 저하됩니다.

대체 텍스트


1

물론 그것은 전적으로 상황에 달려 있습니다. 그러나 일반적으로 이것이 좋은 경험 법칙이라고 생각합니다.

디버깅은 처음에 코드를 작성하는 것보다 두 배나 어렵습니다. 따라서 코드를 최대한 영리하게 작성하면 정의에 따라 코드를 디버깅하기에 충분히 똑똑하지 않습니다.

~ 브라이언 커니 건


더 컴팩트 한 KISS 약어 보다 길지만 더 의미 있고 우아 합니다. 아이러니가 없어지지 않기를 바랍니다. p
violet313

0

내 경험상 짧은 멋진 코드 측면에서 가장 큰 승리는 반복보다는 재귀를 사용하는 경향이 있습니다. 어쨌든 모든 것이 재귀 적 인 언어로 작업하지 않는 한 코드를 한눈에 이해하는 것이 가장 어려운 것 중 하나입니다. 나는 그것이 제공하는 우아함과 속도에 대해 여전히 선호하지만, 미래의 유지 보수 자 또는 내 미래의 자아에게 불투명 할 것 같으면 자세한 의견을 남기려고 노력합니다.


0

나는 의견을 믿지 않기 시작했다. 너무 자주, 코드가 업데이트 될 때 주석이 업데이트되지 않고, 상당히 오래되었거나 더 이상 관련이없는 클라이언트 / 관리의 규칙을 나타냅니다.

주석이 더 이상 설명하는 코드와 일치하지 않는 경우가 있습니다.

내가 이해하기 위해 짧거나 공상과 더 길고 간결한 것을 선택해야한다면, 정말로 좋은 이유 가 없다면 항상 후자를 선택합니다 .


0

가독성과 유지 보수성이 중요하며, 두 번째 예 (더 긴 것)가 훨씬 더 중요합니다. 그러나 왜 자신을 두 가지 옵션으로 제한합니까? 더 긴 코드조차도 더 복잡하지 않기 때문에 너무 복잡합니다 (IMHO). 적절한 Javadoc (또는 무엇이든)과 적절한 메소드 이름을 사용하여 자체 메소드에 넣었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.