어떻게 또는 무엇을 대신하는 이유를 알려주는 의견의 예는 무엇입니까? [닫은]


78

우선,이 질문에서 나는 소스 코드 주석이 좋은지 나쁜지에 대한 논쟁에서 벗어나고 싶습니다. 나는 사람들이 왜, 무엇을 또는 ​​어떻게 말하는지를 언급 ​​할 때 사람들이 무엇을 의미하는지 더 명확하게 이해하려고 노력하고 있습니다.

우리는 종종 "의견은 왜 당신에게 말해야하는지, 코드 자체는 어떻게 당신에게 말해야하는지"와 같은 지침을 보게됩니다. 추상적 수준에서 진술에 동의하는 것은 쉽다. 그러나 사람들은 보통 이것을 도그마처럼 버리고 추가 설명없이 방을 나갑니다. 사람들이 캐치 프레이즈에 동의 할 수있는 것처럼 보이는 여러 장소와 환경에서 이것을 사용하는 것을 보았습니다.

따라서 질문으로 돌아가서 : 의견이 왜 당신에게 말해야한다면, 우리가 무엇을 이야기하고 있는가? 이것이 코드 조각이 처음 존재하는 이유입니까? 이것이 그 조각 코드가 해야하는 일입니까? 누군가가 명확한 설명을하고 좋은 예제를 추가 할 수 있다면 정말로 감사하겠습니다. (나쁜 예제는 실제로 필요하지 않지만 대조를 위해 자유롭게 추가 할 수있었습니다).

의견이 좋은지 나쁜지에 대한 많은 질문이 있지만, 왜 당신에게 좋은지에 대한 좋은 예가 무엇인지에 대한 구체적인 질문을 다루는 사람은 없습니다.


36
때때로 가장 좋은 의견은 왜 그렇지 않습니까? 한 번은 쉽게 단순화 될 수있는 복잡한 코드가 발생했습니다. 이 의견은 왜 특정 개발자가 명백한 단순화가 작동하지 않았는지 설명했다 (원래 개발자가 이미 시도했기 때문에).
Dan Pichelman

6
There are many questions on whether comments are good or bad, but no one that addresses the specific question of what are good examples of comments that tell you WHY. 모두가 올바른 예를 제시하면 모두 정답입니다. 이 웹 사이트의 형식은 모든 답변이 동일하지 않은 Q & A 프로세스를 용이하게하기위한 것입니다.
David Kaczynski

좋은 지적입니다, @ david-kaczynski. 당신은 무엇을 제안합니까?
rick

1
내 머리 위로, 나는 하나의 예 또는 일반화 된 전술이 "최고의"답변이 될 수 있도록 질문을 표현하는 방법을 생각할 수 없다. p.se의 채팅 부분이 있습니다 : chat.stackexchange.com/rooms/21/the-whiteboard 하지만 아마도 귀하의 질문에 대한 더 나은 포럼이있을 것입니다. 공평하게, 귀하의 질문이 커뮤니티의 긍정적 인 반응을 얻고있는 것처럼 보이므로 걱정할 필요가 없습니다. 유용한 의견의 예를 찾기 위해 내가 할 수있는 가장 좋은 조언은 인기있는 공개 git 저장소를 탐색하는 것입니다.
David Kaczynski

답변:


62

가장 일반적이고 가장 독특한 예는 다양한 해결 방법에 대한 주석입니다. 예를 들면 다음과 같습니다.

https://github.com/git/git/blob/master/compat/fopen.c :

/*
 *  The order of the following two lines is important.
 *
 *  FREAD_READS_DIRECTORIES is undefined before including git-compat-util.h
 *  to avoid the redefinition of fopen within git-compat-util.h. This is
 *  necessary since fopen is a macro on some platforms which may be set
 *  based on compiler options. For example, on AIX fopen is set to fopen64
 *  when _LARGE_FILES is defined. The previous technique of merely undefining
 *  fopen after including git-compat-util.h is inadequate in this case.
 */
#undef FREAD_READS_DIRECTORIES
#include "../git-compat-util.h"

Git 및 Linux 소스에서 더 많은 예제를 찾을 수 있습니다. 두 프로젝트 모두이 규칙을 따르려고합니다.

