ruby

「DSLヒッチハイク・ガイド」で使用したコード

| View | Upload your ownRuby勉強会@札幌-8で、「RubyでDSLを作成する際の作戦の立て方と表現のポイント」について発表した際に、使用したコードです。お題は「アンケート作成を支援するDSL」。 DSLじゃない実現 まず始めに、OOPで普通に実現したサンプル。…

Query Method

オブジェクトのプロパティを調べるには、真偽値を返すメソッドを用意しましょう。メソッドには動詞または形容詞に'?'を付けた名前をつけましょう。 empty? nil? visible? Rubyコーディング規約のメソッド名に関する規約も参照しましょう。

Debug Printing Method

デバッグ用にオブジェクトの情報をプログラマに提供するためには、inspectメソッドをオーバーライドしましょう。 Rubyでは、オブジェクトを表示可能な文字列に変換するための仕組みとしてinspectメソッドを用意しています。デバッグ用にオブジェクトの情報を…

Method Comment

メソッドに関するコメントを書く場合は、メソッドの中ではなくメソッドの先頭にコメントを書きましょう。また、コードから明白に読み取れない重要な情報のみ伝えるようにしましょう。 メソッド定義の中で書かれるコメントというのは、コードの補助的な記述で…

Simple Delegation

呼び出し元に依存しない委譲を行いたい場合は、メッセージをそのまま委譲しましょう。 委譲先のオブジェクトが十分に独立していて、委譲元から付加的な情報を貰わなくても自身の仕事を行える場合は、Forwardableによりメッセージをそのまま委譲しましょう。 …

Delegation

継承なしに実装を共有させたい場合は、仕事の一部を直接他のオブジェクトに任せましょう。 あるオブジェクトの機能を別のオブジェクトを通して利用したいけれど、継承はコストがかかりすぎる気がする、もしくは継承することが意味的に言って適切ではない、と…

Collection Accessor Method

インスタンス変数がコレクションを保持する場合、コレクションに処理を委譲するアクセサを用意しましょう。 インスタンス変数に関するパターンです。 インスタンス変数がコレクションを保持する場合、Getting Methodを使ってコレクション自体をクライアント…

Setting Method

インスタンス変数と同じ名前の変数の値を設定するメソッドを作りましょう。 インスタンス変数に関するパターンです。 Indirect Variable Accessで使用するアクセサのうち、設定を行うものをSetting Methodといいます。 class Point attr_accessor :x, :y def…

Getting Method

インスタンス変数と同じ名前の変数の値を返すメソッドを作りましょう。 インスタンス変数に関するパターンです。 Indirect Variable Accessで使用するアクセサのうち、参照を行うものをGetting Methodといいます。 class Point attr_accessor :x, :y def ini…

Indirect Variable Access

