최소 시간 검토를 위해 코드를 어떻게 문서화합니까? [닫은]


22

몇 달 후에 코드를 다시 읽고 탐색해야 할 필요성이 최소화되도록 코드를 문서화하고 싶습니다.

소스 코드와 외부, 시퀀스 다이어그램 등 다양한 유형의 문서가 있음을 알고 있습니다.

몇 개월 후 코드를보고 싶을 때 코드를 읽고 코드 흐름을 이해하는 데 시간이 덜 걸리도록 코드를 문서화하는 효율적인 방법이 무엇인지 알고 싶습니다.


42
나중에 코드를 읽는 데 더 적은 시간을 소비하는 가장 좋은 방법은 더 명확 하고 이해하기 쉬운 코드를 작성하는 것입니다.
Mael


설명서는 대상에 따라 다릅니다. 개발자에게 문의하는 경우 코드의 주석이 매우 유용합니다. 분석가에게 문의하는 경우 개요 다이어그램도 유용합니다. 기술을 많이 사용하는 청중을 대상으로하는 경우 사용자 안내서를 작성하십시오.
Laiv

@Laiv 내 자신의 코드 개발자와 다른 개발자 코드를 고려할 때 좋습니다.
Hamed_gibago

가장 큰 것은 코드를 작게 유지하는 것입니다. 문제 추적 시스템에서 항목을 구현하는 데 필요한 코드가 크면 팀에서 더 많은 코드를 분류하여 검토 된 코드의 양이 압도되지 않도록하는 방법을 배워야 할 수 있습니다.
Berin Loritsch

답변:


16

나는 다른 답변들이 추천 한 것들에 동의하지 않는다는 것을 인정해야한다. 그래서 나는 2 센트를 버릴 것이다.

코멘트

문서는 낯선 사람이 코드를 읽는 데 매우 유용합니다. 일반적으로 많은 것들이 즉각적으로 읽고 이해하기에 충분히 장황하지 않을 것이므로, 당신이하고있는 일을 설명해야합니다.

편집 : 주석 섹션의 토론에서 옳은 점을 지적했습니다. 과도한 주석 처리는 일반적으로 잘못된 코드를 작성할 때 수행됩니다 .

귀하의 작업에 대한 언급은 정확하고 최소한이어야하지만 제 생각에는 분명히 존재해야합니다. 15 줄의 코드마다 최소한 주석. 예를 들어 코드의 블록 위에 수행중인 작업에 대한 줄을 추가하십시오.

def login(username: str, password: str, create_session: bool = True):

    # Filter the user we need from the database
    hash = md5(password)
    users = db.table("users", db_entities.USER)
    results = [x for x in users.query(lambda c: c.get("username") == username and c.get("password_hash") == hash)]


    if len(results) == 0:
        return None, None
    else:
        # Create a login session record in the database.
        if create_session:
            sessions = db.table("sessions", db_entities.SESSION)
            ses = sessions.new()
            ses.set("username", username) \
                .set("expiery", 31536000 + time.time())
            sessions.update(ses)
            return results[0], ses
        else:
            return results[0], None

그리고 무엇 을 하고 있는지 설명하는 최소한의 주석은 코드 전체에서 매우 유용합니다. 나는 그 대답에 동의하지 않습니다

주석이 포함 된 코드를 발견하면 최악의 상황을 준비합니다. 코드가 잘못되었을 수 있으며 정직하게 말하면 주석도 잘못 될 수 있습니다.

여러 번, 정상적으로, 좋은 코드가 문서화되었습니다. 나쁜 프로그래머는 "괜찮아, 내 코드가 나쁘다. 좀 더 명확하게하기 위해 문장 몇 개를 추가하자"와 같은 문서를 보는 것이 사실이다.

예, 그리고 이것은 꽤 많이 발생하지만 깨끗한 코드를 작성하는 훌륭한 프로그래머도 코드로 돌아가서 왜 그런 식으로 기능을 수행해야하는지 또는 왜 그 기능이 필요한지 이해하고 싶어한다는 것도 사실입니다 약간 중복되는 것처럼 보이는 라인 ...

그렇습니다. 명백한 것을 설명하는 주석, 불분명 한 주석, "이 코드가 문서화 되었으면 무엇이든"을 확인하기 위해 함께 작성된 주석은 코드 냄새입니다. 코드를 읽기 어렵고 짜증나게합니다. (아래 예제 추가)

# Logging into Gmail when the module is imported
_client = login()
def get_client():
    global _client
    return _client

