« AmritaHandler(仮) 20050607版 | メイン | Rubyにannotationを定義するとしたら? »
2005年06月08日 (水)
annotation (a.k.a. metadata) 再考 [テクニカル]
Rubyの attr_*
はannotationにほかならない。内部ではメソッド定義でしかないにもかかわらず、「属性」という意味づけが与えられているのだから(RDocなど)。つまり、メソッドに attribute というannotationをつけていることに等しい。
で、Rubyで統一的な annotation を与える書式はどうするのがいいだろうか。やはりRubyでは可読性の高いModuleクラスのメソッドとして定義するべきなのか。
実は暗黙のうちにmetadataを使っているライブラリは多い。
e.g. StrongTyping module:
attr_accessor_typed String, :foo, :bar
うーん、ダサい。
metadataの意味では、foo, barというメソッドに attribute=>readwrite, type=>String というmetadataを与えていると解釈できる。ならちゃんと並列に同じ記法で書けなきゃ。
Java流なら:
meta_attribute :RW
meta_type String
meta_hoge :key1=>'value1', :key2=>'value2'
def foo
...
end
って感じか。ちょっとダサいかな。。あと意味もわかりにくい。meta_*
っていうメソッド名もかぶりそうだし。
もう1つの例。
e.g. ActiveRecord
class Entry < ActiveRecord::Base
def self.table_name; entry; end
belongs_to :blog
belongs_to :author, :foreign_key => 'entry_author_id'
has_one :trackback, :foreign_key => 'trackback_entry_id'
has_many :comments, :foreign_key => 'comment_entry_id'
has_and_belongs_to_many :tbpings, :finder_sql => 'SELECT t.* FROM mt_trackback j, mt_tbping t WHERE t.tbping_tb_id = j.trackback_id AND j.trackback_entry_id= #{entry_id} ORDER BY t.tbping_id'
end
metadata的解釈では、クラスEntryにいろいろmetadataをつけてることになる。Java的アプローチだとこれらはメソッドにつくことになる。さらにオプション項目があればネストしたアノテーションとなる。
メソッドにつけたほうがきめ細かく処理できるはずだが、Rubyではメソッドも自動生成することが多いため、うまい方法がない。必ずdefを書くようにすればできそうだが。(それでもメソッド定義のフックはModule#method_addedで可能だが、クラス定義のフックはどうする?)
Javaで書くとするとこんな感じ?書いたことないから適当だけど。
@Entity
@Table("entry")
public interface Entry {
@ManyToOne
public Blog getBlog();
@ManyToOne
@JoinColumn(name="entry_author_id")
public Author getAuthor();
@OneToOne("trackback")
@JoinColumn(name="trackback_entry_id")
public Trackback getTrackback();
@OneToMany("comment")
@JoinColumn(name="comment_entry_id")
public Set<Comment> getComments();
@ManyToMany("tbping")
@AssociationTable( ... )
public Set<TBPing> getTBPings();
}
トラックバック
このエントリーのトラックバックURL:
http://www.4bit.net/x/mt/mt-tb.cgi/61