クラス設計

 やっちゃいけないことが出来てしまうのは必ずしも悪いことではなくて、ガチガチに型を作ればやっちゃいけないことが出来てしまう可能性をギリギリまで排除することは出来るのだけど、その間違いを犯さなければいいだけの話でもある。その間違いをやってしまう可能性と、その間違いを防ぐためにかかるコストの比が問題になるように見えるが、それよりも「そのクラスが簡単に理解できる程度に単純であるか」の方が問題だ。間違いを防ぐためにケースに合わせて様々な特化したバージョンを作れば、間違わずに済むようには見えるが結局いろんなのが出てきて覚えることが増え、どう使っていいか分からないということにもなりかねない。.NET FrameworkにはIReadOnlyListもIReadOnlyDictionaryもないのだが、別に困らない。デリゲートは実際にはデリゲートのコレクションになっているが普段はコレクションとして使わなければ何の問題もない。「何でも出来る一つ」の方が「一つのことしか出来ないものがたくさん」より分かりやすいことは多い。スクリプト言語は文法が間違ってても実行できるし、配列は作らずハッシュテーブルに全部やらせたりするが、たいして困らないのだ。

 呼び出しちゃいけないメソッドを必死でprivateやinternalに隠し、そのために中間層を新たに作り出したとしたら、それは本末転倒というものだ。そのクラスが適用できないケースで使えなくすることにコストをかけるよりも、そのクラスが適用できるケースを増やすためにコストをかけた方がいい。ダウンキャストを防ぐために必死で<T>をそこら中につけても、そのクラスがしょっちゅう出てこない限りほぼ意味はなく、ダウンキャスト一発の方が分かりやすいことの方が多いと思う。