最短時間のレビューのためにコードを文書化するにはどうすればよいですか?[閉まっている]


22

数か月後にコードの読み取りと閲覧を最小限に抑えるようにコードを文書化したい。

さまざまな種類のドキュメントがあることを知っています(ソースコードと外部、シーケンス図など)。

コードを効率的に文書化する方法を知りたいので、数か月後にコードを確認したいとき、コードの読み取りとコードフローの理解に費やす時間が少なくなります。


42
後でコードを読む時間を減らすための最良の方法は、より明確理解しやすいコードを書くことです。
マエル


ドキュメントはターゲットに依存します。開発者向けの場合は、コード内のコメントが非常に役立ちます。アナリストを対象としている場合、概要の図も役立ちます。技術に精通した視聴者を対象にしている場合は、ユーザーガイドを作成してください。
Laiv

@Laiv私自身のコードとおそらく他の開発者コードの開発者の観点から。
Hamed_gibago

最大のことは、コードを小さく保つことです。問題追跡システムにアイテムを実装するのに必要なコードが大きい場合、チームはレビューするコードの量が圧倒的にならないように、それをさらに分割する方法を学ぶ必要があるかもしれません。
ベリンロリチュ

回答:


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()、上記の例のメソッドとは関係ありません。

しかし、基準と一致し、理由ではなく理由を説明し、正しい質問答えるコメントは、非常に(非常に)役に立ちます。

インラインコメント

してはいけないことの1つは(そして、もっと大きく書くことができるなら)、コードの同じ行にコメントを書くことです。それはコメントを非常に行固有にし、コードをコメントする目的を完全に逃します。

たとえば、悪いインラインコメント:

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
特定の例に同意しない-1つの巨大な関数に多くのコメントを書く代わりに、コメントとして機能する説明的な名前を持つ多くの小さな関数から構成する必要があります。コードが実際に実行していることと同期しなくなるリスクなし。
user11153

6
最後にいくつかの正気。コメントを独自の関数に使用する可能性のあるすべてのコードを抽出すると、数百のファイルに数千の関数が分散することになります。
user369450

2
2番目の例は素晴らしいです。
Monica

7
2番目の例のコメントは非常に冗長です。それらのいくつか(たとえば、「何かを見つけましたか?」)は、コードが言うことを繰り返すだけで、削除する方が良いでしょう。その他の場合、ループ条件を(stream.is_empty())にしたり、accept_literalsのチェックを外に移動するなど、リファクタリングすることで読みやすくすることができます。
Frax

3
@cpburnz、「何が起こっているのか、なぜ起こっているのかを説明するコメントを評価するには、コードコメントなしで多くのレガシープロジェクトとサードパーティライブラリを掘り下げなければなりませんでした」。まさに私のポイント:コメントは、がらくたコードを説明するためにあります。質問は「読みやすいコードをどのように書くか」であるため、最初から良いコードを書くのではなく、悪いコードを説明するコメントを書くことに焦点を当てているため、明らかにこの答えは間違っています。
デビッドアルノ

55

IMOの最良のドキュメントは、実際に必要のないドキュメントです。また、ドキュメントやコメントを書くのも嫌いです。

それが言われていると:

  • 読みやすい名前を選んでください。を使用せずn、代わりに使用numberOfItemsFoundします。
  • すべてを1行にプッシュするのではなく、計算の一部を定数変数に格納することをためらわないでください。
  • 部分的なタスクをブランチから独自の(インライン)関数に移動する(それらを再利用する場合、または親関数が長くて退屈になる場合)。
  • より複雑で、本当に必要な場合にのみ読みやすさよりもコードを最適化します。

19
これは、ドキュメント化のための適切なメトリックです(必須リンク)。
ニール

4
これもリストに載っていなければなりません。あなたがやっていることをやる理由をコードで説明してください。
t3chb0t


4
numberOfItemsFoundただし、かなり冗長です。冗長すぎること問題です。
マチューM.

6
@MatthieuM。、コード内の名前に関する問題が「冗長すぎる」ことはまれです。しかし、あまりにも簡潔または不可解なことが非常に一般的な問題です。
デビッドアルノ

25

コードをドキュメントとして扱う

コードは主要なドキュメントです。結果のアプリ、ライブラリなどが実際に何をするかを正確に記述します。そのため、そのコードの理解をスピードアップする試みは、コード自体から始めなければなりません。