또한 커밋 로그를 사용 하여이 규칙을 더욱 엄격하게 따르는 것이 좋습니다 . 코드 주석의 경우 코드를 수정하지만 주석을 업데이트하는 것을 잊지 마십시오. 일반적인 프로젝트의 코드 양으로 조만간 발생할 수 있습니다. 반면 커밋 로그는 특정 변경 사항에 연결되며 버전 제어 시스템의 "주석"/ "비난"기능을 사용하여 다시 호출 할 수 있습니다. 다시 Git과 Linux에는 좋은 예가 있습니다.

예를 들어이 커밋을보십시오 . (여기서 복사하지 않으면 너무 깁니다). 여기에는 정확히 무엇이 잘못되었는지, 왜 잘못되었는지, 왜 잘못되었는지를 설명하고 거의 모든 SIX 라인을 수정하고 설명하는 거의 전체 페이지를 차지하는 4 개의 단락이 있습니다. 그들은 다음과 같은 두 가지 목적으로 주석을 사용합니다.

  1. 제출 된 모든 변경 사항을 검토하고 커밋 로그는 검토 자의 변경 사항을 설명해야합니다.
  2. 버그가 발견되면 "pickaxe"또는 "blame"을 사용하여 관련 로그를 검색하여 이전의 잘못된 동작으로 되돌아 가지 않도록합니다.

(참고 :이 두 가지 예를 생각해 내기 위해 git repo를 무작위로 탐색하는 데 최대 10 분이 걸렸으므로 더 쉽게 찾을 수 있습니다)


29

을 설명 주석 이유 코드 뒤에 이유를 설명 - 예를 들면 :

// We need to sync the values if the temp <doodad> GUID matches one of the active <doodad>'s
// GUID, as the temp <doodad> has the most recent values according to the server and said 
// values might have changed since we added the <doodad>. We want a user to be able to <foo> 
// the <doodad> whenever, which means those values must be accurate.
for (doodad in doodads) {
    if ([doodad guid] == [tempDoodad guid]) {
        [doodad updateFromDoodad:tempDoodad];
        break;
    }
}

을 알려줍니다 주석은 어떻게 코드가 무엇을하는지 설명합니다.

// Loop through our <doodads> and check for a GUID match. If it matches, copy the new values
// on the <doodad> that matches 
for (doodad in doodads) {
    if ([doodad guid] == [tempDoodad guid]) {
        [doodad updateFromDoodad:tempDoodad];
        break;
    }
}

차이점은 관리자가 첫 번째를보고 "아, 이것이 구식 일 수 있습니다!"라고 말할 수 있다는 것입니다. 두 번째 경우, 유지 관리자는 코드 자체가 공개하지 않은 것을 알려주지 않는 주석을 가지고 있습니다 (좋은 변수 이름을 가정).

다음은 게이트웨이 주소 (또는 합리적인 추측)를 얻는 데 필요한 일부 iOS 코드에서 왜 주석에 대한 실제 사례입니다. 나는 "수신 소켓 초기화"와 같은 말을 남겼지 만, 관리자에게 (또는 미래에) 나에게 무슨 일이 있었는지 알려줄 것이다. 처음.

/*
 We're going to do something really hacky here and use a custom partial
 implementation of traceroute to get our gateway IP address.

 [rant removed - irrelevant to the point]

 There's no good way to get at the gateway address of an iDevice
 right now. So, we have two options (per https://devforums.apple.com/message/644915#644915 ):
 1. Get at and parse the routing table (like netstat -rn, or route -n)
 2. Do a traceroute and grab the IP address for the first hop

 As far as I can tell, the former requires <sys/route.h> from the Mac OS X
 header files, which doesn't seem like a good idea to me. Also, there's a
 thread on the Apple Developer forums that seems to imply that header isn't
 in iOS for a reason (https://devforums.apple.com/message/774731#774731 ).

 So when we send our request with a TTL of one it will survive a single hop
 to the router and return, triumphant, with the router's IP address!

 Viva la kludge!

 PS: Original source was the below SO question, but I've modded it since then.
 http://stackoverflow.com/questions/14304581/hops-tracing-ttl-reciveform-on-ios/14304923#14304923
 */

