클린 코드 주석과 클래스 문서


83

의견에 관해 새로운 동료들과 토론을하고 있습니다. 우리는 Clean Code를 좋아 하고 인라인 코드 주석을 피하고 클래스와 메소드 이름을 사용하여 수행하는 것을 표현해야한다는 사실에 완벽하게 만족합니다.

그러나 저는 수업의 목적과 실제로 나타내는 것을 설명하는 작은 수업 요약을 추가하는 것을 좋아합니다. 주로 단일 책임 원칙 패턴 을 유지하기가 쉽습니다 . 또한 메소드가 수행해야 할 작업을 설명하는 메소드에 한 줄 요약을 추가하는 데 익숙합니다. 전형적인 예는 간단한 방법입니다

public Product GetById(int productId) {...}

다음 방법 요약을 추가하고 있습니다

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary

메서드가 null을 반환한다는 사실을 문서화해야한다고 생각합니다. 메서드를 호출하려는 개발자는 메서드가 null을 반환하는지 또는 예외를 throw하는지 확인하기 위해 코드를 열지 않아도됩니다. 때로는 인터페이스의 일부이므로 개발자는 어떤 기본 코드가 실행중인지도 모릅니다.

그러나 동료들은 이러한 종류의 주석은 " 코드 냄새 "이고 "댓글은 항상 실패"라고 생각합니다 ( Robert C. Martin ).

의견을 추가하지 않고 이러한 유형의 지식을 표현하고 의사 소통하는 방법이 있습니까? 나는 Robert C. Martin의 열렬한 팬이기 때문에 약간 혼란스러워지고 있습니다. 요약은 주석과 같으므로 항상 실패합니까?

이것은 인라인 주석에 대한 질문이 아닙니다.


38
로버트 마틴은 "의견은 항상 실패"라고 말했다. 글쎄, 그는 프린지 극단 주의자이며 소금 한 덩어리로 가져 가야합니다. (예, 나는 그가이 메시지를 수사하기 위해 이러한 수사 목적을 위해 글을 쓴다는 것을 알고 있습니다. 제 요점은 당신도 그래야합니다 .)
Kilian Foth

18
밥 아저씨의 책에는 1kg의 소금이 들어 있습니다.
AK_

6
Robert Martin을 따르는 경우 널 사례에 대한 문서를 테스트해야합니다. 즉, 어떤 경우에 메소드가 널을 리턴 할 수 있는지 보여주는 테스트가 있어야합니다. 또는 이것이 Java이기 때문에 @Nullable 주석도 주석보다 낫습니다.
Martin Epsz 2016 년

15
@Bjorn 저는 Clean Code 사본을 소유하고 있으며 두 번 이상을 다루기 위해 표지를 읽었습니다. 그렇습니다. Bob 아저씨는 코드가 자체 문서화되는 것을 선호하지만 , 책 자체 코드 에는 여러 주석 예제가 있습니다. 요점은 의견을 작성해야한다고 생각되면 의견을 추가하는 대신 코드를 변경하려고 열심히 노력하지만 의견을 완전히 허용하지는 않습니다 (인라인 의견조차도).

6
이 메소드는 TryGetById라고하고 주석을 제거해야합니다.
usr

답변:


116

다른 사람들이 말했듯이 API 문서 주석과 인라인 주석에는 차이가 있습니다. 내 관점에서 볼 때 가장 큰 차이점은 인라인 주석이 코드 와 함께 읽히는 반면 문서 주석은 주석 처리하는 내용의 서명 과 함께 읽히는 것 입니다.

이를 감안할 때 동일한 DRY 원칙을 적용 할 수 있습니다 . 주석이 서명과 같은 것을 말하고 있습니까? 예를 보자.

ID로 제품을 검색합니다

이 부분은 이름 GetById과 반환 유형 에서 이미 본 것을 반복 합니다 Product. 또한 "getting"과 "rerieving"의 차이점과 베어링 코드와 주석의 차이점에 대한 의문도 제기합니다. 따라서 불필요하고 약간 혼란 스럽습니다. 어쨌든 그것은 실제로 유용한 주석의 두 번째 부분을 방해하고 있습니다.

제품이 없으면 null을 반환합니다.

아! 서명만으로 확실하게 알 수없는 유용한 정보를 제공합니다.