설명의 예 : "아니요, Sherlock. _client = login()메일 서비스에 로그인합니까? OMG!"

더 명확하게 : login()방법은 login()위 예제 의 방법 과 관련이 없습니다 .

그러나 이렇게 코멘트 기준과 일치하는 이유가 아닌 방법의를 설명하고, 올바른 질문에 대답 이다 아주 아주 ( 아주 도움)를.

인라인 코멘트

당신이 해서는 안되는 한 가지 (그리고 더 크게 쓸 수 있다면) 코드의 동일한 줄에 의견을 쓰십시오. 주석을 매우 행별로 지정하므로 코드 주석 달기의 목적을 완전히 놓칠 수 있습니다.

예를 들어 잘못된 인라인 주석 :

outer = MIMEText(details["message"]) # Constructing a new MIMEText object
outer["To"] = details["to"] # Setting message recipient
outer["From"] = "xAI No-Reply" # Setting message sender
outer["Subject"] = details["subject"] # Setting message subject
outer.preamble = "You will not see this in a MIME-aware mail reader.\n" # I don't know what I'm doing here, I copied this from SO.
msg = outer.as_string() # Getting the string of the message
_client = details["client"] # Assigning the client
_client.sendmail(SENDER, details["to"], msg) # Sending the mail

주석 없이이 코드를 읽고 이해하기가 훨씬 어려워 지저분하고 읽을 수 없게 만듭니다.

대신 코드 내부의 주석은 코드의 블록 위에 배치해야하며 코드 블록을 읽는 동안 발생할 수있는 중요한 질문에 답변해야합니다.

# Constructing the email object with the values 
# we received from the parameter of send_mail(details)
outer = MIMEText(details["message"])
outer["To"] = details["to"]
outer["From"] = "xAI No-Reply"
outer["Subject"] = details["subject"]
outer.preamble = "You will not see this in a MIME-aware mail reader.\n"
msg = outer.as_string()

# Sending the mail using the global client (obtained using login())
_client = details["client"]
_client.sendmail(SENDER, details["to"], msg)

훨씬 더 명확합니까? 이제 login()함수 를 사용해야하고 send_mail()사용한 모든 것에 매개 변수를 제공 해야한다는 것도 알게되었습니다 . 조금 도움이되지만 한 가지가 여전히 누락되었습니다.

기능 문서

널리 논의되었습니다. 당신은 항상 독자들에게 당신의 기능이 무엇인지, 왜 그리고 무엇을하는지 알려 주어야합니다. 그렇게하는 방법은 설명서에 속하지 않으며 기능 각주에 속할 수도 있습니다.

매개 변수가 무엇인지 예상하고 특정 방법으로 매개 변수를 얻거나 작성하려면 명확하게 설명해야합니다. 함수가 무엇을 반환해야하는지, 그 용도가 무엇인지 등을 선언해야합니다.

다시, 그것은 내 의견을 작성하는 동안 나의 의견과 방법론입니다. 그뿐만 아니라 다른 답변에 동의 할 수없는 것 중 일부 일뿐입니다. 아, 물론 주석은 코드를 읽는 것이 아니라 코드 자체를 읽습니다. 깨끗하고 이해하기 쉬운 코드를 작성하십시오 . 코딩하는 동안 미래의 자기 자신을 생각하십시오. ;-)


5
주어진 예제에 동의하지 않음-하나의 거대한 함수로 많은 주석을 작성하는 대신 설명적인 이름을 가진 많은 작은 함수에서 주석으로 작성해야합니다. 코드가 실제로 수행하는 작업 과 동기화되지 않을 위험이 없습니다 .
user11153

6
마침내 약간의 정신력. 주석을 자체 함수에 사용할 수있는 모든 코드를 추출하면 수백 개의 파일에 수천 개의 함수가 분산됩니다.
user369450

2
두 번째 예는 사랑 스럽습니다.
Monica와 가벼운 가벼움

7
두 번째 예의 주석은 너무 장황합니다. 그들 중 일부 (예 : "우리가 찾은 것이 있습니까?")는 코드가 말한 것을 반복하고 더 잘 제거 될 것입니다. 다른 경우에는 (stream.is_empty ()) 루프 조건을 만들거나 accept_literals에 대한 검사를 외부로 옮기는 등의 리팩토링을 통해 가독성을 높일 수 있습니다.
Frax

