一角獣は夜に啼く

ただの日記です。

思ってることとか考えたこととか適当に書きます。 主にソフトウェア開発の話題を扱う 「ひだまりソケットは壊れない」 というブログもやってます。

動的型付け言語とメソッド名

動的型付け言語を使うときは結構長めで説名的なメソッド名を付けるようにしてる。 型がわかるような名前をメソッド名に含めるとか。

例えば何らかの画像の URI を文字列で返すようなメソッドを定義するとして、人によっては、あるいは場合によっては uri って名前を付けることもあると思うけど、そこそこ規模が大きい場合は、例えば image_uri_str というような名前を使うようにしてる。 この例の image_uri_str だと別にそんなに長くないけど、実際のところもっと長ったらしくて説名的なメソッド名を使うことがよくある。 失敗時に例外を送出するようなメソッドの末尾に _or_throw ってつけるとか。 意図としては次のようなものがある。

  • 返り値型の情報とか引数の型の情報などをメソッド名に入れることで、呼び出し側でメソッド名を見たときに型情報などを想起しやすくしたい
  • _or_throw などを付けることで、注意すべき事項がある場合に呼び出し側でメソッド名を見たときに気付きやすくしたい
  • プロジェクト全体でできるだけメソッド名をユニークにしたい

型についてはまあ動的型付け言語なんだから当然という感じではあるけど、メソッドの返り値の型が呼び出し側のコードをいじってるだけではわからないので、メソッド名から想起しやすくしておきたいと思ってる。 「想起しやすく」 っていうのは、メソッド名を見ただけでわかるようにしておきたいという意味ではなくて、メソッド定義を一度調べて返り値などを知った後、しばらくたってからでも呼び出し側のコードを見て思いだしやすくしておきたい、という感じ。 静的型付け言語だと、たいていは呼び出し側のコードをいじってるときにすぐにメソッド定義を見れるけど、動的型付け言語をいじってる時はそういうわけにはいかないことが多い。

引数の型をメソッド名に入れるっていうのは、静的型付けだと同名のメソッドで異なる型の引数を受け取らせたい場合はメソッドのオーバーロードをすればよいけど、動的型付け言語だと基本的には同名のメソッド名を同じクラスの中に定義できないので、引数の型に応じて別名のメソッドを作ればいいよね、という感じ。 引数の型を動的に検査して処理内容を分けるようなメソッドを作るという方法もあるけど、それはあんまり良い方法だとは思ってない。

あと _or_throw みたいな注意喚起系も同様で、メソッド定義を調べた後に 「例外が発生するかどうか」 みたいなことを後から思いだしやすくするのに付けといたら便利だと思ってる。

それからメソッド名をできるだけユニークにしたいという話。 静的型付け言語だと、メソッド呼び出しの箇所を見れば呼び出してるメソッドがどの型に属するものなのかはわかる (どの実装が呼ばれるかはわからないが、型さえわかれば基本的には問題ない) けれど、動的型付け言語の場合はその動的型付けの性質ゆえにメソッド呼び出しの箇所だけを見ても呼びだそうとしてるメソッドがどの型 (?) に属するものなかのはわからない。 逆にいえば、静的型付けの言語だとある型に属するとある名前のメソッドを呼び出してる箇所を調べることはそんなに大変ではないけど、動的型付けの場合はあるメソッドがどこで使われてるのか調べることが困難な場合が多い。 そんなわけなので、grep とかで調べやすいように、メソッド名はできるだけユニークにしておきたい。 (同じ型に属するつもりの別実装のメソッドはもちろん同名にする。)

ちゃんとコード中のドキュメントが整備されてたらいいけど、整備されてなかったらそれこそメソッド呼び出しを何個も辿っていってどっちの型のメソッドとして呼び出してるのかとか調べないといけないことがあるわけで、そんな糞みたいなことしたくないよね。 まあドキュメントとか全体の設計をちゃんとしろって話でもあるけど。

動的型付け言語はコード補完が効きにくいこともあって短い名前を使いがちな様子もあるけれど、むしろ静的型付け言語より動的型付け言語の方がメソッド名を長めにかつ説明的にすべきだよなー、と思ってる。 *1

*1:長いことがいいことだ、ってわけではない。