インスタンス変数の値を取り出したり設定したりするためのアクセサを用意しましょう。 インスタンス変数に関するパターンです。 Rubyだとattr_accessorを使うことで、簡単に間接アクセスを実現出来ます。 class Point attr_accessor :x, :y def initialize(x…

Method Object

たくさんの引数や一時変数であふれてしまったメソッドを整理したい場合は、メソッド呼び出しを表現するオブジェクトを作成しましょう。 メソッドの整理に関するパターンです。 当初はシンプルだったメソッドでも、コードに手を入れていくうちに、行数や引数…

Execute Around Method

必ず対で実行しなければならない処理がある場合は、ブロックを受け取るメソッドを定義しましょう。 振る舞いの実現に関するパターンです。 ファイルをオープンしたら最後に必ずクローズしなければいけないといった、必ず対で実行しなければならない処理を実…

Role Suggesting Instance Variable Name

インスタンス変数には役割を表す名前をつけましょう。変数がコレクションを持つ場合は、複数形の名前にしましょう。 インスタンス変数の命名に関するパターンです。 変数は変数名と型によって構成されます。そのうち、型については、その変数が何を出来るか…

Intention Revealing Message

実装の意図を表現する手段としてメソッドを活用しましょう。 メソッドの定義に関するパターンです。 メソッドを定義することの最大の意義は、実装の読み手に対してそのコードの意図を伝えることにあります。たとえ、たった一行の実装であっても、意図を伝え…

Explicit Initialization

変数の初期値が何であるかを把握しやすくするため、すべての変数の初期化を一箇所で行いましょう。 インスタンス変数の初期化に関するパターンです。 インスタンス変数を持つクラスを実装する際には、initializeメソッドを実装して、そこで全てのインスタン…

vrubyを使ってコモンダイアログと遊ぶ

VisualuRuby(仮称)使い方のコモンダイアログのところが未作成なようなので、備忘録がてらメモ。 Windows向けのUIを手軽に作れるのがナイスなvrubyを使ってコモンダイアログを表示するサンプル。 require 'vr/vruby' #ファイル選択ダイアログを表示 file = SW…

Common State

オブジェクトの状態に関するパターンです。 あるクラスのすべてのインスタンスがそれぞれ異なる値を持つ場合は、インスタンス変数を定義しましょう。 class Point def initialize(x, y) @x = x @y = y end end a = Point.new(60, 120) b = Point.new(100, 30)

Constructor Method

インスタンスを生成するために何が必要かを明らかにするため、必要なパラメータをとり適切なインスタンス生成を行うメソッドを用意しましょう。 オブジェクトの生成に関するパターンです。 オブジェクトの生成を表現するもっとも単純でもっとも柔軟な方法は…

Conversion

あるオブジェクトの情報の形式に対して別の形式での表現が求められる場合は、その表現が可能な別のオブジェクトに変換しましょう。 具体的には、Converter MethodやConverter Constructor Methodの適応を考えます。

Converter Constructor Method

オブジェクトの変換に関するパターンです。*1 あるオブジェクトの持つ情報を元にして別のオブジェクトを新しく生成したい場合は、変換先のオブジェクトに変換元のオブジェクトを引数として持つコンストラクタを作りましょう。 class Pathname def initialize…

Converter Method

オブジェクトの変換に関するパターンです。*1 あるオブジェクトの持つ情報を別のオブジェクトの形式で表現しなおしたい場合は、変換元のオブジェクトに新しいオブジェクトに変換するためのメソッドを作りましょう。 p 10.to_f # => 10.0 p 10.to_s # => "10"…

Composed Method

メソッドは、一つのことのみを行う単位に分割しましょう。また分割する際は抽象度のレベルを統一しましょう。 メソッドの粒度に関するパターンです。 メソッドを適切な単位で分割することは、コードの可読性を維持する上で非常に大切なことです。適切な単位…

Intention Revealing Selector

メソッドには、そのメソッドが何を実現しているかにちなんだ名前をしましょう。 メソッドの命名に関するパターンです。 メソッドの命名でついやってしまいがちなのが、そのメソッドが仕事をどのようにして実現しているかまでをメソッド名に含めてしまうとい…

Smalltalkベストプラクティス・パターン

ソフトウェアでパターンというと、多くの方はオブジェクト指向における再利用のためのデザインパターンで紹介され広く世に広まったデザインパターンをイメージされると思います。しかし、同じくソフトウェアのパターンについて紹介しているソフトウェアアー…

任意の期間について日ごとに処理する

開始日から終了日のような任意の期間について日ごとに処理しなければいけない場合は、イテレータで。 require 'date' from = Date.new(2007,7,15) to = Date.new(2007,8,30) (from..to).each do |date| # ここに日ごとの処理を記述 end

CppUnitテスト自動化スクリプトをERBで

eXtreme Programmingテスト技法―xUnitではじめる実践XPプログラミング (OOP foundations)で紹介されている、CppUnit-xのテストケースが書かれたヘッダファイルからTestRunnerを自動生成してくれるスクリプトを、ERBを使って実現してみました。 require 'erb'…

ブレゼンハムの線分アルゴリズムを用いた追跡

ゲーム開発者のためのAI入門に載ってたタイルベースのLOS追跡アルゴリズムをRubyで。 まずは下準備としてタイルを表現するクラスを準備。 class Tile def initialize(x, y) @cel = [] (0..y).each do |i| @cel[i] = Array.new(x, 0) end end def set_value(x…

コームソート

プログラミングの宝箱 アルゴリズムとデータ構造 (C magazine)のコームソートをRubyで。 class Array def comb_sort gap = self.size begin if 0 == (gap = gap * 10 / 13) gap = 1 end i = 0 has_sorted = false until (i + gap >= self.size) do if self.a…

Rakefileに定義されているタスクを表示する方法

$ rake -T 自作のRakefileで上記にてタスクの説明を表示させるためには desc "ここにタスクの説明を記述" をタスク定義の直前に記述。 こんな感じ。 #rake desc "Build target." task :default => [TARGET] file TARGET => OBJ do sh "#{CXX} #{OBJDIR}/#{OB…

最大公約数、最小公倍数

rationalをrequireすることで、以下のメソッドがIntegerで使えるようになる。 require "rational" p 6.gcd(4) #=> 2 p 6.lcm(4) #=> 12 p 6.gcdlcm(4) #=> [2, 12]