Hatena::ブログ(Diary)

土屋つかさのテクノロジーは今か無しか

2017-05-20

「正しく書かれたソースコードにコメントは必要ない」なんて幻想だという話(補足編)


 前回書いた「「正しく書かれたソースコードにコメントは必要ない」なんて幻想だという話( http://d.hatena.ne.jp/t_tutiya/20170519/1495197904 )」は土屋のブログ記事にしては珍しくはてブやコメント、twitterで反響を幾つか頂きました。その中の幾つかを紹介します。分かっているとは思うけど、サンプルコードはJavaScriptを意識してますがてきとーです。

案1:マジックナンバーを定数化する

MAX_OPAQUE = 1.0f //定数宣言のつもり
if (alpha < MAX_OPAQUE){
 //処理A
}

 "1.0f"に意図を設定すればコメントが不要なのではないか説。うーん、これはちょっと難しいかな……。"MAX_OPAQUE"が正しい変数名だとは思えませんが、どんな名前にすれば意図が説明できるのかちょっと思いつきません。また、数式が複雑化した場合に対応仕切れないのではないかと思います。

案2:条件式をメソッド化する

function isFadeinCompleted(){
  return alpha < 1.0f
}

if (isFadeinCompleted()){
  //処理A
}

 条件式をメソッド化し、そのメソッド名で意図を説明すればコメントが不要なのではないか説。ここではalphaがメンバ変数であると仮定していますが、そうでない場合もメソッド呼び出し時に引数が一個増えるだけです。

 これは一つの回答と言えます。ただ、この条件式がコード上でこの一箇所しか現れない場合に、「(コメントではなく)コードのみで意図を説明する」ためだけにメソッド化すべきなのかには疑問があります(名前空間汚染も起こりますし)。

 実は前回の記事でも当初はこのコードを書いていたのですが「実務で書く時、土屋はこのメソッド化はしないな」と考え、削除したのでした。これが何故なのか理論化できていないのですが、土屋の中では「1行の式を返すだけの処理をメソッド化しない」というルールがあるような気がしています(これはいずれまた検討してみます)。

※5月21日22時追記:ここの「1行の式を返すだけの処理をメソッド化しない」ですが、「一箇所からしか呼ばれない1行の式を返すだけの処理をメソッド化しない」と書こうとしたのを間違っていましたすみません。複数箇所から呼ばれる処理であれば行数に関係なくメソッド化を検討します。

案3:条件式を一時変数化する

var isFadeinCompleted = alpha < 1.0f

if (isFadeinCompleted){
  //処理A
}

 条件式の実行結果を一時変数に代入し、その変数名で意図を説明すればコメントが不要なのではないか説。

 これは土屋が書かないタイプのコードで、なるほどと思いました。条件式がここ一箇所しか使われていないとしても名前空間を汚染しませんし、「1行の式を返すだけの処理をメソッド化しない」という土屋のマイルールにも抵触していません。また、一般的なコンパイラなら最適化されてオーバーヘッドは発生しないでしょう(もしかしたらlint時に警告が出るかもしれない)。

 ただ、自分が書くかというと、どうかなあ……? そこまでしてコードで意図を説明しなければならないのか? と感じます。本来無理筋である(と土屋が思っている)「コード=ドキュメント」を達成するために、逆に回りくどいことをしているように思えます。

コメント工学のススメ

 「コメントで設計意図を記述すると二重管理になる」という批判をよく聞くのですが、結局なにかしらの仕様書を出力しなければならない以上、どこかで自然言語のテキストを書く事になるのであれば、それがコメントとしてコードに埋め込んである方がトータルの作業コストは下がるのではないでしょうか。

 これは土屋が作家だからなのかもしれませんが、「なぜコメントの(セマンティクスの)記法が検証されていないのか」については強い疑問があります。土屋は「コメントを機械的に書きたい」と常々思っていて、自分の中ではなんとなくなルールを定義して運用しています。これについてはまたいずれ記事にしたいと思っています。

 近年ではコメントにタグを埋め込むことで自動ドキュメント化できる仕組みがありますが、もっとプリミティブな部分で「コメント」を検証する必要があると感じています。コメントは必要だ! 何百行もコメント無しで書くんじゃねえ! 後任者がメンテできねえだろうが!(私情)

naoya2knaoya2k 2017/05/21 22:24 案2も案3も変数名がダメです。isFadeinRunningとかならまだマシですが、むしろコメントが必要な反例になってしまっていると思います。

t_tutiyat_tutiya 2017/05/21 22:35 え、あ、ホントだ! すみません前記事のコメントで頂いた変数名をそのまま使ったのですが、符号を反転してるのをスルーしていました><。
はてブの議論等がこの名前をベースに行われているのでこのままにしておきますが、一段落したらしれっと直しておきますー。

Error401Error401 2017/05/22 18:09 「何をしているかを説明するコメントは不要」「コードそのものの説明は不要」「whyのコメントは有用」という人が多いですが、私は前二つも有用だと思っています。
さらには、日本語コメント推奨です。

理由その1:
自己叙述的なコードであればコメント不要、とよく言われますが、isFadeinRunning, isFadeinCompleted,
isFadeinHogehogeなどを見て一瞬で内容を把握できる人はそれほど多くないと思います。
でも「フェードインが未完了の場合」なら、だれでも一瞬でその意味を把握できます。

理由その2:
コードを読むのは、対象ドメインに関する英語に詳しい人ばかりではありません。
そもそもが、その英単語の意味がわからず(あるいは、コーディングした人が誤って選択したり)、そこでコードリーディングが止まります。

でも「フェードインが未完了の場合」というコメントがあったなら!!!

理由その3:
日本語を一瞥してその意味を把握する範囲とそのスピードは、いわずもがなですが、日本語の方が速いです。
日本人なら、「フェードイン/が/未完了/の/場合」などと品詞を区切って理解する必要などなく、たいていの人は一目で「フェードインが未完了の場合」全部を理解するでしょう。

日本語コメント最高!

Error401Error401 2017/05/22 18:17 追記。

教条主義的に「リーダブルコードを読め」という人への武装。

『リーダブルコード』にはこう書かれてますよ。

P68から引用。
> WHAT・WHY・HOWをコメントに書くべきか?
> 「コメントにはWHATではなく(あるいはHOWではなく)WHYを書こう」というア ドバイスを耳にしたことがあるかもしれない。確かにキャッチーな言葉だけど、少し単純化しすぎていて、人によって受け取り方が違うかもしれない。ぼくたちからのアドバイスはこうだ。「コードを理解するのに役立つものなら何でもいいから書こう」これなら、WHATでもHOWでもWHYでも(あるいは3つ全部でも)書ける。

love0hatelove0hate 2017/05/24 22:23 突っ込むのも野暮なのですが、武装なるものをされたので、少し補足しておきます。

まず、リーダブルコード読みましょうよ、と言ったのは

> 「なぜコメントの(セマンティクスの)記法が検証されていないのか」

の1つの答えがリーダブルコードだからです。コメント含め、良いコードを書くためのノウハウが詰まった書籍で、まさに我々が求めているものでは、という。もし id:t_tutiya さんがこの本を読んでいたら、また違った思いが込められた記事が書かれたのではと思うわけです。

目次を見れば分かりますが、リーダブルコードでは、コメントに関して、5章と6章で20ページ近く割かれています。最初の5.1節で述べられているのは、

> コメントするべきでは「ない」こと
> コメントのためのコメントをしない
> ひどい名前はコメントをつけずに名前を変える

です。こういったことに同意している人からすると、

> 理想を言えばコード1行ごとにコメントを書きたいくらいです

なんて言われると、お、おう…となるわけですね。ブクマのコメントの多くは、そういった感覚から書かれているものでしょう。 (ちなみに、案3についても、8.2 要約変数 で触れられていたりします。)

なお、p.68について言及されたコメントについては、とにかく日本語を書くべきと言いたいようですが(?)、その引用は日本語を書くことは関係ないような…?もし、リーダブルコードもとにかくコメント書くことを推奨している、という話だとしたら、他にも色々なこと書いてあるようだけども?という問いかけをしておきます。

t_tutiyat_tutiya 2017/05/25 07:25 > id:love0hate さん
コメントありがとうございます。

リーダブルコードの5章も6章も、より適切なコメントの付け方の話であり、それ自体は有益ですが、セマンティクスについて検証されているというほど詳細な物ではないと認識しています。

また、同章ではメソッド名を適切に変更することによってそのメソッドを説明するコメントを省略できるという説明はありますが、(今回の記事のように)ある式の説明をコメントですべきか、メソッド名にすべきかについては議論されていません(土屋の読み逃しだったら教えて頂けると助かります)。

今回の(「補足編」の)方の記事にの話ですれば、「8.1説明変数/8.2要約変数」あたりが適切かと思いますが、それはカプセル化の粒度として本当に正しいのか? リーダブルコードの記述を無批判に受け入れて良いのか? という疑問に端を発する物でした。

また、

> 理想を言えばコード1行ごとにコメントを書きたいくらいです

これは、土屋は「コードコンプリート」で紹介されているPDLを初期設計に採用していて、非英語圏のエンジニアが採用する場合、他に手段がないという認識から来ている発言です(「1行ごとに1コメント」については、今回の記事の本論から外れるので、またいずれ書ければと思います)。

Error401Error401 2017/05/26 18:33 > id:love0hate さん
『リーダブルコード』のP68の引用は、確かに他にも色々なこと書いてあるけれど、「5章 コメントすべきことを知る」のまとめ的コラムだということで引用しました。

コメントに関しては、WHYのみ有用、WHAT/HOWのコメントは不要と言いたがる人たちが目につきます。それに対して、みんな大好き『リーダブルコード』にはそんなこと書いてないよということですね。

日本語コメントの件は、「フェードインが未完了の場合」というコメントより、isFadeinComletedとかisFadeinRunningとか、isFadeinInProgressとか、なにかそんな単語のかたまりで置き換えた方が自己叙述的であり素晴らしいという人が多いけど、いやいや、「フェードインが未完了の場合」というコメントの方がずっとわかりやすいよということです。
なぜ、わかりやすいか、それは日本語であるということも大きく関係しています(これは私個人の主張)。

「a = 0; // aを0で初期化する」なら誰もが「それは不要なコメントだ」と言うでしょうが、今回の件に関しては、そのコメントは不要だというのは少々不躾じゃないかと、多少の憤りを感じたわけですね。それが私がコメントを書いたモチベーション。

t_tutiyat_tutiya 2017/05/27 10:14 > id:Error401 さん
 前も含めてコメントありがとうございます。

 仰る通り、土屋がコメントで意図を書くというのは「母国語のコメントの方が可読性が高い」という主張が含まれています(これ、自分の中であまりに自明なので、記事ではほとんど触れていませんでした。後出しになってしまってすみません>ブコメ他で反応して下さった皆様)。

 その意味では、以下のように書いていいのであれば、コメントがなくても構いません。

function フェードインが未完了の場合(){
return alpha < 1.0f
}

if (フェードインが未完了の場合()){
//処理A
}

 非英語圏のエンジニアには、アルファベットの羅列を瞬時に「意図」として読み取ることは困難で(少なくとも、ネイティブよりも遅くなる)、そのタイムラグを補完するためには母国語でのアシストが必要になると考えています。UTF8で書ける言語(例えばrubyとか)では既に可能なスタイルです(ユーザーが少ないので、全角半角問題などがなかなか……)

 この日本語識別子コーディングについては、改めて記事を書きたいと思っています。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/t_tutiya/20170520/1495244763