3
@cpburnz, "어떤 일이 일어나고 있는지, 왜 그런지를 설명하는 의견에 감사하기 위해 너무 많은 레거시 프로젝트와 타사 라이브러리를 코드 주석없이 조사해야했습니다." 정확히 내 요점은 : 쓰레기 코드를 설명하기 위해 주석이 있습니다. 문제는 "읽기 쉬운 코드를 어떻게 작성 하는가"이기 때문에 우선이 코드를 작성하는 대신 나쁜 코드를 설명하기 위해 주석을 작성하는 데 중점을두기 때문에이 대답은 분명히 틀립니다.
David Arno

55

IMO 최고의 문서는 실제로 필요하지 않은 문서입니다. 나는 또한 문서와 의견을 쓰는 것을 싫어합니다.

그렇게 말하면서 :

  • 읽을 수 있고 말하는 이름을 선택하십시오. 예를 들어을 사용하지 말고 n대신 사용하십시오 numberOfItemsFound.
  • 모든 것을 한 줄로 밀어 넣는 대신 계산 부분을 상수 변수에 저장하는 데 주저하지 마십시오.
  • 부분 작업을 재사용하거나 부모 기능이 길고 지루한 경우 분기에서 자체 (인라인) 기능으로 이동하십시오.
  • 실제로 필요한 경우 코드를보다 정교하게 작성하고 가독성을 최적화하십시오.

19
다음 은 문서화에 대한 좋은 지표 입니다 (필수 링크).
Neil

4
이것은 또한 목록에 있어야합니다 : 당신이하고있는 일을 코드로 설명하십시오 .
t3chb0t


4
numberOfItemsFound그래도 장황하다; 너무 장황한 것도 문제입니다.
Matthieu M.

6
@MatthieuM., Rarely는 "너무 장황하다"는 코드 이름에 문제가있다. 너무 간결하거나 암호는 매우 일반적인 문제입니다.
David Arno

25

코드를 문서로 취급

코드는 기본 문서입니다. 결과 앱, 라이브러리 또는 실제로 수행하는 작업을 정확하게 설명합니다. 따라서 해당 코드에 대한 이해를 높이기위한 모든 시도는 코드 자체에서 시작해야합니다.

읽을 수있는 코드를 작성하는 방법에 대한 많은 글이 있지만 핵심 요점은 다음과 같습니다.

  • 잘못된 코드를 설명하고 코드를 개선하고 주석을 제거하기 위해 주석에 의존하지 마십시오.
  • 짧은 초점을 맞춘 함수, 메소드, 클래스 등을 작성
  • 문맥에 적합한 이름을 사용하십시오 (예 : n루프에 적합하고 더 넓은 범위의 항목에 대해서는 더 긴 설명이 필요함).
  • 함수 이름을 주석 인 것처럼 취급하십시오. 예를 들어 , 이름으로 사용될 수있을 UpdtTbl때 제공된 규칙으로 테이블을 업데이트하는 것을 설명하는 주석과 함께 사용하지 마십시오 UpdateTableContentsWithSuppliedRules.
  • 변경을 피하십시오. 변수의 내용을 변경할 때마다 코드의 복잡성이 증가합니다. 해당하는 경우 새 값 (이름이 좋은)에 새 값을 지정하십시오.
  • 마지막으로, 가장 중요한 것은 "영리한"코드를 피하십시오. 유일한 영리한 코드는 읽기 쉬운 코드입니다. 복잡한 코드를 작성하고 "와우, 내가 영리하지 않습니까?"

코드를 잘 읽으십시오

얼마나 간단한 지에 관계없이 코드를 읽는 것은 학습 된 기술입니다. 자연스럽게 코드를 읽는 사람은 없습니다. 연습이 필요합니다. 많은 연습. 예를 들어, Github 또는 다른 곳으로 이동하여 해당 라이브러리를 사용하는 대신 사용하는 라이브러리의 코드를 읽으십시오. 읽고 읽을 코드를 찾으십시오.

주석은 코드 냄새입니다

그래야만 다른 유형의 문서를 얻을 수 있습니다. 첫째, 앞에서 언급했듯이 주석을 피하십시오. 주석이 포함 된 코드를 발견하면 최악의 상황을 준비합니다. 코드가 잘못되었을 수 있으며 정직하게 말하면 주석도 잘못 될 수 있습니다. 코드를 통해 의사 소통을 잘 못하는 사람은 자연어를 통해 더 나은 의사 소통을 할 수 없을 것입니다.