이제 한 단계 더 나아가십시오. 사람들이 코드 냄새로 주석에 대해 이야기 할 때, 코드에 주석 필요한지 여부가 아니라 주석에 정보를 표현하기 위해 코드가 더 잘 작성 될 수 있음을 나타내는 지 여부가 문제입니다. 이것이 바로 "코드 냄새"가 의미하는 바입니다. "하지 마십시오!"라는 의미는 아닙니다. "이 작업을 수행하면 문제가있을 수 있습니다"라는 의미입니다.

따라서 동료가 널에 대한이 의견이 코드 냄새라고 말하면 간단히 물어보십시오. "그럼 어떻게 표현해야합니까?" 그들이 가능한 대답이 있다면, 당신은 무언가를 배웠습니다. 그렇지 않다면, 아마도 그들의 불만이 죽었을 것입니다.


이 특정 사례와 관련하여 일반적으로 null 문제는 어려운 것으로 잘 알려져 있습니다. 코드베이스에 가드 절이 흩어져있는 이유, 왜 널 체크가 코드 계약의 인기 전제 조건인지, 왜 널의 존재가 "십억 달러의 실수"라고 불 렸는지가 있습니다. 실행 가능한 옵션이 많지 않습니다. 그러나 C #에서 발견되는 인기있는 Try...규칙 은 다음과 같습니다.

public bool TryGetById(int productId, out Product product);

다른 언어에서는 유형을 사용하여 ( Optional또는 이와 비슷한 이름을 사용하여 Maybe) 존재하거나 존재하지 않는 결과를 나타내는 것이 관용적 일 수 있습니다 .

public Optional<Product> GetById(int productId);

어떤 식 으로든이 반 댓글 입장은 어딘가에 있습니다. 우리는 적어도이 의견이 냄새를 나타내는 지, 그리고 어떤 대안이 존재할 수 있는지에 대해 생각했습니다.

우리가 실제로 원래 서명보다 이것을 선호 해야하는지 여부는 완전히 다른 논쟁이지만 적어도 제품을 찾을 수 없을 때 발생하는 의견보다는 코드를 통해 표현할 수있는 옵션이 있습니다. 동료들과 어떤 옵션이 더 낫고 왜 좋은지에 대해 논의하고 의견에 대한 포괄적 인 견해를 넘어서도 도움이되기를 바랍니다.


9
또는 Linq-와 동등 Try...하며 ...OrDefault, 이는 default(T)절이 빈 결과를 초래할 경우 반환 합니다.
Bart van Nierop 2016 년

4
인라인 코드 주석과 문서 주석, 그리고 주어진 예제들 사이의 차이점에 대해 정말 감사합니다.
Rachel

2
함수의 가능한 반환 값은 서명으로 분명해야합니다. TryGetValue패턴은 C #으로이 일을 합리적인 방법이지만, 가장 기능적인 언어 누락 된 값을 표현하는 더 좋은 방법이있다. 자세히 알아보기
AlexFoxGill 2016

2
@BenAaronson : 공분산을 지원할 수있는 일반 인터페이스를 원할 경우 T TryGetValue(params, ref bool success)모든 유형 T에 대해 또는 T TryGetValue(params)클래스 제한 유형 T에 대해 실패를 나타내는 null과 함께 사용할 수 있지만 TryGetXX반환 되는 패턴 bool은 공분산과 호환되지 않습니다.
supercat

6
Java 8에서는 Optional<Product>메소드에서 리턴 된 제품이 없을 수 있음을 표시 하기 위해를 리턴 할 수 있습니다 .
Wim Deblauwe 2016 년

102

Robert C. Martin의 인용문은 문맥에서 벗어납니다. 약간 더 많은 문맥을 가진 인용문은 다음과 같습니다.

잘 배치 된 의견만큼 도움이 될만한 것은 없습니다. 사소한 독단적 인 의견 이상의 모듈을 어수선하게 만들 수있는 것은 없습니다. 거짓말과 잘못된 정보를 전파하는 오래된 잔인한 의견만큼 큰 피해는 없습니다.

댓글은 쉰들러의 목록과 다릅니다. 그들은 "순수하지 않다". 실제로, 의견은 기껏해야 필요한 악입니다. 우리의 프로그래밍 언어가 충분히 표현력이 있거나 의도를 표현하기 위해 그 언어를 미묘하게 사용하는 재능이 있다면, 우리는 전혀 언급하지 않아도 될 것입니다. 아마도 아닙니다.

