The Basis of Making DSL with Ruby

Preview:

DESCRIPTION

Slides of my talk in RubyKaigi 2010 on DSLs.

Citation preview

RubyKaigi2010

株式会社万葉

The Basis of Making DSL with Ruby

Rubyで作るDSLの基礎2010.8.27

(株)万葉 大場寧子 (@nay3)Yasuko Ohba

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

自己紹介Who I am

•Yasuko Ohba•Ruby Programmer•Developing rails applications

and iPhone applications•Everyleaf Corporation (万葉)

2010年8月28日土曜日

株式会社万葉

関西Ruby会議02

Web家計簿「小槌」• http://www.kozuchi.net• http://github.com/everyleaf/kozuchi

KozuchiHousekeeping Book on Web

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

IDs

•@nay3 (twitter)•http://github.com/nay•y.ohba@everyleaf.com

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

JRuby on Rails実践開発ガイド

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Ruby on Rails逆引きクイックリファレンス

2010年8月28日土曜日

提供

株式会社万葉Everyleaf Corp.

2010年8月28日土曜日

coming soon.

Everyleaf Corp.

2010年8月28日土曜日

My many failed productsjugyo

@中ホール200

photo by koichiroo

2010年8月28日土曜日

World Wide Ruby ConferenceKuniaki Igarashi

@202-B

photo by koichiroo

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

RubyはDSLに向いている

と言われる

Ruby is good forDSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ドメイン特化言語

Domain Specific Language

What’s DSL?

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

General Computer Language汎用的なコンピューター言語

DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

General Computer Language汎用的なコンピューター言語

DSLHospitals

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

General Computer Language汎用的なコンピューター言語

DSLHospitals

Libraries

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

General Computer Language汎用的なコンピューター言語

DSLHospitals

GameLibraries

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

General Computer Language汎用的なコンピューター言語

DSLHospitals

Game

EC

Libraries

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

プログラムではなく言語に見える

It looks like a language rather than a

program

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Ruby

DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Ruby

DSLinternal

言語内DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Ruby

DSLinternal

言語内DSL

external

言語外DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Rubyの言語内DSL

internal DSLin Ruby

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

DSLの例DSL examples

•Rails• routes.rb• migrations• RJS

•RSpec•Rake

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL的コード : Rails

DSL-like codes : Rails

class NotesController before_filter :find_group ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

before_filter :find_group

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

特にはDSLに見えませんか?

It doesn’t look like DSL ?

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

よりDSLらしくなく書ける

it can be less DSL like

self.add_before_filter_methods( :find_group)

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

比較すればDSLっぽい

much more DSL like

self.add_before_filter_methods( :find_group)

before_filter :find_group

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

難しい話ではない

My talk is simple

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

読みやすいコードの話

I’ll talk aboutreadable codes

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL的コード : マイグレーション

DSL-like codes : migrations

create_table :users do |t| t.string :name t.timestampsend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL的コード:RSpec

DSL-like codes : RSpec

describe Group do it “nameがないと検証エラー” do

g = Group.new g.should_not be_valid end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

読みやすい

Easy to read

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

書きやすい

Easy to write

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

記述量が少ない

Brief

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

メンテナンスしやすい

Easy to maintain

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ところで

OK, but...

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSLはすごい人が書いて、使わせてもらうもの?

Do we just use existing great DSLs ?

Photo by Lawrence OP2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

NO

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

日常的にDSLっぽく書こう

Write your ruby codes like DSL

everyday

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL は Rubyのコーディング技術

といえる

That’s just a skill of programming in Ruby

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

このセッションでは

I’m going to talk about

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

意識してDSLっぽく書くコツを話します

..how to make your codes like DSL

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

私たちの目標

Our goal

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

“DSLらしさ”

DSL-likeness

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSLっぽさとは何だろう?

What decideswhether it is DSL

or not ?

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

明確な境界線はない

No Solid Boundary

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

感覚的な区別

But we can feel it

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

そこで

to make the difference clear

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

普通のRubyとDSLの表現を比較

Compare normal Ruby codes and DSLs

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

普通のRubyNormal Ruby Style

“Hey receiver, do/return THIS !”

「レシーバよ、これをせよ/くれ」

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

レシーバよ、これをせよ

Hey receiver do THIS!

array.cleararray[1]array.collect!{...}hash.delete(key)string.empty?

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

オブジェクト指向プログラミング

では当然

Because it’s OOP

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSLでは少し違う

DSLs have another styles

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

3つの典型的な表現

3 typical forms

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

1.Declarative Programming宣言的記述

2.Using Blocksブロックの活用

3.Methods Represent Special Concepts 特定概念を表すメソッド

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

1. 宣言的記述

1. Declarative Programming

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

「私は Rubyist です」

“I am a rubyist”

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

宣言的記述の例

examples : declarative expression

validates_presence_of :namebefore_filter ...has_many :children

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

通常のスタイルとの違いtypical features

• describe status or nature状態や性質を記述する

• receivers are not always importantレシーバは必ずしも重要でない

• no brackets括弧を書かない

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

お金がない

No money

self.money = 0

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

お金がない

No money

self.money = 0

poor

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

クラス定義などで記述することが多い

Mostly in Class Definitions

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

No money

class Boy poor ...end

お金がない

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

実現したい処理がクラスの性質として表せるか考える

Try to express your request as a nature

of the class

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Object task

task task

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

the class has this natureこのクラスにはこういう性質がある

Object task

