配列やハッシュテーブルを構造体の代わりに使う奴はヤキ
Perl, Ruby など多くのスクリプト言語では、1つの配列に異なる型のオブジェクトを格納することができます。
Generics 導入前 (1.4 以前) の Java でも、同じようなことができました。
しかし、このテクニックは基本的に使ってはいけません。
次のプログラムを見てください:
books =[ |
この例では、配列 books の中の要素 (これまた配列) が各「書籍」のデータを表します。
0 番目の要素が「表題」、1番目の要素が「著者名」、2番目の要素が「価格」がそれぞれ格納されるという寸法。
なので、すべての書籍の著者名を出力するコードは次のようになります。
books.each { |b| puts b[1] } |
......最低ですね。
何が悪いのかと言うと (聡明なる読者諸兄は当然お気付きのことと思いますが)、インデクス値と要素に意味のある対応がないことです。
(出力コードだけを見て、b[1]
が「著者名」だと分かりますか?)
さらに、このデータがメソッドの戻り値や引数にされたり、変数に代入されたりして、定義された場所から離れた場所で参照されるような場合、型による意味付けがなされなくなります。
この場合、このデータのレコードに対して型を調べてみても、ただ 'Array
' と帰ってくるだけで、それ以外の配列オブジェクトと区別できなくなってしまいます。
では、配列ではなくハッシュテーブルを使うとどうかと言えば、若干マシにはなるものの、本質的な「悪さ」は何も変わりません。
books =[ { :title => '神は妄想である', :author =>'リチャード・ドーキンス', :price => 2500 }, { :title => '穴 -HOLES-', :author =>'ルイス・サッカー', :price => 620 }, ] |
確かに、キーが数字ではなく属性の名前を表すシンボル (文字列) になった分だけ、プログラムの可読性は向上しました。
books.each { |b| puts b[:title] } |
しかし、型というセマンティクスが利用できない状況に変わりはありません。
このデータレコードの型を調べても、'Hash' と帰ってくるだけで、それが「書籍」の情報を表すことを知る術はないのです。
ではどうすればよいのかというと、話はあまりにも単純。 「書籍」を表すクラスを定義すればよいだけです。
class Book attr :title attr :author attr :price def initialize(title, author, price) @title =title @author =authtor @price =price end end books =[ Book::new('神は妄想である', 'リチャード・ドーキンス', 2500), Book::new('穴 -HOLES-', 'ルイス・サッカー', 620), ] |
これなら、どこで参照されても、クラスの情報 (Book
) から、書籍のデータであることが明確です。
とても当たり前で簡単な方法なのですが、スクリプト言語使いは「(良くも悪くも) ものぐさ」なので、クラスを定義するわずかなタイプ数を惜しんで、先に上げたような保守性の悪いコードを書いてしまう傾向が見られます。
絶対に再利用されることのない、使い捨てのコードならともかく、長期に渡る保守・運用が想定されるようなプログラムで、配列やハッシュテーブルをクラス (あるいは構造体) の代わりに使うのは愚かとしか言いようがありません。
そのようなプログラムで「死ぬ」のが書いた本人ならまだ良いのですが、大抵の場合、被害を被るのはそのプログラムの保守運用を引き継がされる別のプログラマだったりするんですよね……。
と言うわけで、そんな迷惑なコードを書き散らす奴を見たときは、こってりとヤキをいれてやることにしています。