주석의 올바른 사용은 코드로 자신을 표현하지 못한 것을 보상하는 것입니다. 나는 실패라는 단어를 사용했습니다. 나는 그것을 의미했다. 주석은 항상 실패입니다. 우리는 항상 그들없이 자신을 표현하는 방법을 알 수 없기 때문에 그것들을 가져야하지만, 그것들의 사용이 축하의 원인이 아닙니다.

따라서 의견을 작성해야 할 위치에있을 때 의견을 검토하고 표를 돌리고 코드로 표현할 수있는 방법이 없는지 확인하십시오. 코드로 자신을 표현할 때마다 등을 두 드려야합니다. 당신이 의견을 쓸 때마다, 당신은 얼굴을 찡그리고 표현력의 실패를 느껴야합니다.

( 여기서 복사 했지만 원래 인용문은 Clean Code : Handbook of Agile Software Craftsmanship )입니다.

이 인용문이 "코멘트는 항상 실패"로 축소되는 방법은 일부 사람들이 문맥에서 현명한 인용을 취해 어리석은 교리로 바꾸는 좋은 예입니다.


javadoc과 같은 API 문서 는 사용자가 소스 코드를 읽을 필요없이 API를 사용할 수 있도록 API를 문서화해야 합니다 . 따라서이 경우에는 문서 한다 방법이 무엇을하는지 설명한다. 이제 메소드 이름으로 이미 표시되어 있기 때문에 "ID로 제품 검색"이 중복 적이라고 주장 할 수 있지만 null리턴 될 수 있는 정보는 명백한 방식이 아니기 때문에 문서화에 반드시 중요합니다.

주석의 필요성을 피 null하려면 API를보다 명시 적으로 작성하여 근본적인 문제점 ( 유효한 리턴 값으로 사용)을 제거해야합니다 . 예를 들어 Option<Product>, 어떤 유형의 유형을 리턴 할 수 있으므로 유형 서명 자체는 제품을 찾을 수없는 경우 리턴 될 내용을 명확하게 전달합니다.

그러나 어쨌든 메소드 이름과 유형 서명을 통해 API를 완전히 문서화하는 것은 현실적이지 않습니다. 명확하지 않은 추가 정보에 대해서는 doc-comments를 사용하십시오. DateTime.AddMonths()BCL 에서 API 문서를 말하십시오 .

AddMonths 메서드는 윤년과 한 달의 일 수를 고려하여 결과 월과 연도를 계산 한 다음 결과 DateTime 객체의 요일 부분을 조정합니다. 결과 날짜가 결과 월의 유효 날짜가 아닌 경우 결과 월의 마지막 유효 날짜가 사용됩니다. 예를 들어, 3 월 31 일 + 1 개월 = 4 월 30 일입니다. 결과 DateTime 객체의 시간 부분은이 인스턴스와 동일하게 유지됩니다.

메소드 이름과 서명 만 사용하여이를 표현할 수있는 방법은 없습니다! 물론 클래스 문서는이 수준의 세부 사항을 요구하지 않을 수 있습니다. 이는 단지 예일뿐입니다.


인라인 주석 도 나쁘지 않습니다.

나쁜 의견은 나쁘다. 예를 들어 코드에서 사소하게 볼 수있는 내용 만 설명하는 주석은 고전적인 예입니다.

// increment x by one
x++;

변수 나 메소드의 이름을 바꾸거나 코드를 재구성하여 명확하게 설명 할 수있는 설명은 코드 냄새입니다.

// data1 is the collection of tasks which failed during execution
var data1 = getData1();

이것들은 마틴 레일즈에 대한 의견입니다. 주석은 명확한 코드를 작성하지 못한 경우의 증상입니다.이 경우 변수 및 메소드에 대해 자명 한 이름을 사용하십시오. 주석 자체는 물론 문제가 아니며 문제는 코드를 이해하기 위해 주석이 필요하다는 것입니다.

그러나 주석은 코드에서 명확하지 않은 모든 것을 설명하는 데 사용해야 합니다. 예를 들어 코드가 분명하지 않은 방식으로 작성된 이유 는 다음과 같습니다.

// need to reset foo before calling bar due to a bug in the foo component.
foo.reset()
foo.bar();

지나치게 복잡한 코드 조각이하는 일을 설명하는 주석도 냄새이지만, 수정은 주석을 금지하지 않으며 수정은 코드 수정입니다! 실제로 복잡한 코드가 발생하지만 (리팩터링까지 일시적으로 만 가능) 일반 개발자는 처음으로 완벽한 코드를 작성하지 않습니다. 복잡한 코드는 그것보다 무엇을 설명하는 코멘트를 작성하는 훨씬 더 발생하면 되지 코멘트를 작성합니다. 이 의견은 또한 나중에 쉽게 리팩토링 할 수있게합니다.

