コメントとdocstring

1ヶ月後でも読めるソースコードの書き方 - 何気に大変
この記事の中で、「読みやすいコード」の要件として「コメントが少ない」というのがあってちょっと気になりました。

役に立たないコメントを残すと後々害になる

結論としては、言っていることは妥当で、コメントが「少ない」っていうよりは
「役に立たないコメントを書かない」ことが大事だって言いたいんだと思いました。

名前を適切に付ければコメントはかなり減らせると思います。
コメントというものは得てしてほとんど(あるいはまったく)メンテされません。
メンテされないコメントほどアテにならないものはありません。
いつでも動いているコードの方が正しいので
「コメントがアテにならないならコードをコメントにすればいいじゃない」というわけです。

僕が見たコメントの中で嫌だなと思ったのは、

単純で簡潔な処理なのに1行ずつ丁寧に処理を説明するコメント
z = x + y #変数zに引数の合計を代入する

とか、いくら何でも「それはわかってる」って思うもの。
これはコメントと本当のコードで2倍に行数が増えるだけの無駄だと思う。

コードの変更履歴を残す為のコメントアウト

これひどいww

def foo(x, y):
    # modified at 2005/07/08 by da.re.ka
    # return x * y
    return x ** y

こういう、前のコードを残しておくコメント。
僕がJavaとかストアドプロシージャのコードを触るお仕事をしていた頃、
これがどんどん増えていって本当のコードの数倍の行数を変更履歴コメントが占めていたことがありました。
当時、あまりにも処理が理解しづらくてわざわざコメントを消すスクリプトを書いた覚えがあります。

いまどきこんなばかなことをする現場はないと思うけど、
こういうのはバージョン管理システムを使って管理して欲しいですよね。

他人に自分の意図を伝えるためのコメントは大切

逆にコメントを付けるべきところは、
カリカリにチューニングしていて一見してなにをしているのか分からないコードや、
理由があってわざと効率の悪い方法や無駄なことをしているところなどです。
後者などは後々リファクタリングの名のもとに削除されかねませんので、
コメントを付ける意味があります。

これもまったくその通りだな〜って思いました。
僕も変に見える処理を書いたときは意図をコメントに残します。

docstringからdoctest

doctestのコンセプトを翻訳があったのでちょっと目を通しました。
Bitbucket | The Git solution for professional teams

docstringには関数やクラスの概要を書くけど、その中にUsageを書いておくと役立つという話。
そしてそれが実際にテストとして実行可能だとなお良しというのがdoctestのコンセプトみたいです。

昨日僕が読んでいたActive StateのPython Recipeも、doctestが書いてありましたね。
Temporary substitution of object in modules via with statement « Python recipes « ActiveState Code

    Example::

        >>> from StringIO import StringIO
        >>> capture = StringIO()
        >>> with substitute('sys.stdout', capture):
        ...     print('foo')
        >>> capture.getvalue()
        'foo\\n'

こういうやつですね。
これはちゃんと

if __name__ == '__main__':
    import doctest
    doctest.testmod()

こういうのを書いておくとテストとして実行されるんです!
すごい!

ただ、doctestに何でも書くとドキュメント部分も本当の処理の部分も読みにくくなる上、テストがむしろやりにくいという難点もあります。
僕の今までの経験と見聞してきたことから判断すると、

  1. 境界値テストとか、マトリクスを作って沢山のパターンを検証するテスト
  2. mock, stub, dummyなどを使うテスト

こういうものは素直にunittestを書いた方がいいんじゃないかな〜と思います。