// Default to using Google's DNS address. We used to try checking www.google.com
// if reachability reported we had internet, but that could still hang on routers
// that had no internet connectivity - not sure why.
const char *ip_addr = [kGoogleDNS UTF8String]; // Must be const to avoid undefined behavior
struct sockaddr_in destination,fromAddr;
int recv_sock;
int send_sock;

// ... more code follows

4
첫 번째 예는 지나치게 장황하며 많은 "방법"을 포함합니다. "단순한 <doodad>에서 <doodads>를 업데이트하여 사용자가 언제라도 안전하게 <foo> 할 수 있도록"합니다. 나머지는 이것 또는 코드에서 암시하는 것이 쉽지 않습니다. 또한 마지막 예의 첫 네 단락에서 "동화 소개"는 전혀 의미가 없습니다. 나는 "Viva la kludge!"; 재미 있고 결국 끝났습니다. 그러나 시작은 실제 설명에 도달하기 전에 파헤쳐 야 할 단어가 너무 많습니다.
Jan Hudec

@JanHudec 의견에 따라 조정되었습니다. 맞습니까?
thegrinner

15
두 번째 예에서 좋은 점 중 하나는 코드가 특정 방식으로 작동하는 이유를 설명 할뿐만 아니라 다른 합리적인 대안을 취하지 않은 이유도 설명한다는 것입니다. 다음 코드를 읽고 "왜 라우팅 테이블을 구문 분석 할 수 없는가?"라고 생각하기 때문에 코드의 유지 관리가 훨씬 쉬워집니다. 댓글을 읽을 수 있습니다. 또한, 누군가 않는 코드를 변경하는 정당한 이유를 가지고 올은 그렇게하는 것이 안전하다고 자부 할 것이다. 그렇지 않으면 관리자는 kludge에 영감을 준 (알 수없는) 시나리오에서 변경이 실패 할 것을 두려워합니다.
Brian

18

Jeff Atwood의 블로그 게시물 코드 에서 인용 한 방법으로 의견 을 시작하고 싶습니다 .

가장 좋은 종류의 의견은 필요하지 않은 의견입니다.

그는 또한 다음과 같이 말합니다.

먼저 목발로 의견에 의존하지 않고 코드를 이해하기 쉽게 작성하도록 노력해야합니다. 코드를 이해하기 쉽게 만들 수없는 지점에서만 주석을 추가해야합니다.

나는 완전히 동의 하고이 시점에서 코드를 가능한 한 간단하게 만들기 전에 코드를 작동시킨 다음 리팩토링을 시작해야한다고 덧붙여 야합니다. 따라서 리팩토링하기 전에 첫 실행 중에 주석 이 많은 도움이되는 이유를 추가했습니다 .

예를 들어, 데이터를 구문 분석하는 동안 평일 테이블을 채우기 위해 2 차원 해시 테이블이있는 3 개의 중첩 루프를 사용하는 경우 몇 주 동안 보지 않고 갑자기 리팩토링하면 누군가 또는 심지어 자신이 수행 한 작업을 잃어 버리기가 매우 쉽습니다.

[loop1]6oclock -> [loop2]Monday -> [loop3]stage 1 to 4
         -> tuesday-> stage 1 to 4
         ...
         -> Saturday -> stage 1 to 4
    7oclock -> Monday-> stage 1 to 4
        ....etc.

위는 리팩토링 전에 3 개의 중첩 루프가 작동하는 방법의 예입니다.
또한 일부 분기 조건을 설명하면 프로세스에서 생각한 내용으로 코드를 훨씬 잘 이해할 수 있습니다.

// added a zero before the actual day in order for the days always to be 2 digits long.
if( actualDayFuture < 10 ) 
{ 
     actualDayFuture = padIfSingleDigitDate(actualDayFuture); 
}

간단하고 명백한 코드조차도 주석과 잘 작동합니다. 동료들과 심지어 자신이 소프트웨어를 유지 관리하는 데있어 좀 더 명확하고 명확하거나 이해하기 쉽게 만드는 것입니다.

물론 XP는 자체 설명하는 코드를 가지고 있지만 한 줄 주석이 아프지 않습니까?