때때로 코드는 불가피하게 복잡합니다. 복잡한 알고리즘 일 수도 있고 성능상의 이유로 명확성을 희생하는 코드 일 수도 있습니다. 다시 의견이 필요합니다.


13
코드 복잡한 상황을 처리하고 간단한 코드로는 처리 할 수없는 경우도 있습니다.
gnasher729

6
좋은 지적이야. 성능을 위해 일부 코드를 최적화해야 할 때 종종 발생하는 것 같습니다.
JacquesB

9
심지어 코멘트에는 x++이 같은 "증가 x는이 UINT32_MAX을의 경우 약 포장, 하나"라면 잘 할 수있다; 언어 사양을 아는 사람은 누구나 줄 uint32_t바꿈 이 가능하다는 것을 알고 있지만 주석이 없으면 그러한 줄 바꿈이 구현되는 알고리즘 의 예상 부분 인지 알 수 없습니다 .
supercat

5
@ l0b0 : 농담하고 싶습니다!
JacquesB 2016 년

9
@ l0b0 임시 코드와 같은 것은 없습니다. 비즈니스가 결과에 만족하고 코드를 수정하기위한 자금을 승인하지 않기 때문에 코드는 리팩토링되지 않습니다. 5 년 후, 일부 주니어 개발자는이 코드를 볼 수 있습니다. Bugtrocity v9로 교체 한 이후 WizBug 4.0을 더 이상 사용하지 않기 때문에 "Bug123"은 아무 의미가 없습니다. 그는 이제 이것이 영구 코드가 될 것이라고 생각하고 그의 경력 전체에서 끔찍한 개발자로 진행합니다. 아이들을 생각하십시오. 임시 코드를 작성하지 마십시오.
corsiKa

36

코드 주석 처리코드 문서화 에는 차이가 있습니다 .

  • 코드를 나중에 유지 관리하려면 주석 이 필요합니다. 즉, 코드 자체가 변경됩니다.

    의견은 실제로 문제가있는 것으로 인식 될 수 있습니다. 극단적 인 요점은 항상 코드 내에서 (코드를 이해하기 어려운) 언어 (언어를 표현할 수없는 언어; 예를 들어 메소드가 결코 반환하지 않는다는 사실을 null표현할 수 있음) 내에서 문제를 나타냅니다. C #에서 코드 계약을 통해 코드를 작성할 수는 있지만 PHP와 같은 코드를 통해 코드를 표현할 방법은 없습니다).

  • 개발 한 객체 (클래스, 인터페이스)를 사용하려면 문서 가 필요합니다. 대상 독자는 다릅니다. 코드를 유지 관리하고 여기서 말하는 코드를 변경하는 사람이 아니라 코드를 거의 사용 하지 않는 사람입니다 .

    코드가 충분히 명확하기 때문에 문서를 제거하는 것은 미친 짓입니다. 문서는 수천 줄의 코드를 읽지 않고도 클래스와 인터페이스를 사용할 수 있도록 특별히 만들어 졌기 때문 입니다.


예. 그러나 Martin의 요점 중 적어도 일부는 현대 개발 관행에서 테스트 자체가 코드가 아니라 문서라는 것입니다. 코드가 BDD 스타일 테스트 시스템, 예를 들어 specflow로 테스트되고 있다고 가정하면 테스트 자체는 메소드의 동작에 대한 직접 읽을 수있는 설명입니다 ( "GetById가 유효한 제품의 ID로 호출 될 때 제품 데이터베이스가 제공됨). 잘못된 제품 ID로 GetById를 호출하면 해당 제품 개체가 [...]로 반환되고 null이 반환됩니다 "등).
Jules

13

글쎄, 당신의 동료는 책을 읽고, 그들의 말을 받아들이고, 생각없이 그리고 문맥을 고려하지 않고 배운 것을 적용하는 것 같습니다.

함수가 무엇을 해야하는지에 대한 귀하의 의견은 구현 코드를 버릴 수 있고 함수의 주석을 읽으며 아무런 문제없이 구현을 대체 할 수 있습니다.

