「Rubyによるデザインパターン」の要点と使いどころの続きです。
『Rubyによるデザインパターン』の「第Ⅲ部 Rubyのためのパターン」についてまとめます。第Ⅲ部は、どの章もそれだけで本が1冊書けるような濃い内容なので、本書を足がかりに別の本も合わせて読んだほうが良さそうです。
DSL: ドメイン特化言語
概要
- DSL: ドメイン特化言語(Domain-Specific Language)とは、あるドメイン(領域)の言葉を用いてプログラミングができる言語。例えば、会計士が会計の事柄をそのまま表現できる言語など。
- 外部DSL: 会計士の言葉でプログラミングができる会計用DSLがある場合、そのDSLを解析・実行するためにパーサとインタープリタが必要になる。このように、DSLとインタープリタが別々の場合を外部DSLという。
- 内部DSL: DSLが何らかの言語(例えばRuby)と同じ書き方ができる場合。Rubyはこの内部DSLを簡単に作ることができる。
実装
内部DSLの実装は、DSLで書かれたファイルをevalメソッドで読み込み、Rubyのプログラムとして実行させている。DSLで使用できるキーワード(メソッド等)は、全て本来プログラム側に定義する。
実行ファイル
def output(message)
puts message
end
eval(File.read('DSLで書かれたファイル'))
DSLで書かれたファイル
output 'メッセージ'
実行結果
メッセージ
メタプログラミング
概要
- Rubyの柔軟性を活用して、動的なオブジェクトを生成する。
実装
実装例1.インスタンスにメソッドを定義する
def make_object(type)
object = Object.new
if type == :a
def object.type
'a'
end
end
object
end
obj = make_object(:a)
obj.type # => "a"
実装例2.インスタンスにメソッドをextendする
module M
def type
'a'
end
end
def make_object(type)
object = Object.new
if type == :a
object.extend(M)
end
object
end
obj = make_object(:a)
obj.type # => "a"
実装例3.インスタンスにメソッドをclass_eval()で追加する
class Obj
def self.set_type(member)
code = %Q{
def type
"#{member}"
end
}
class_eval(code)
end
end
Obj.set_type('a')
obj = Obj.new
obj.type # => "a"
Convention over Configuration
概要
- "設定よりも規約"というRuby on Railsの思想。
- 従来の"設定"によるフレームワークでは、規模が大きくなるほど設定が大きくなり、拡張性や保守性に問題があった。CoCの思想では、フレームワークがある規約に則ることで、余分な設定を排除し、拡張性や保守性を高めている。