変数名、関数名とコメントでは表現する内容が違う

先日Twitterにこんなことを書いた。

なにやってるかはコード見ればわかる。なにやろうとしてるかはコードみてもわからんからコメント書け。


そうしたところ、変数・関数(メソッド)に適切な名前をつければ改めてコメントの必要はないんじゃないかという指摘をうけた。
そんで、しばらくやりとりをしたのだけど、その中で結論として変数名・関数名やコメントで表現する内容が違うということに気づいた。


やはり、変数名・関数名には、その機能を表すものをつけることになる。一方で、コメントにソースコードで表されていることを書くのは意味がない。

if(a==0){
//aが0のとき
}

のようなコメントは、意味のないコメントとしてよく例にあげられる。

if(a==0){
//パラメータが渡されなかったとき
}

のように、判定の意図を書くべきだ。


ここで、変数をaじゃなくてまともな名前にすればいいんじゃないかという話で、

if(paramCount==0){
}

とすればいいかといいのではないかという指摘*1だったのだけど、やはり変数名はその機能を表しているので、意図はあらわせていない。パラメータの個数が0であるというのは、パラメータを受け取ったかどうかの判定材料として使っているだけで、やりたいこととはズレる。


で、判定の意図をあらわそうとすると

boolean wasParamReceived = paramCount != 0;
if(!wasParamReceived){
}

のようになって、作業性が犠牲になっていく。変数名は肯定形にしたいので条件が逆転しちゃうというようなことも起こる。
たぶん、プログラムで意図を表そうとすると、作業性は犠牲になっていくんじゃないだろうか。


ただ、変数の場合は、値に名前をつける役割が大きく、意図もあらわしやすい。
問題は関数で、関数は処理をまとめて名前をつける役割よりも、処理を複数の場所で使いまわせるようにするという役割の場合が多い。
このとき、なるべく再利用がしやすいようにと考えると、できるだけコンテキストから機能を切り離して抽出するということになる。コンテキストに依存してしまうと、再利用がしにくい。
つまり、再利用しやすい関数をつくろうとすると、意図が抜かれるということだ。そうやって作られた関数の名前は、意図を反映しない名前になる。
そうすると、呼出側では、コメントで意図をあらわすことになる。

//処理中に行われた変更を画面に反映させておく
updateView();

とか。
もちろん、「処理中に行われた変更を画面に反映」を意味する名前の関数を作るということも可能だろうけど、作業性はかなり悪くなる。


と書いたところで、関数の場合は、戻り値を受ける変数や引数に渡す変数の名前で意図が結構表現できることに気づいた。
そうすると問題は、変数名で意図を表現することと同じになる。
方針としては、関数はコンテキストに依存しないように機能を抜きだして機能の名前をつける、変数名は作業性とのバランスをとってなるべく意図をあらわす、あらわしきれない意図はコメントで書く、となるだろうか。

*1:実際のやりとりとは違うけど