주석이 예외가 발생했는지 여부 또는 nil이 반환되는지 여부를 알려주지 않으면 그렇게 할 수 없습니다. 댓글이 말하지 않는 경우 또한, 당신이 예외가 발생 여부를 nil을 반환 여부를 함수를 호출 할 때마다, 다음, 당신은 반드시 당신의 코드에서 예외가 발생 또는 nil을 반환 여부를 제대로 작동해야합니다.

따라서 동료는 완전히 잘못되었습니다. 계속해서 모든 책을 읽으십시오. 그러나 스스로 생각하십시오.

추신. "때로는 인터페이스의 일부이므로 어떤 코드가 실행 중인지조차 모릅니다."가상 기능만으로도 어떤 코드가 실행 중인지 알 수 없습니다. 더군다나 추상 클래스를 작성했다면 코드조차 없습니다! 따라서 추상 함수가있는 추상 클래스가있는 경우 추상 함수에 추가하는 주석은 구체적 클래스의 구현자가이를 안내 해야하는 유일한 것입니다. 이러한 주석은 클래스의 사용자를 안내 할 수있는 유일한 것일 수도 있습니다. (물론 구현 의 소스 코드를 보아서는 안됩니다 ).


10 년 동안 코드에 댓글을 달지 않았습니다. 댓글은 부풀어 오르고 쓰레기입니다. 요즘에는 아무도 코드를 작성하지 않습니다. 우리는 잘 정립되고 이름이 지정된 코드, 작은 모듈, 디커플링 등에 중점을 둡니다. 테스트를 통해 코드를 버릴 경우 주석이 아닌 문제가 없는지 확인합니다. 테스트는 작성하는 코드를 사용하는 방법, 코드를 호출하는 방법 및 그 이유가 무엇인지 알려줍니다. 당신은 너무 오래된 학교입니다. 친구 테스트 및 깨끗한 코드에 대해 배우고 싶습니다.
PositiveGuy

12

고려해야 할 두 가지 유형의 주석이 있습니다. 코드를 가진 사람들에게 보이는 주석과 문서를 생성하는 데 사용됩니다.

Bob 아저씨가 언급 한 주석 유형은 코드를 가진 사람에게만 보이는 종류입니다. 그가 옹호하는 것은 DRY의 한 형태입니다 . 소스 코드를보고있는 사람에게는 소스 코드가 필요한 문서 여야합니다. 사람들이 소스 코드에 액세스 할 수있는 경우에도 주석이 항상 나쁜 것은 아닙니다. 때로는 알고리즘이 복잡하거나 불명확 한 접근 방식을 취하는 이유를 파악하여 다른 사람들이 버그를 수정하거나 새로운 기능을 추가하려고 할 때 코드를 깨뜨리지 않도록하는 경우가 있습니다.

설명하는 주석은 API 문서입니다. 이들은 구현을 사용하는 사람들에게 보이지만 소스 코드에 액세스하지 못할 수 있습니다. 소스 코드에 액세스 할 수있는 경우에도 다른 모듈에서 작업하고 소스 코드를보고 있지 않을 수 있습니다. 이 사람들은 코드를 작성할 때 IDE에서이 문서를 제공하는 것이 유용하다는 것을 알게 될 것입니다.


나는 솔직히 DRY가 코드 + 주석에 적용되는 것을 생각하지 않았지만 완벽하게 이해됩니다. @JacquesB의 답변에서 "증가 X"와 같은 종류입니다.

7

주석의 가치는 정보를 읽거나 무시하는 데 필요한 노력을 뺀 정보의 가치로 측정됩니다. 주석을 분석하면

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary>

가치와 비용에 대해서는 다음 세 가지가 있습니다.

  1. Retrieves a product by its id함수의 이름이 말하는 것을 반복하므로 값이없는 비용입니다. 삭제해야합니다.

  2. returns null if no product was found매우 귀중한 정보입니다. 다른 코더가 함수의 구현을보아야하는 시간을 줄일 수 있습니다. 나는 그것이 스스로 도입하는 독서 비용보다 더 많은 독서를 절약 할 것이라고 확신합니다. 머물러 있어야합니다.

  3. /// <summary>
    /// </summary>
    

    어떤 정보도 가지고 있지 않습니다. 그들은 주석 독자에게 순수한 비용입니다. 문서 생성기에 필요한 경우에는 정당화 될 수 있지만이 경우 다른 문서 생성기에 대해 생각해야합니다.

    이것이 문서 생성기를 사용하는 것이 논란의 여지가있는 이유입니다. 일반적으로 광택이있는 문서를 위해서 정보를 제공하지 않거나 명백한 내용을 반복하는 추가 의견이 많이 필요합니다.


