kazasiki's blog

プログラミングとかVRゲームとか

変数名に型を含むのは避けた方が良い

変数名に型を含むのは避けた方が良い。異論は認める。まず、つい最近リファクタリング(?)で大変苦労した話をさせてください。

例えば、Userクラスがあったとして、きっとみなさんはコードの何処かにこう書くでしょう。

user = User.new(name: 'hoge', age: 12)
print user.name

Ruby on Railsを使ってるときもModel層にUserクラスがあれば、きっと上のようなコードを書くでしょう(だってRuby on Railsチュートリアルでもそうなってるし!)。

ここで何かしらの理由があってUserテーブルをCustomerテーブルに変更するとしましょう。ほら、サービス自体が有料会員制に変更になったのでUserよりもCustomerの方が正しい気がします(?)。そして、これは恐らくみなさんが思っているよりもとても辛い作業になります。

テーブル名の変更などはさておき、クラス名の置換は問題なく行えます。IDEなどの機能を使えば数分の作業でしょう。ただし、この後に変数名の置き換えの作業があります。例えば、先ほどのコードのuserという変数はどうやって見つけましょう?Userクラスを探せばその近くにいますし、userという文字列でgrepしたらだいたい見つかるんですが、一斉置換するのが難しい作業であることは明らかです。tmp_userなどちょっと変形した変数名もありえます。usrのようなtypoなのか省略なのかよくわからないものもあるでしょう。

以上の話から導かれる私の結論は、変数名に型を含むのはリファクタリングを難しくするということです。

とはいえ、動的型の言語で変数名に型を含めないのは難しいです。特にメソッドの引数については名前だけが性質を読み取る情報源です。引数xが呼べるメソッドをどうやって予測すればよいでしょう?インスタンス変数やクラス変数も同様でしょう。

ただ、メソッド内で宣言する変数(ローカル変数)は型を含めないことが出来るのではないでしょうか。変数のスコープを十分に短くすればよいのです。逆にこういったルールはどうでしょう? ローカル変数は、宣言とスコープの終わりが必ず画面内に収まるようにする というルールです。

私のコーディング環境ではディスプレイは大体40行くらいのコードを表示しています。1行の文字数はまぁ120文字くらいでしょう。この中で変数のスコープを切る。具体的に言えば、そのためにメソッドを分けたりブロックを区切ったりするのは可能ではないでしょうか?そうして変数にはもっとシンプルで型を含まない名前をつけましょう。 tmp とか a b とか x y とか id とか obj new_obj old_obj とか。そうすれば、テーブル名やクラス名の変更の際に、変数の修正に手間取らずに済むのです。

とここまで書いたものの、実際やるとなんだかんだ読みにくくなりそうだし何だかなぁという気持ちです。ここまで読んで頂きありがとうございました。

追記 2017/06/23 15:07

書き終わってから思ったけど、上記の苦労は設計における変更可能性の考慮が抜けてたからな気がしてきた。変更可能性の考慮というのは、例えば、Ruby on Railsでアプリケーションを構築するのではあれば、ActiveRecordという名前は(多分)変わらないが、自分が定義したクラスは変わる可能性が高いという話です。基本的に、使用するgemのコードや抽象化されたコードのほうが変更されにくく、業務に直接関連するコードの方が変更されやすくなります。

これを踏まえれば、例えば、user は変数名としてやはり良くないですが、 recordrc はめったことでは変更されません。抽象的だが変更に強い変数名になります。そんな感じにしてかつ、スコープを短く保てればあんまり読みにくくならない気がします。変更可能性の高い型を変数名に入れるとよくないって話ですかね。。。