자동 생성 된 API 문서를주의하십시오

또한 자동 생성 된 API 설명서를주의하십시오. 그러한 문서를 읽는 데 의지해야한다면 코드를 읽기가 어렵 기 때문입니다. 다시 말하지만 코드를 간단하게 만들면 직접 읽을 수 있습니다.

테스트도 문서입니다

테스트도 문서화됩니다. 따라서 단위 테스트를 집안일로 취급하지 마십시오. 코드 작동 방식 및 사용 목적에 대해 다른 사람 (6 개월 후 여기에 포함됨)과 의사 소통하는 방법으로 취급하십시오.

도움이된다면 그림 그리기

UML을 좋아한다면 반드시 자신에게 좋은 도구를 찾고 코드에서 UML 다이어그램을 생성하십시오. 결코 코드를 생성하기 위해 사용하려고 시도하지 마십시오. 디자인 도구로는 좋지 않으며 결과적으로 끔찍한 코드가 생깁니다.

"1000ft"보기 문서가 있어야합니다

마지막으로, 개요 문서를 작성하십시오. 앱의 기능은 무엇입니까? 어떻게합니까? 어떤 다른 시스템에 연결되어 있습니까? 그런 것들. 여기서 코드 구조를 설명하려고 시도하지 마십시오. 코드가 그렇게하자. 이 문서가 왜 코드를 처음에 작성했는지 알려줍니다.


14
의견이 그 자리를 차지한다는 점을 제외하고는 모든 요점에 동의합니다. 와 같은 주석에는 아무런 의미가 없지만 add 1 to i, 주석은 코드가 작동하는지 설명해야합니다 . 예를 들어, 코드 if (!something.Exists()) {...}는 다음과 같은 주석을 사용할 수 있습니다 // something exists only when (explanation of the broader scenario).
Jonathan

16
우리는 모두 쓸모 // increment x x++;없는 의견에 대한 공정한 의견을 보았지만, 아기를 목욕물에 버리고 의견이 항상 나쁘다고 선언하는 것은 잘못입니다. 예를 들어 양식의 주석입니다 // this case should never happen because xyz throw exception "unreachable".
angrydust

7
아주 좋은 목록입니다. 그러나 @Jonathan과 같습니다. 의견에 동의하지 않습니다. 때로는 타사 프레임 워크의 버그를 고려해야합니다. 이것은 자체 기능으로 리팩토링 될 수 있지만, 해결 방법 (버그 번호 또는 버그 이름 / 버그 설명)이 필요한 이유에 대해 약간의 설명을 남겨 두는 것이 좋습니다.
magu_

16
@DavidArno 그러나 당신은 왜 무언가가 수행 되지 않은지를 설명하는 의견으로는 그렇게 할 수 없습니다 . 처럼 //XXX: Not using straight-forward method Foo here because .... 이러한 의견은 매우 귀중 할 수 있지만 명백한 이유로 코드와 함께 전달하는 것은 불가능합니다.
cmaster

7
나는 그것이 훨씬 더 극적인 좋아 : 모든 코멘트 코드 자신을 잘 표현하는 실패 . 예를 들어 한 가지 방법으로 4 줄 주석을 작성하여 타사 버그의 해결 방법을 설명합니다. 코드로 잘 표현하지 못해서 주석에 있습니다. 나는 누군가가 매우 길고 매우 설명적인 메소드 이름 을 읽기 위해 가로로 스크롤하는 것을 의심하기 때문에 가독성을 향상 시켰다고 말하고 싶습니다 . "코멘트는 코드 냄새입니다."-네, 그러나 우리는 냄새가 나는 모든 것이 sh * t라는 것을 기억해야합니다.
R. Schmitz

5

표지를 제공하십시오

매우 기술적 인 영역에 있지 않다면 코드와 관련된 대부분의 질문은 '방법'이 아니라 '왜'또는 '무엇'에 관한 것입니다.

따라서 사람들이 코드를 보지 않아도되는 방법은 간단한 설명을 작성하는 것입니다. 이것의 장점은 설명의 개요를 아주 쉽게 컴파일 할 수 있고 훨씬 더 접근하기 쉽다는 것입니다. (코드를 볼 수 없거나 허용하지 않는 사람들에게도).

사람들이 기술적 인 사람이라하더라도, 표지는 그들이 무엇을 찾아야하는지에 대한 지침을 제공해야합니다.