다른 답변에서 찾지 못한 관찰 :

코드를 이해 / 사용할 필요 가 없는 주석조차 매우 가치가 있습니다. 다음은 그러한 예 중 하나입니다.

//XXX: The obvious way to do this would have been ...
//     However, since we need this functionality primarily for ...
//     doing this the non-obvious way of ...
//     gives us the advantage of ...

코드를 이해하고 사용하는 데 필요한 텍스트가 많을 수 있습니다. 그러나 코드가 그렇게 보이는 이유를 설명합니다. 코드를 보는 사람들을 짧게 멈추고 왜 코드가 명백한 방법으로 이루어지지 않았는지 궁금해하며 코드가 왜 이런 식으로 쓰여 졌는지 알 때까지 코드 리팩토링을 시작합니다. 그리고 독자가 리팩토링으로 바로 넘어 가지 않을 정도로 똑똑하더라도, 코드가 코드를 유지하는 방법을 이해하기 전에 코드가 왜 그렇게 보이는지 알아 내야합니다. 이 의견은 말 그대로 작업 시간을 절약 할 수 있습니다. 따라서 값이 비용보다 높습니다.

마찬가지로 주석은 코드의 작동 방식 대신 코드의 의도를 전달할 수 있습니다. 또한 코드 자체의 세부적인 부분에서 일반적으로 손실되는 큰 그림을 그릴 수 있습니다. 따라서, 당신은 호의적 인 수업 댓글에있는 것이 옳습니다. 나는 수업의 의도, 다른 수업과의 상호 작용 방법, 사용 방법 등을 설명하면 수업 댓글을 가장 중요하게 생각합니다. 아아, 나는 그런 의견의 큰 저자가 아닙니다 ...


2
와우-파싱을 위해 몇 줄의 html 라인이 더 필요하기 때문에 문서 생성기를 변경 하시겠습니까? 하지 말자
corsiKa

2
@corsiKa YMMV이지만 주석의 비용을 최소로 줄이는 문서 생성기를 선호합니다. 물론 실제 코드와 동기화되지 않은 doxygen 문서보다 잘 작성된 헤더 파일을 읽는 것이 좋습니다. 그러나 내가 말했듯이 YMMV.
cmaster

4
방법의 이름이 그 목적을 훌륭하게 묘사하더라도, 자연어를 사용하여 그 목적을 반복하면 그 목적을 따르는 사람이 그 목적을 뒤 따르는 경고와 쉽게 연관시킬 수 있습니다. 이름에 설명 된 내용을 다시 말하면 값이 낮더라도 비용도 낮아질 정도로 짧습니다. 따라서 귀하의 게시물의 첫 부분에 동의하지 않습니다. 그러나 두 번째 부분은 +1입니다. 평가되고 거부 된 대체 접근 방식에 대한 문서는 매우 가치가있을 수 있지만 그러한 정보는주의를 기울이는 경우가 거의 없습니다.
supercat

GetById질문, 아이디가 무엇인지, 그리고 어디에서 무엇을 얻습니다. 문서 주석은 개발 환경이 이러한 질문에 대한 답변을 표시 할 수 있도록해야합니다. 모듈 문서 주석의 다른 곳에서 설명하지 않는 한 어쨌든 ID를 얻는 이유를 알려주는 한 곳이 될 것입니다.
hyde

의견은 날카 롭고 깔끔한 코드 (자체 설명), TDD (자주 의견을 받거나 디자인에 대한 의견을 자주 받음), 테스트 (자신감과 행동을 문서화) 규칙! 테스트 사람들 테스트. 여기서 아무도 그것에 대해 이야기하고 있지 않습니다. 일어나
PositiveGuy

4

주석 처리되지 않은 코드는 잘못된 코드입니다. 코드를 영어와 거의 같은 방식으로 읽을 수 있다는 것은 보편적이지는 않지만 보편적 인 신화입니다. 시간과 노력이 필요한 가장 사소한 코드를 제외하고 해석해야합니다. 또한, 모든 사람은 주어진 언어를 읽고 쓰는 데있어 서로 다른 수준의 능력을 가지고 있습니다. 저자와 독자의 코딩 스타일과 기능의 차이는 정확한 해석에 강력한 장애물입니다. 또한 코드 구현에서 저자의 의도를 이끌어 낼 수 있다는 신화입니다. 내 경험상, 코멘트를 추가하는 것은 거의 잘못이 아닙니다.

