Rubyで作る宣言的DSL
Ruby応用でDSL作成の基礎
Rubyはその柔軟な構文とブロック機能により、Domain Specific Language(DSL)を簡単に作成できる言語です。DSLは特定のドメインに特化した表現力を提供し、コードの可読性と保守性を大幅に向上させます。まずは簡単な構文を定義し、メソッドチェーンで直感的に記述できるようにします。
class Config
def initialize(&block)
instance_eval(&block)
end
def set(key, value)
instance_variable_set("@#{key}", value)
end
def get(key)
instance_variable_get("@#{key}")
end
end
config = Config.new do
set :host, 'localhost'
set :port, 8080
end
puts config.get(:host) # => localhost
ドメイン特化言語の設計原則
DSLを設計する際の主な原則は「宣言的記述」と「実装の隠蔽」です。宣言的記述により、何をしたいかを記述し、Rubyが内部でどう実装するかを隠します。これにより、ドメインエキスパートがコードを理解しやすくなります。また、メソッド名やキーワードはドメイン語彙に合わせることで表現力を高めます。
- ドメイン語彙を採用
- 副作用を最小化
- エラーハンドリングを明示的に
宣言的記述とブロック活用
RubyのブロックはDSLの核です。ブロックを渡すことで、構造化された設定やルールを宣言的に記述できます。以下は、テストフレームワークのようにブロックでテストケースを定義する例です。
class TestSuite
def initialize(name, &block)
@name = name
@tests = []
instance_eval(&block)
end
def test(name, &block)
@tests << { name: name, block: block }
end
def run
puts "Running #{@name}"
@tests.each do |t|
puts " #{t[:name]}"
t[:block].call
end
end
end
suite = TestSuite.new('Math Tests') do
test 'addition' do
raise 'fail' unless 1 + 1 == 2
end
test 'multiplication' do
raise 'fail' unless 2 * 3 == 6
end
end
suite.run
設定ファイルと表現力の向上
DSLを設定ファイルとして利用することで、アプリケーションの構成をコード化せずに柔軟に変更できます。RubyのYAMLやJSONと組み合わせると、設定を読み込みつつ、DSLで表現したロジックを実行できます。以下はYAMLを読み込み、DSLで処理を定義する例です。
require 'yaml'
class Router
def initialize(routes)
@routes = routes
end
def route(path, &block)
@routes[path] = block
end
def dispatch(path)
if @routes.key?(path)
@routes[path].call
else
puts "404 Not Found"
end
end
end
routes = YAML.load_file('routes.yml')
router = Router.new(routes)
router.dispatch('/home')
このように、設定ファイルとDSLを組み合わせることで、表現力を最大化し、運用コストを低減できます。
コメント
コメントを投稿