또한이 블로그 의 다음 규칙이 매우 유용 하다는 것을 알았습니다 .

  • 쓰기 전에 자료 이해
  • 잠재 고객이 4 학년 인 것처럼 작성
  • 독자들이 당신을 어떻게 잘못 해석 할 수 있는지 생각해보십시오

자신의 코드 또는 다른 사람이나 레거시 코드로 돌아 가야하는 사람은 그것이 두통이 될 수 있다는 것을 알고 있습니다. 그래서 게 으르거나 아무 것도 언급하지 않는 것에 대해 우버 코더가 되려고 노력하는 대신, 자신이나 코드를 유지 해야하는 나쁜 버거를 만들지 말고 인용 된 규칙을 따르면 미래의 삶을 훨씬 쉽게 만듭니다.

또한 많은 프로그래밍 결정이 검토 중에 의심스러워하며 코드가 몇 년 동안 사용되면서 발견 된 주요 버그로 인해 일부 코드 섹션이 프로그램이 작동하는 데 필수적인 경우에도 일부 부분이 작성된 이유를 항상 명확하지는 않습니다. . 따라서 acmqueue 의 마지막 따옴표로 가까운 tl; dr로 완전히 당신을 낳지 않으려면 :

이전의 명확하고 광범위한 문서는 생존하고 적응할 수있는 소프트웨어를 만드는 데있어 핵심 요소입니다. 높은 표준으로 문서화하면 개발 시간이 단축되고 작업이 향상되며 수익이 향상됩니다. 어떤 기술보다 더 많이 요구하기는 어렵습니다.


8
두 번째 예에서는 리팩토링을 통해 주석을 모두 제거 할 수 있습니다. actualDayFuture = padIfSingleDigitDate (actualDayFuture); 이것은 사소한 것이지만보다 강력한 예는이 접근 방식의 이점이 있습니다.
Chris Cudmore

4
조건부도 메소드로 옮겼을 것입니다. 다시 말하지만, 사소한 것이 아니라 패딩 논리에 대한 생각을 무시할 수 있습니다. 그래도 질문에 대한 더 나은 대답이므로 원래 예제를 바꾸지 않을 것입니다. 다른 대안을 모색하는 추가 참고 사항입니다.
Chris Cudmore 12

1
광고 "확실히 말하면 xp는 자체 설명하지만 한 줄 주석이 아프지 않은 코드를 가지고 있습니까?": 주석은 좋지만 지나치게 주석 처리 할 위험이 있습니다. 모든 주석 줄은 코드를 변경할 때 누군가가 업데이트하는 것을 잊어 버릴 수있는 것입니다.
Jan Hudec

1
이것을 말하는 더 좋은 방법은 "최고의 의견 유형은 의견이 필요하지 않다"입니다. 필요하지 않지만 (어쨌든 쓰여진) 의견은 좋은 의견이 아닙니다.
Kaz

1
참조 코드 int directionCode = (x > oldX) ? DIRECTIONCODE_RIGHT : (x > oldX) ? DIRECTIONCODE_LEFT : DIRECTIONCODE_NONE;에 오류가있는 것이 흥미 롭습니다 . 확실해야합니다 ... (x < oldX) ? DIRECTIONCODE_LEFT : DIRECTIONCODE_NONE;. 좋은 의견 아이디어-나쁜 코드.
chux

8

특정 기능 / 코드가 더 철저하게 설명되거나 특정 프로그래밍 방법이 선택된 이유를 설명하는 참조로 주석을 줄이는 경향이 있습니다.

비슷한 기술을 가진 다른 프로그래머가 코드를 사용하거나 읽는 것을 고려할 때 예상과 다른 방식으로 무언가를 달성하는 경우 주석을 달아야합니다. 따라서 왜 이런 방식을 선택하는지 주석으로 설명 할 수 있습니다.

예를 들어, Android 장치에서 서로 다른 두 개의 센서를 사용할 수 있고 그 중 하나가 사용자의 요구에 맞지 않는 경우 다른 센서를 선택한 이유를 설명에 설명 할 수 있습니다.

따라서 '왜'는 선택한 사항에 대한 근거 를 제공해야합니다.


5
참조는 좋은 예입니다. //이 방법은 furshclingeheimer 알고리즘을 사용하여 foobit를 론 스터 화합니다. http : // ... 참조
Chris Cudmore