Robert Martin et al. 코드가 변경되고 주석이 변경되지 않았기 때문에 "나쁜 냄새"로 간주하십시오. 나는 그것이 좋은 것이라고 말한다 ( "악취"가 가정용 가스에 추가되어 사용자에게 누출을 경고하는 것과 정확히 같은 방식으로). 주석을 읽으면 실제 코드를 해석하는 데 유용한 출발점이됩니다. 일치하면 코드에 대한 신뢰도가 높아집니다. 서로 다른 경우 경고 냄새가 감지되어 추가 조사가 필요합니다. "나쁜 냄새"에 대한 치료는 냄새를 제거하는 것이 아니라 누출을 막는 것입니다.


2
당신은 지적 작가이고 텍스트는 지적 청중의 이익을위한 것입니다; 상식을 사용하여 선을 그립니다. 분명히, 그 예는 멍청하지만 그 시점에서 왜 코드에 i ++이 포함되어 있는지 주석으로 명확히할만한 이유가 없을 수는 없습니다.
빈스 오 설리번

8
i++; // Adjust for leap years.
빈스 오 설리번

5
"Robert Martin 등은 코드가 변경되고 주석이 변경되지 않았기 때문에"악취 "라고 생각합니다." 그것은 냄새의 일부일뿐입니다. 최악의 냄새는 프로그래머가 코드를 좀 더 설명적인 방식으로 쓰려고하지 않고 대신 "누설을 봉인"하기로 결정했다는 생각에서 비롯됩니다. 그의 주장은 윤년에 대한 "// adjust"주석을 때리는 것이 아니라 아마도 코드 자체에 "adjustForLeapYears ()"메소드가 있어야한다는 것입니다. 이 문서는 윤년 논리를 시험하는 테스트 형태로 제공됩니다.
Eric King

3
한 줄의 코드를 주석 과잉으로 대체하기 위해 메소드 호출을 추가하는 것을 고려할 것입니다. 특히 메소드의 이름은 실제로는 코드 자체에 레이블이 있고 더 나은 문서 정확성을 보장하지 않는 주석이기 때문입니다. (그 라인이 두 곳 이상에서 발생했다면 물론 메소드 호출을 도입하는 것이 올바른 솔루션 일 것입니다.)
Vince O'Sullivan

1
@Jay 그 이유는 (예를 들어 메소드를 도입하여) 추상화를 명시 적으로 만드는 것이 규칙 이기 때문입니다. 한 줄의 메소드로 끝날 수 있으므로 그렇게하지 않는 것은 예외입니다. 나를 의역하자 실제 ", 추상화를 소개하는 프로그래밍 언어의 구조 (일반적으로 방법과 클래스)를 사용하여 임의의 규칙을 하지 않는 한 그 추상화의 구현이 한 줄의 코드로 표현 될 수 있으며,이 경우의 추상화 지정하는 자연 언어를 추가하여 의견 "
Eric

3

