最近のこと

by tanabe on March 28, 2009

年明けくらいに「今年はたくさん更新を」と書いたような気がしないでもないが、早々に挫折しずいぶんと間隔が開いた。

いろいろと忙しかったという言い訳があるのだけど、その間に読んだ本で思ったことがけっこうあるのであとで書くしておく。

これらについて、あとで書く。

  • アジャイルな見積りと計画づくり
  • コーディングの掟
  • Release It!
  • 「日本の経営」を創る(三枝匡)
  • 企業戦略としてのデザイン

今年は仕事以外でもいろいろできるといいなぁと思います。ikebukuro.rb とかして、ジュンク堂近くのスタバで一人コーディングとか。

  

お疲れ様でした。

by tanabe on March 28, 2009

チームに今月末で退職する方がいたので、送別会でした。

前の職場を自分が辞めるときにも強く感じたことですが、本当に自分はチームで働くということと、単純にそのチームの人たちがすごく好きなんだなぁと感じました。

「初めてのRuby」勉強会継続中なので、また会う(のだろう)けど、その一風変わったセンスでこれからも活躍してほしいです。

# といいつつ、このブログ職場ばれしてないから読まれないな。うん。

  

Ruby で 50 行ほどのルールエンジンを書いてみた。

by tanabe on March 10, 2009

drools の記法が DSL らしくて「へー、いいなー」と思ったりしたので、なんとなく書いてみた。バックトラックを考慮していない(最初の答えを見つけたら break する)うえに速度が速いわけでもないので記法の違う if 文と言われると返す言葉もない。

要は rule, when, then のブロックでルールを定義するというのをやってみたかったということで。

when と then はメソッド定義まではできるんだけど DSL 風なアクセスをうまいこと API として定義できなくて _when と _then で妥協した。残念。

class Rrools
  class Rule
    def initialize
      @rule = {}
    end

    def _when &condition
      @rule[:condition] = condition
    end
    alias on _when

    def _then &consequence
      @rule[:consequence] = consequence
    end
    alias run _then

    def pack context
      instance_eval &context
      @rule[:context] = self
      @rule
    end
  end

  def self.describe &block
    rools = self.new
    rools.instance_eval &block
    Proc.new {|&context| rools.valuate &context }
  end

  def initialize
    @rules = []
    @description_context = Proc.new {}
  end

  def rule &rule_block
    rule = Rule.new
    rule.instance_eval &rule_block
    @rules << rule.pack(@description_context)
  end

  def context &context # rule の生成時に都度評価される
    @description_context = context
  end

  def valuate &context
    @rules.each do |rule|
      rule[:context].instance_eval &context
      if rule[:condition].call
        break rule[:consequence].call
      end
    end
  end
end

使い方はこんなかんじ。

rule = {}
rule["入場料"] = Rrools.describe do
  rule do
    _when { @people > 4 }
    _then { 5000 * @people }
  end

  rule do 
    _when { @people <= 4 }
    _then { 6000 * @people }
  end
end

people = 3
puts rule["入場料"].call { @people = people }  # => 18000

people += 1
puts rule["入場料"].call { @people = people }  # => 24000

people += 1
puts rule["入場料"].call { @people = people }  # => 25000


# やってみる。
# http://amateras.sourceforge.jp/cgi-bin/fswiki/wiki.cgi/free?page=Drools

class User
  attr_accessor :age, :name
  def initialize name, age
    @age = age
    @name = name
  end
end

is_adult = Rrools.describe do
  rule do
     on { @user.age >= 20 }
    run { puts "#{@user.name} is an adult." }
  end

  rule do
     on { @user.age < 20 }
    run { puts "#{@user.name} isn't an adult." }
  end
end

is_adult.call { @user = User.new("Bob", 21) }
is_adult.call { @user = User.new("Amy", 17) }