8

주석은 코드가 수행하지 않는 것을 알려 주어야하며 반드시 WHY , HOW 또는 WHAT에 의해 제거되지는 않습니다 . 좋은 이름을 가지고 있고 명확한 기능을 가지고 있다면, 코드가 정확히 무슨 일인지 알려줄 수 있습니다. 예를 들면 다음과 같습니다.

List<LightMap> maps = makeLightmaps(receivingModels);
TrianglePartitioner partition = new Octree(castingTriangles);
List<Photon> photons = firePhotons(lights, partition);

if (photons.Count > 0)
{
      PhotonPartitioner photonMap = new KDTree(photons);
      gatherPhotons(maps, photonMap, partition, lights);
}

이 코드는 실제로 주석이 필요하지 않습니다. 함수와 타입 이름은 이해하기 쉽습니다.

그러나 때로는 위와 같이 유창한 코드를 만들기가 어렵거나 불가능할 수 있습니다. 예를 들어, 다음 코드 스 니펫은 구에서 통계적으로 임의의 점을 찾는 것입니다. 수학은 매우 불투명하기 때문에 설명에 대한 링크에 코멘트 알 수 있도록하는 것입니다 방법 이 작동합니다. 이 알려줄 수있는 기능에 싸여 수 있습니다 무엇 그렇지 않으면 링크 제목은 해당 부서에 도움이, 그것은 두 번 이상 필요한 경우 설명을 필요로하지 않습니다.

double randomA = localGenerator.NextDouble();
double randomB = localGenerator.NextDouble();

//http://mathworld.wolfram.com/SpherePointPicking.html
double theta = 2 * Math.PI * randomA;
double phi = Math.Acos(2 * randomB - 1);

Vector3 randomDirection = new Vector3(Settings.ambientRayLength * (float)(Math.Cos(theta) * Math.Sin(phi)),
                                      Settings.ambientRayLength * (float)(Math.Sin(theta) * Math.Sin(phi)),
                                      Settings.ambientRayLength * (float)Math.Cos(phi));

주석이 코드에없는 것을 알려주는 다른 예는 결정을 설명하기위한 것입니다. 다음 예제에서 코드는 스레드 코드가 아닌 내부의 비스 레드 로컬 변수를 잠그지 않습니다. 이에 대한 이유가 있으며 의견은 WHY를 설명합니다 . 의견이 없으면 버그로 간주되거나 눈치 채지 못할 수도 있습니다.