일부 언어 (예 : F #)에서는이 전체 주석 / 문서가 실제로 메소드 서명으로 표현 될 수 있습니다. F #에서 null은 특별히 허용되지 않는 한 일반적으로 허용되는 값이 아니기 때문입니다.

F # (및 다른 여러 기능 언어)에서 공통적 인 것은 null 대신 또는 형식 일 Option<T>수 있는 옵션 유형 을 사용한다는 것입니다 . 그러면 언어는 이것을 이해하고 사용하려고 할 때 두 경우 모두 일치하도록 강요하거나 경고하지 않습니다.NoneSome(T)

예를 들어 F #에서는 다음과 같은 서명을 가질 수 있습니다.

val GetProductById: int -> Option<Product>

그리고 이것은 하나의 매개 변수 (int)를 취한 다음 제품 또는 값 None을 반환하는 함수입니다.

그런 다음 이렇게 사용할 수 있습니다

let product = GetProduct 42
match product with
| None -> printfn "No product found!"
| Some p -> DoThingWithProduct p

두 경우에 모두 일치하지 않으면 컴파일러 경고가 표시됩니다. 따라서 컴파일러 경고를 무시하지 않는 한 null 참조 예외를 얻을 수있는 방법은 없으며 함수 서명을 보면 필요한 모든 것을 알 수 있습니다.

물론 C #, Java, C ++ 등과 같은 많은 공통 언어는 그렇지 않은 방식으로 언어를 설계해야합니다. 따라서 현재 상황에서는 도움이되지 않을 수 있습니다. 그러나 주석 등을 사용하지 않고 이러한 유형의 정보를 정적으로 입력 된 방식으로 표현할 수있는 언어가 있다는 것을 알고 있으면 좋을 것입니다. :)


1

여기에 훌륭한 답변이 있으며 그들이 말한 것을 반복하고 싶지 않습니다. 그러나 몇 가지 의견을 추가하겠습니다. (말장난은 없습니다.)

소프트웨어 개발과 다른 많은 주제에 대해 현명한 사람들이 말한 내용은 문맥 상으로 이해 될 때 매우 훌륭한 조언이지만 문맥을 벗어 났거나 부적절한 상황에 적용하거나 취하기보다 어리석은 사람들은 말도 안되는 극단.

코드가 자체 문서화되어야한다는 아이디어는 그러한 훌륭한 아이디어 중 하나입니다. 그러나 실제로는이 아이디어의 실용성에 한계가 있습니다.

한 가지 문제점은 언어가 명확하고 간결하게 문서화해야 할 내용을 문서화하는 기능을 제공하지 않을 수 있다는 것입니다. 컴퓨터 언어가 향상됨에 따라이 문제는 점점 줄어들고 있습니다. 그러나 나는 그것이 완전히 사라 졌다고 생각하지 않습니다. 내가 어셈블러로 썼던 시절로 돌아가서, "총 가격 = 비과세 품목 가격 + 과세 품목 가격 + 과세 품목 가격 * 세율"과 같은 의견을 포함하는 것이 의미가있었습니다. 주어진 순간에 정확히 레지스터에 있던 것이 반드시 분명하지는 않았습니다. 간단한 작업을 수행하려면 많은 단계가 필요했습니다. 그러나 현대 언어로 작성하는 경우 이러한 주석은 한 줄의 코드를 다시 언급 한 것입니다.

"x = x + 7; // 7을 x에 추가"와 같은 주석을 볼 때 항상 화가납니다. 더하기 기호가 무엇을 의미하는지 잊어 버린 경우 매우 도움이되었을 것입니다. 내가 실제로 혼란 스러울 수있는 곳은 "x"가 무엇인지 또는 왜이 특정 시간에 7을 더해야하는지 아는 것입니다. 이 코드는 "x"에 더 의미있는 이름을 지정하고 7 대신 기호 상수를 사용하여 자체 문서화 될 수 있습니다. "total_price = total_price + MEMBERSHIP_FEE;"를 쓴 것처럼 주석은 전혀 필요하지 않습니다. .

추가 주석이 중복되도록 함수 이름이 함수의 기능을 정확하게 알려줘야합니다. 항목 번호가 데이터베이스 항목 테이블에 있는지 확인하고 true 또는 false를 반환하고 "ValidateItemNumber"라고 부르는 함수를 작성한 시간을 좋아했습니다. 괜찮은 이름처럼 보였다. 그런 다음 다른 사람이 와서 해당 기능을 수정하여 항목에 대한 주문을 만들고 데이터베이스를 업데이트했지만 이름은 변경하지 않았습니다. 이제 그 이름은 매우 오도되었습니다. 실제로 훨씬 더 많은 일을 한 것처럼 작은 일을 한 것처럼 들렸습니다. 나중에 누군가는 항목 번호의 유효성을 검사하는 데 참여하여 다른 곳에서 그 작업을 수행했지만 이름은 변경하지 않았습니다. 따라서이 기능은 이제 아이템 번호 확인과 관련이 없지만

그러나 실제로는 함수 이름이 해당 함수를 구성하는 코드만큼 함수 이름이 없으면 함수의 기능을 완전히 설명하는 것이 불가능한 경우가 많습니다. 이름이 모든 매개 변수에 대해 어떤 유효성 검사가 수행되는지 정확하게 알려줍니까? 예외 조건은 어떻게됩니까? 가능한 모든 모호성을 철자 하시겠습니까? 어느 시점에서 이름이 너무 길어 혼란스러워졌습니다. 적절한 함수 서명으로 String BuildFullName (String firstname, String lastname)을 수락합니다. 비록 그것이 이름이 "첫 번째 마지막"인지 "마지막, 첫 번째"또는 다른 변형으로 표현되는지를 설명하지는 않지만, 이름의 한 부분 또는 두 부분이 모두 비어있는 경우, 결합 된 길이에 제한을 가하면 어떻게됩니까? 초과하면 어떻게됩니까?

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