매우 최소한의 간단한 포인트 :

  1. 소개,이 코드 (기본)가 존재하는 이유
  2. 코드 서브 세트가 수행하는 기능
  3. 코드는 어디에 있습니까 (예를 들어 스크립트 이름)

  1. 이 스크립트 세트는 StackOverflow를 폐기하고 Dennis Jaheruddin의 답변을지지합니다.
  2. 에이. 이 스크립트는 HTML을 파싱하고 올바른 사용자인지 분석합니다.
  3. 에이. 스크립트는 ScrapeAndVote / RecognizeDennis.scr에 있습니다.

1

필자가 일반적으로 컴파일하고 작동하는 중간 단계를 나타내는 별도의 커밋을 구축하여 얻는 가장 큰 속도 향상입니다.

따라서 특정 기능을 구현하기 위해 함수에 새 매개 변수를 도입 해야하는 경우 선언, 정의 및 모든 호출 사이트에서 매개 변수를 추가하는 것 외에는 아무것도하지 않는 커밋이 있습니다. 그런 다음 다음 커밋은 기능을 소개하고 세 번째 커밋은 새로운 기능을 사용하는 호출 사이트를 업데이트합니다.

순전히 기계적인 변경 사항을 신속하게 파악한 후 벗어날 수 있기 때문에 검토가 쉽습니다.

마찬가지로 코드를 다시 포맷하는 경우 항상 별도의 커밋이어야합니다.


1

기존 답변 사이에 한 가지 또는 두 가지 명백한 의견 차이가 있지만, 강조 할 때만 모든 사람들이 어디에서 왔는지 분명하게 일반적인 조언을 요약하려고 노력할 것입니다.

  1. 먼저 깨끗한 코드를 작성하십시오. 그 밖의 다른 "문서"는 그 후 스스로 처리합니다. 클린 코드는 우선 단일 책임 클래스, 한 가지 역할을하는 짧은 메소드, 좋은 변수 및 메소드 이름, 은유에 중점을 두어 더 나은 클래스 / 유형 이름 (예 : MultiButtSupporter a 요구 사항, DRY, SOLID, 일관된 패러다임 등을 나타내는 단위 테스트.
  2. 코드는 코드 작동 방식을 보여줍니다. 주석은 코드가 작동하는 이유를 나타냅니다. 예를 들어, "1로 오류를 방지합니다"로 +1을 설명하거나 "이 교재 또는 웹 페이지에서 파생 됨"으로 복잡한 수식을 설명하십시오.
  3. 주석으로 무엇을하고 있든 위의 포인트 1은 깨끗한 코드로 달성 할 수 있습니다. 주석을 실패 / 필요한 악으로 보거나, 시간이 지남에 따라 코드가 편집 될 때 코드와 동기화되지 않으면 거짓말을합니다. 주석이 잘못 작성된 코드를 보완해서는 안됩니다. 왜 주석이 코드보다 더 많은 재능이나주의를 기울여 작성 되었습니까?

반면에, 내가 다른 방법으로 너무 많이 잘못하면 거의 주석을 사용하지 않습니다. 코드 검토자는 잘못된 장소에 잔액이 있는지 알려 주지만 위의 3 점 계획을 따르기 위해 의식적으로 노력하면 아마도 최적의 상태에 가깝습니다.


2
"+1은 오타가 아닙니다"또는 "프로그램의 하나의 오류로 인해 꺼짐을 알 수 없습니다"라는 주석과 "1에서 오류를 방지"주석과 다른 점은 무엇입니까? (유용한 주석은 일반적으로 소스 코드에서 +1보다 큰 것 또는 소스 코드 외부의 것에 관한 것입니다.) 따라서 여전히이 텍스트 북이나 웹 페이지에서 파생 된 것은 여전히 ​​귀하의 포인트 # 2에서 유효하고 실제로 훌륭한 예입니다. 그러면 요점 # 3은 주석없이 충분한 코드를 사용하여 "이 교재 또는 웹 페이지에서 파생 된"표현할 수 있다고 제안하는 것 같습니다. 와우, 나는 그것을 실제로보고 싶다.
Jirka Hanika

@JirkaHanika 어쩌면 한 사람이 나쁜 예일 것입니다. 3의 의미는 "각각"보다는 "각각"이었다. 아니, 코드만으로는 그런 것들을 명확히 할 수 있다고 생각하지 않습니다. (글쎄, gaussianFromThisTextbookNamesApproximation을 변수 이름으로 시도해 볼 수는 있지만 나쁜 생각입니다!)
JG
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.