読み取り可能なコードの記述方法についてはたくさん書かれていますが、重要な点は次のとおりです。

  • 悪いコードを説明し、コードを改善し、コメントを取り除くためにコメントに頼らないでください。
  • 短い焦点の関数、メソッド、クラスなどを書く
  • コンテキストに適した名前を使用します(たとえばn、ループに適しています。範囲が広いアイテムには、より長い説明的な名前が必要です)。
  • 関数名をコメントのように扱います。たとえば、名前として使用できるUpdtTbl場合、指定されたルールでテーブルを更新することを説明するコメントと共に使用しないでくださいUpdateTableContentsWithSuppliedRules
  • 可変性を避けます。変数の内容を変更するたびに、コードの複雑さが増します。可能であれば、その新しい値を(適切な名前で)新しい変数に割り当てます。
  • 最後に、そして最も重要なことは、「賢い」コードを避けることです。唯一の本当の巧妙なコードは、読みやすいコードです。複雑なコードを書いて、「すごい、ここで賢いのではないか」と思ったら、答えは「いいえ、そうではない」とほぼ保証されます。

コードを読むのが上手になる

コードの読み方は、それがどれほど単純であるかに関係なく、学んだスキルです。誰もコードを読むのが得意ではありません。練習が必要です。たくさんの練習。そのため、たとえば、単にGithubにアクセスするのではなく、Githubなどにアクセスして、使用するライブラリのコードを読み取ります。読むコードを見つけて読んでください。

コメントはコードの匂いです

そうしてはじめて、他の種類のドキュメントを入手できます。まず、前述のように、コメントを避けます。コメントを含むコードに出くわした場合、最悪の事態に備えます。コードが悪い可能性が高く、正直なところ、コメントも悪い可能性が高いです。コードを使ってうまくコミュニケーションできない人は、自然言語を使ってもっとうまくコミュニケーションできるとは考えられません。

自動生成されたAPIドキュメントに注意してください

また、自動生成されたAPIドキュメントにも注意してください。そのようなドキュメントを読むことに頼らなければならないのは、あなたのコードが読みにくいからでしょう。繰り返しになりますが、コードを単純にして、直接読むことができます。

テストもドキュメントです

テストもドキュメントです。したがって、単体テストを雑用として扱わないでください。コードがどのように機能し、どのように使用されるかについて、他の人とコミュニケーションをとる方法(6か月後の自己をここに含める)として扱います。

役立つ場合は絵を描く

UMLが好きなら、ぜひとも自分に適したツールを見つけて、コードからUML図を生成してください。これを使用してコードを生成しようとすることはありません。それは設計ツールとしては良くなく、結果として恐ろしいコードになってしまいます。

「1000ft」ビュー文書を持っている

最後に、概要ドキュメントを作成します。アプリは何をしますか?それはどうしますか?他のどのシステムに接続しますか?そういうもの。ただし、ここではコード構造を説明しようとしないでください。コードにそれをさせてください。このドキュメントで、最初にコードを書いた理由を思い出させてください。


14
コメントに代わりがあることを除いて、あなたのすべての点に同意します。のようなadd 1 to iコメントには意味がないことに同意しますが、コメントはコードが何をするのを説明する必要があります。たとえば、コードでif (!something.Exists()) {...}は次のようなコメントを使用できます // something exists only when (explanation of the broader scenario)
ジョナサン

16
役に立た// increment x x++;ないコメントのかなりの部分を見てきましたが、赤ちゃんを風呂水で捨てて、コメントが常に悪いと宣言するのは間違っています。たとえば、フォームのコメント// this case should never happen because xyz throw exception "unreachable"
-angrydust

7
とてもいいリスト。しかし、@ジョナサンのように。私はコメントに同意しません。ただし、サードパーティのフレームワークのバグを考慮する必要がある場合もあります。これは独自の機能にリファクタリングできますが、回避策(バグ番号またはバグ名/バグの説明)が必要な理由について少し説明を残しておくと便利です。
magu_

16
@DavidArnoしかし、何かが行われなかった理由を説明するコメントのためにそれを行うことはできません。のような//XXX: Not using straight-forward method Foo here because ...。このようなコメントは非常に価値がありますが、明らかな理由でコードで伝えることは不可能です。
cmaster

7
私はそれがさらに劇的であることを好みますすべてのコメントはコードで自分をうまく表現することの失敗です。たとえば、1つのメソッドに4行のコメントがあり、サードパーティのバグの回避策を説明しています。私はそれをコードでうまく表現できなかったので、コメントにしています。誰もが非常に長くて非常に説明的なメソッド名を読むため水平スクロールを楽しむことを疑うので、読みやすさが向上したと思います。「コメントはコードの匂いです」-はい、しかし、匂いのするすべてがsh * tではないことを覚えておく必要があります。
R.シュミッツ