Random random = new Random();
Parallel.For(0, maxPhotons, delegate(int photonIndex, ParallelLoopState state)
{
    ...
    //I don't actually care if this random number is unique between threads, threadsafty is not that big of a deal
    //  in this case and locking the random object could cause a lot of lock contention
    while (random.NextDouble() > reflectProbability)
    {
        ...
    }
    ...
}

아마도 왜 랜덤 객체가 병렬 루프 내부에서 처음 생성되지 않는지 말하기 위해 향상 될 수 있습니다. 이유가 없다면, 누군가가 와서 전체 아이디어가 어리 석고 리팩토링하기에 좋은 장소라는 것을 깨달을 수도 있습니다.


주석 앞에 주석이 WriteText아닌 주석이 필요없는 것으로 코드를 설명하는 것이 합리적 //입니까?

1
대답에서 말했듯이 인쇄 문이 없더라도 주석은 필요하지 않지만 요점을 명확하게하기 위해 인쇄 문을 제거하도록 주석을 편집했습니다.
질긴 검볼

5

다른 종류의 "왜"를 인식하는 것이 도움이 될 수 있습니다.

  • 지나치게 복잡해 보이는 코드가 단순화되면 작동하지 않는 이유

  • 위험한 것처럼 보이는 특정 간단한 조작이 실제로 안전한 이유 (예 : "페치 데이터 루틴은 더미 항목 항목을 마지막 항목보다 다른 항목보다 작고 그 이후 항목이 더 큰 것으로보고합니다. 정렬해야하는 항목) 일관된 오름차순 또는 내림차순으로 다른 항목보다 먼저 그 뒤에 하나 이상의 항목이있을 수 있습니다 ").

대부분의 경우 코드의 한 부분에서 두 번째 유형의 주석이 다른 유형의 첫 번째 유형의 주석과 "일치"할 수 있습니다 (예 : "이 작업 순서가 단순화 된 것처럼 보이지만 Fitz 루틴은 ers 글은 밴더 스나 치가 뭉개 질 때까지 울퉁불퉁 해지지 않았다. ")


2

프로그램을 작성하는 경우 무작위로 입력하는 것이 아니라 공식 문서에 있거나 머리에 든 원하는 모델이 있기 때문에 수행하는 것을 잊지 마십시오 . 머리 속의 물건은 컴퓨터의 소프트웨어 / 데이터만큼이나 실제적이며 버그가있을 가능성이 큽니다.

코드를 읽는 사람은 해당 모델이 머리에 없을 수도 있으므로 주석은 모델이 무엇인지, 코드가 어떻게 관련되어 있는지 알려주는 역할을합니다. 나는 그것이 "왜"의 의미라고 생각합니다. 분명히 코드 자체를 가능한 한 자명하게 만드는 것이 좋지만 항상 충분하지는 않습니다. 예:

// transform the x,y point location to the nearest hexagonal cell location
ix1 = (int)floor(0.5 + x + y/2);
iy1 = (int)floor(0.5 + y);

또한 시간이 지남에 따라 모델이 변경되므로 해당 변경 사항을 코드로 전송해야합니다. 따라서 주석은 코드에 "이유"가있을뿐만 아니라 예상되는 모델 변경에 대한 응답으로 코드 를 변경하는 방법 도 중요 합니다 . 예:

// to change to square cell locations, remove the "+ y/2" in the above code

나는 의견의 목적이 때때로 무시된다고 생각한다.


2
문제는 예를 요구하는 것입니다. 이 답변을 더 유용하게 만드는 예를 추가해 주시겠습니까?
Bryan Oakley

2
첫 번째 코드는 "무엇"을 설명하는 전형적인 예처럼 보입니다. 그것은 나쁜 의견이 아니지만 OP의 질문에 대답한다고 생각하지 않습니다.

@ 존 : 의견이 없다면 독자는 무슨 일이 일어나고 있는지 알 수 있지만 그 이유를 모릅니다.
Mike Dunlavey

1
@ MikeDunlavey : 동의하지 않습니다. 나는 아직도 모른다-왜 가장 가까운 육각형 셀 위치를 원합니까? 이 위치를 얻는 목적 은 무엇입니까 ? 이 두 줄을 삭제하면 아무 영향이 없습니까?

2

모든 의견이 '왜'유형 인 것은 아니지만 많은 의견이 있습니다.
다음은 하나의 (Delphi) 소스 파일의 예입니다.

// For easier access to the custom properties:

function GetPrivate: Integer;   // It's an integer field in the external program so let's treat it like that here

// The below properties depend on the ones above or are calculated fields.
// They are kept up-to-date in the OnEventModified event of the TTSynchronizerStorage
// or in the ClientDataSet.OnCalcFields of the TcxDBSchedulerStorage.DataSource.DataSet
property IsModified       : Boolean   read GetIsModified   write SetIsModified;
property IsCatTT          : Boolean   read GetIsCatTT      write SetIsCatTT;
property IsSynced         : Boolean   read GetIsSynced     write SetIsSynced;

lLeftPos := pos(' - [',ASubject); // Were subject and [shiftnaam:act,project,cust] concatenated with a dash?

// Things that were added behing the ] we will append to the subject:

// In the storage the custom value must also be set for:
Self.SetCustomFieldValueByname(cCustFldIsCatTT,Result);

// When we show the custom fields in a grid, the Getters are not executed,
// because the DevEx code does not know about our class helpers.
// So we have two keep both properties synchronized ourselves:

// lNewMasterEvent was set to usUpdated, overwrite because we added:
if ARepair then
  lNewMasterEvent.CustUpdateStatus := usRecreated

// The source occurrence date may have bee changed. Using GetOriginalDate we can retrieve the original date,
// then use that for creating a target occurrence (and update its date):

lNewTTOccurrence.CustSyncEntryID := cSyncEntryID0;    // Backward compatibility with old sync methode

// Single event became recurring or vice versa; replace entire event

// In contradiction to CopySingleEventToTimeTell, CopyMasterEventToTimeTell does not have a ANewStatus parameter
// because master events are always added.

(my) 주석이 일반적으로 코드 앞에 오는지 (따라서 콜론으로 끝남 ) 것에 주목하십시오 .

좀이 의견은 설명 할 어떤 프로세스가 논리적 그룹이 (그리고 코드가 자동으로 보여 리팩토링되지 않음) 여러 단계가있을 때 일어나고, 예를 들어, 내가 같이 언급합니다 :

// Step 1. Initialization

1

나는 왜 당신이 무언가를 요구하는 주어진 상황 때문에, 당신이 뭔가 이상하거나 어리석은 방식으로 무언가를하는 이유 인 이유를 이해합니다. 방법은 코드가없는 "의미"를하지 않는다해도, 아무리 이상한 코드 자체에서 볼 수 없습니다. 는 무엇을하는 것이 가장 클래스 / 함수 문서의 시작 부분에 말했다된다. 따라서 WHY 를 추가하면 HOW 및 WHAT에 포함되지 않은 내용 및 제어 할 수없는 이유로 인해 필요한 고유 한 방법을 설명 할 수 있습니다.

물론 유니콘과 무지개의 땅 밖에서는 항상 그런 것은 아닙니다 ...

어떻게:

foreach($critters as $creature) {
   $creature->dance();
}

뭐:

/* Dancing creatures v1.0
 * 
 * The purpose of this is to make all your critters do the funky dance.
 */

foreach($critters as $creature) {
  $creature->dance();
}

왜:

// We had to store the items in an array of objects because of _____ (reason)
foreach($critters as $creature) {
   $creature->dance();
}

5
이것은 질문에 어떻게 대답합니까?
gnat

1
OP를 인용하기 위해 : "질문으로 돌아가서 : 만약 의견이 왜 당신에게 말해야한다면, 우리가 무엇에 대해 이야기하고 있는가?"라는 질문에 대답했습니다. 주어진 코드 조각.
Juha Untinen

1
이 질문은 구체적으로 몇 번 예를 요구합니다. 이 답변에 더 유용한 예제를 추가해 주시겠습니까?
Bryan Oakley

1
나는 이러한 의견 중 하나가 실제로 도움이되지 않는다고 생각합니다. 함수의 서명이 critters.dance()인 경우 주석은 명백한 것을 반복하며 "우리가 시도한 다른 방법으로는 작동하지 못했습니다"는 완전히 도움이되지 않습니다. 또한 "각 객체에 대해 메소드를 호출합니다"라는 말은 코드가 매우 명확하게 말하는 것을 반복합니다.
Brendan Long

1

나는 항상 다른 개발자에게 API를 전달하거나 doxygen과 같은 자동 문서 도구를 사용하는 경우 C ++ 헤더 파일에 주석을 작성하는 법을 배웠습니다 (이름이 좋은 힌트를 주더라도 함수가하는 일이 항상 명확하지 않기 때문에).

나에게 전형적인 의견은 다음과 같습니다.

/*** Functionname
/*   What happens here
/*  [in] Params
/*  [out] params
/*** 

내가 왜 주석을 사용했는지 유일한 이유는 이해하기 어렵고 때로는 프로그래머에게도 "이러면 안 돼요!"또는 "프로그램이 삭제되면 충돌 할 것입니다 ..."와 같은 것입니다.

해결 방법, 해킹 및 이상한 행동은 내 눈에 WHY 기준을 충족시킵니다 ...

아주 좋고 재미있는 사례는 Richard라는 사람이 작성한 엉망인 코드에 대한 "해결 방법"입니다. 다른 사람이 그것을 감싸서 주석에서 이유를 설명했습니다 ... https : //.com/a/184673/979785

불행히도, "항상 그렇게 되었기 때문에"원본에 손을 대지 못하기 때문에 황소 **를 포장해야하는 경우가 상당히 많습니다. 목적을 위해 원본을 고칠 시간이 없어 실제로 오버 헤드에 적합하지 않습니다.


7
문제는 문서가 아닌 의견관한 것 입니다. 그들은 실제로 다른 것들입니다 ( documentation태그는 유감이지만 여전히 질문에 적용되지 않습니다).
토마스

내 모국어 주석과 문서 주석에서 상호 교환 가능하게 사용되므로 태그와 함께이 질문에도 적용 할 수 있다고 가정합니다. 이것이 실제로 공감해야 할 이유입니까?
AnyOneElse

2
질문은 주석의 예를 몇 번 요구 하지만, 당신이 포함하는 유일한 예는 what 주석입니다. 예를 들어 답을 감추고있는 사람들은 여러분의 예에 오도 될 수 있습니다. 댓글 의 예를 들어 줄 수 있습니까 ?
Bryan Oakley

난 내 코드에서 매우 적은 이유들가 말했다, 나는 두 가지 예를 이름이 있지만 : 수정 됨 ... 여기 링크가 확실히 왜 자격으니,
AnyOneElse

@AnyOneElse 나는 공감하지 않았다. 내가 도착하기 전에 있었다.
토마스

0

코드는 실행 계획을 지정해야합니다. 그렇게하면 프로그램 추종자 (또는 컴파일러)가해야 할 일과 수행 방법을 알아낼 수 있습니다. 프로그램 추종자가 수행 할 수있는 단계로 구분됩니다. 기본 단계는 방법입니다.

코더의 의도는 또 다른 문제입니다. 간단하고 명확하며 간단한 코드에서 의도는 분명합니다. 합리적으로 유능한 인간 독자는 코드를 읽음으로써 코드 블록의 의도에 도달 할 것입니다. 대부분의 코드는 다음과 같아야합니다.

간혹 의도와 계획의 관계가 모호합니다. 코드는 무엇과 방법을 보여 주지만 그 이유는 밝히지 않습니다. 그 때 의도를 밝힌 의견이 가치가 있습니다. 프로그래머의 의도가 그 이유입니다.


3
이 질문은 몇 가지 예를 요구합니다. 답변에 더 유용한 예를 추가 할 수 있습니까?
Bryan Oakley

0

이 문제는 현재 복잡하고 다소 복잡한 데이터 모델에 대한 저장 프로 시저와 뷰를 넘어서고 있습니다.

"x.account가 null이 아니고 (페덱스에서 주소 선택) x.account가 x.account else y.account end"인 경우와 같이 (수 많은) 선택을하고 시간이 없더라도 생산성이 예상됩니다. 모든 소스 코드 를 읽을 수 있습니다. 그리고이 예는 일종의 의미가 있지만 여전히 필연적입니다.

페덱스에서 x와 x가 아닌 경우 전체 시스템에 빛을 비추는 이유를 설명하고 충분히 읽을 때 우리는 그것을 얻기 시작합니다. 그리고 이것은 단순화되고 수백 또는 수천 개의 유사한 진술이 있습니다. 2007 년부터 온 그 종류의 사람들이 그 이유를 넣은 사람에게 내 마음이 따뜻하게 빛납니다.

예, 복잡한 복잡한 데이터 모델과 털이 많은 veiw 및 유효하게 명명 된 여러 경로가있는 저장 프로 시저, 하나님의 사랑에 대해 알려주십시오.


0

방금이 의견을 썼습니다. 코드 라인이 무엇인지, 특히 내가 왜 변경했는지 를 설명하는 구체적인 예입니다 .

이 방법은 저장된 데이터를 검사하여 한쪽 끝의 현재 날짜와 다른 쪽 끝의 시작 날짜까지 완료되었는지 평가합니다.

// In principal, this should be ">=", as we may have data up to the account start
// date but not complete for that day; in practice, 98% of the time if we have
// data for the start date it *is* complete, and requerying it would be a waste
// of time.
while (endDate > accountStartDate)
    ...

당신이 아마 짐작할 수 있듯이,보다 큰 연산자는 더 크거나 같았습니다. 주석은 이전 값이 의미가있는 이유와 새로운 값이 더 나은 이유를 설명합니다. 앞으로 누군가가 이것을 본다면, ">"의 사용은 감독이 아니라 최적화라는 것을 알게 될 것입니다. 그런 다음 당시의 필요에 따라 변경하거나 남겨 둘 수 있습니다.

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