「『変数のスコープは狭いほど良い』という迷信」という迷信

「変数のスコープは狭いほど良い」という迷信
変数でもメソッド名でもクラス名でも言えることだが、単純に「スコープは狭いほどよい」という方針でプログラムすると、逆に保守性も可読性も悪いプログラムができあがることがけっこうある。
中途半端に優秀なプログラマが「正しいプログラミングテクニック」だと妄信しがちな3つポイント - 分裂勘違い君劇場 by ふろむだ

変数とオブジェクトが持つ属性やメソッドを混同してません?

いわゆる「変数」のスコープが問題になるのは、一言では「依存性が複雑になるため」。

そのオブジェクトだったりメモリ領域だったりの内容は、その変数を使う時点でどのような状態を持つかっていうのは、その処理の前に実行されたどれかの処理結果に依存する。が、実際にその変数の内容を定義したり更新したりしたのはどの処理かは、もう闇の中。だから、グローバル領域の変数に対して、使う直前にわざわざ初期化してみたりするよね。ほらコードが増えた、バグが増える。

静的型付けの場合、型定義の変更だって簡単には出来なくなる。ある箇所で他の型に変更したい場合、もしもその後の処理でその変数の内容をそのまま利用してたら、どうする?その変数がグローバル領域にある必要がある変数か、それとも必要がない変数かわからない。ほらテストが増えた、バグが増える。

これだけの話、大して難しい話じゃないでしょ?

オブジェクトが持つ属性やメソッドのスコープについては、積極的に限定する文化と消極的に限定する文化があって、どちらが良いかは一概には言えない。前者はJava、後者はPython。それでも、極力限定すべきという原則は変わらない*1。ただ、それはオブジェクトの定義の話であって、オブジェクト自身のスコープではない。オブジェクト(インスタンスと呼んでもいい)自身のスコープは、外部から定義されるもので、レイヤが違う。

なーんて思ったら、既にid:JavaBlackに指摘されてるね。

クラス名やメソッド名だと思っているものは、単なる変数にクラスメタオブジェクトやメソッドメタオブジェクトが格納されたもの、と見なすことができるわけだ。
中途半端に優秀なプログラマが「正しいプログラミングテクニック」だと妄信しがちな3つポイント - 分裂勘違い君劇場 by ふろむだ*2

「クラスメタオブジェクト」「メソッドメタオブジェクト」っていう用語は初見で意味がよくわからないけど(多分、第一級オブジェクトとしてのクラスとメソッドを言いたいんだろう)、「見なすことができる」じゃなく「格納されていることがある」だよね。しかも「クラスメタオブジェクト」とそのクラスのインスタンスはまったく違うオブジェクトだし、混同するのは無意味に見える。

ちなみに、JavaのSystem.out.println()が長いのは、シンタックスシュガーが効いてないだけですね。Java5からimport static宣言なんて構文ができたから、好きなら使えば問題ない。標準出力オブジェクトのスコープっていう観点では、RubyJavaも大した違いはないでしょう?

*1:消極的に限定する文化でも、公開するつもりか公開しないつもりかの作者の意図を明示してほしいし、現にそういう習慣になってる。はず。

*2:追記消しちゃったのか。