5

カバーレターを提供する

非常に技術的な領域にいる場合を除き、コードに関するほとんどの質問は「方法」ではなく「理由」または「内容」に関するものです。

そのため、人々がコードを見る必要を減らす方法は、簡単な説明を書くことです。これの利点は、説明の概要を非常に簡単に編集できることと、これがはるかにアクセスしやすいことです。(コードを見ることを許可されない/許可されない人々にも)。

人々が技術的であっても、カバーレターはどこで何かを探すべきかのガイダンスを提供する必要があります。

シンプルで極めてミニマルなポイント:

  1. はじめに、なぜこのコード(ベース)が存在するのか
  2. コードサブセットが果たす機能
  3. コードはどこにありますか(たとえば、スクリプト名)

  1. このスクリプトセットはStackOverflowをスクレイプし、Dennis Jaheruddinによる回答に賛成票を投じます
  2. a。このスクリプトはhtmlを解析し、適切なユーザーであるかどうかを分析します
  3. a。スクリプトは次の場所にあります:ScrapeAndVote / RecognizeDennis.scr

1

私が通常得る最大の速度の向上は、それぞれがコンパイルして動作する中間ステップを表す個別のコミットを構築することです。

したがって、特定の機能を実装するために関数に新しいパラメーターを導入する必要がある場合、宣言、定義、およびすべての呼び出しサイトでパラメーターを追加するだけの1つのコミットがあります。次に、次のコミットで機能が導入され、3番目のコミットで新しい機能を使用する呼び出しサイトが更新されます。

これは簡単に確認できます。純粋に機械的な変更をすばやく一目で確認でき、邪魔にならないからです。

同様に、コードを再フォーマットする場合、常に別個のコミットにする必要があります。


1

既存の回答には1つまたは2つの明らかな相違点がありますが、強調する場合のみ、誰がどこから来たのかが明確になるように通常のアドバイスを要約します。

  1. まず、きれいなコードを書きます。その後、他の「ドキュメント」はすべて自動的に処理されます。きれいなコードはそもそも学ぶべき一連の原則です:単一責任クラス、1つのことを行う短いメソッド、優れた変数名とメソッド名、比phorに焦点を当てることによってこれらよりも優れたクラス/型名(たとえば、MultiButtSupporterソーダ)、要件を示すユニットテスト、DRY、SOLID、一貫したパラダイムなど。
  2. コードは、コードの仕組みを明らかにします。コメントは、コードが機能する理由を明らかにします。たとえば、+ 1を「1つずれたエラーを防ぐ」と説明するか、「この教科書またはWebページから派生した」と複雑な式を説明します。
  3. コメントを使って何をしていても、上記のポイント1はそれをきれいなコードで達成できるでしょう。コメントを失敗/必要な悪として見るか、両方とも編集されて時間が経つとコードとの同期が外れると嘘になることさえあります。コメントは、不適切に記述されたコードを補うべきではありません。なぜコードよりも才能や注意を払ってコメントを書くのでしょうか?

一方で、もし何か間違っているとしたら、おそらく逆に、コメントを使用することはほとんどありません。コードレビュー担当者は、バランスが間違った場所にあるかどうかを通知しますが、上記の3点計画に従うように意識的に努力すれば、とにかく最適に近いでしょう。


2
「+1が誤植ではない」または「プログラムの1つのエラーによるオフを認識していない」というコメントと、「1つのエラーによるオフを防止する」コメントの違いは何ですか?(有用なコメントは通常、ソースコードの+1より大きいもの、またはソースコード外の何かに関連します。)そのため、ポイント2では、「この教科書またはWebページから派生した」が有効で実際に素晴らしい例として残っています。次に、ポイント3は、コメントなしでクリーンな十分なコードを使用して「この教科書またはWebページから派生」を表現できる可能性があることを示唆しているようです。うわー、私はそれが動作しているのを見たいです。
ジルカハニカ

@JirkaHanikaオフバイワンは悪い例かもしれません。3に関しては、「多分それぞれ」ではなく「それぞれ」かもしれません。いいえ、コードだけではそのようなことを明確にできるとは思いません。(まあ、変数名としてgaussianFromThisTextbookNamesApproximationを試すことができますが、それは悪い考えです!)
JG
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.