task task

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

モジュール向き

Modules are goodto express natures

Class Object

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

モジュール向き

Modules are goodto express natures

Class Object

Module

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

モジュール向き

Modules are goodto express natures

Class Object

Module Module

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

実装方法

implementation

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

コード例 1Example 1

Declare the class to have some nature implemented as a module性質を実現するモジュールのincludeを宣言的に書く

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Book(Class)

Product

class Book include "Product" ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

class Book include "Product" ...end

class Book acts_as_product ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

class Book acts_as_product ...end

NameError: undefined local variable or method `acts_as_product' for Book:Class

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

acts_as_product メソッドを用意する

You needacts_as_product

method

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

スーパークラスに

in the super class

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Book(Class)

Object(Class)

acts_as_product

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Book(Class)

Object(Class)

acts_as_product

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Book(Class)

Object(Class)

acts_as_product

Product

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

簡単なやり方the easier way

class Object def self.acts_as_product include Product endend

the caller (Book) will be self here呼んだクラス(Book) が self

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Book(Class)

Product

class Book acts_as_product ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Execute this before acts_as_product is invoked

Bookクラスのロード前に実行しておくRails なら config/initializer/acts_as_product.rb

class Object def self.acts_as_product include Product endend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

丁寧なやり方the softer way

module ActsAsProduct module ClassMethods def acts_as_product include Product end end def self.included(base) base.extend(ClassMethods) endendObject.instance_eval { include ActsAsProduct }

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ActsAsProduct

Object(Class)

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ActsAsProduct

Object(Class)

add acts_as_product

ClassMethods

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ActsAsProduct

Object(Class)

Book(Class)

add acts_as_product

ClassMethods

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ActsAsProduct

Object(Class)

Book(Class)

callacts_as_product

add acts_as_product

ClassMethods

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ActsAsProduct

Object(Class)

Book(Class)

callacts_as_product

Product

add acts_as_product

ClassMethods

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

コード例 2Example 2

set @title for a layout in some actions in Rails controllers

Railsのコントローラで、レイアウトで使う@title の値をアクションごとにセットする

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

Controllerindex show new edit

Request

layout

@title

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

こう書きたい

want to write like this

class BooksController < ApplicationController title "書籍の編集", :only => [:edit, :update]

....end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

同じ戦略

Same Strategy

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

スーパークラスにクラスメソッドを

add a class methodin the super class

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

BooksController

ApplicationController

title

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ApplicationController

class ApplicationController < ... def self.title ... endend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

title "書籍の編集",

:only => [:edit, :update]

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ApplicationControllerclass ApplicationController < ... attr_accessor :title

# フィルターを利用 def self.title(name, options={}) before_filter(options) {|controller| controller.title = name} end .....

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

validate ? validates ?

English naming problems

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

2. ブロックの活用

2. Using Blocks

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ブロックの例:rake

examples : rake

namespace :myapp do task :my_rake_task do # rake タスクの中身 endend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Example : Rails Form Helper

form_for :book do |f| f.text_field :name f.submitend

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

DSL的なブロックの用途Usages of block for DSL

•describe complex structure複雑なデータ構造を表現

•get some tasks into a scope処理にスコープをかける

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

構造を表現してみる

describe structure

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

コード例3Example 3

Write a game rule using playing cards

トランプゲームのルールを記述してみる

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

七ならべ

Sevens

game 'sevens' do |g| g.use 53 g.deal 53, :to => :each_player ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

game usedeal

Top Level

GameYou

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Game Classclass Game def use (card_size, options ={}) ... end def deal (card_size, options ={}) ... endend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

def game g = Game.new yield gend

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

GameYou

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

GameYou

Block

game

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

GameYou

Block

game new

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

GameYou

Block

game new

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Top Level

GameYou

Block

game new usedeal

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

パラメータ引数をなくしたい?

want the block parameter removed?

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

パラメータ g をなくす

without parameter g

game 'sevens' do use 53 deal 53, :to => :each_player ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

instance_execを使う

use instance_exec

def game(&block) g = Game.new g.instance_exec(&block)end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

宣言ぽくsをつけても

can be changed slightly

game 'sevens' do uses 53 deals 53, :to => :each_player ...end

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

3. 特定概念を表すメソッド

3. methods represent special concepts

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

名詞代わりのメソッド

methods that work as noun

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

別言語にそのまま対応するメソッド

methods that represent vocabularies

in another language

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

f.submit

books_urlpage.assert

session request

current_user

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

番外編

an extra DSL style

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

4. 英語っぽく見せるためのメソッド

4. Methods to make codes like English

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

it

should

years_sincebytes

from_now

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

Balance

REALLY Useful ?

実用性

Cosmos of OOP妥当性

?2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

一般的なコツ

General Tips

2010年8月28日土曜日

RubyKaigi2010

株式会社万葉

General Tips• provide default values for parameters引数にデフォルトをつける

• use a hash parameter引数にハッシュを使う

• use symbolsシンボルを使う

• naming methods nicelyメソッド名を工夫する

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

まとめ

Summary

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSLは身近な存在

DSL is not very special

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

DSL的な考えを取り入れることでコードがよくなる

Implementation will improve with DSL ideas

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ぜひ試してみて!

Have a try !

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

気になったコードを読むのがおすすめ

The best way to learn is reading codes

2010年8月28日土曜日

株式会社万葉

RubyKaigi2010

ありがとうございました

Thank you !

2010年8月28日土曜日

Recommended