櫓日誌

スポンサーサイト

一定期間更新がないため広告を表示しています

| スポンサードリンク | - | | - | - |
ふつける

9章まで読み終わった。主に電車で読んでるのでなかなか読み進まないな。単に読むだけじゃなくて、演習問題で手を動かしてみないとなかなか身につかないし。

ここまで読んだ感じだと、同じ関数型言語でも Lispより数式に近い記述形式なので、理解しやすいような。インデントや$で、コードもスッキリするので読みやすい。

| YAGURA | ソフトウェア | 01:26 | comments(0) | trackbacks(1) |
オブラブ2006夏イベント

6/29のオブラブイベントに参加してきた。 当日は風邪で体調が最悪で何度も途中から帰ろうかと思ったけど、どのセッションも楽しいものだった。帰らなくてよかった。スタッフの皆さんのおもてなしや盛り上げも素晴らしかった。

*ワールドカフェ
いろいろな人と議論できるのが楽しい。ただ、ソフトウェア開発の楽しさなど、一つのテーマについてもう少し語れても良かったのと、重複しているテーマがいくつかあったので、開始前に全体でテーマを選考する時間があるとさらによかった。

*パネルディスカッション
はぶさん面白。達人プログラマ好きなので、DRY重要と言われたのがうれしい。 オブ脳カーのエアコンフィルターは、私の買ったオブ脳本で出来ていたことが発覚。

| YAGURA | ソフトウェア | 03:03 | comments(0) | trackbacks(0) |
Binding.of_caller

Binding.of_caller を調べてみました。クリティカルセーフなのはもちろん、継続を使って効率良く caller bindingを取得してます。(るびまの記事で解説があったのにきちんと理解できてなかったよ。。)たとえば、関数Aから呼び出された関数Bの中で Binding.of_caller を使うと以下のような流れになります。

AからBを呼び出す->B内でBinding.of_caller(&block)を実行->継続ポイントをセット->set_trace_funcをセット->関数Bからreturnして関数Aに戻る->set_trace_func により継続ポイントから再開->関数Aのbindingを取得->Aのbindingをパラメータにして blockを実行。

ただし、Binding.of_caller は関数Bの最後の式にしないと set_trace_funcが期待通りに動かない(このために Binding.of_callerはクロージャになっている)。ややこしいけど、うまいなぁ。自分で実装してたら思いつかないな。

| YAGURA | ソフトウェア | 19:07 | comments(0) | trackbacks(1) |
続:Rubyで内包表現

配列リテラル([1,2,3]のような配列のことをこう呼ぶらしい)のinitialize上書きは無理っぽいので諦めて、コードを整理してみました(ついでにバグ取りも)。 用語はこちらを参考にさせて頂きました。

書式:
I['value_expression' | 'var <- source',  'predicate_1', 'predicate_2', ・・・, 'predicate_n']

この式は以下のような式に展開されます。

source.select do |var|
  predicate_1(var) &&  predicate_2(var) && ・・・ && predicate_n(var)
end.map do |var|
  value_expression(var)
end
例1:
xs = [10,30,3,-5,1,10,100,-60]
p I['(x*2).abs' | 'x<-xs', 'x < 50']
=> [20, 60, 6, 10, 2, 20, 120]
例2:
def quicksort(x = nil, *xs)
  return []  if x == nil
  quicksort(*I['y' | 'y <- xs', 'y < x']) + [x] + quicksort(*I['y' | 'y <- xs', 'y >= x'])
end
p quicksort(*xs)
=> [-60, -5, 1, 3, 10, 10, 30, 100]
コードはこちら:
require 'active_support/binding_of_caller'

class Intention
  def initialize(value_expression, var, source)
    @value_expression = value_expression
    @var = var
    @source = source
  end
  
  def to_a(predicates, binding)
    predicates << 'true'  if predicates == []
    eval(<<-EOF, binding)
      #@source.select {|#@var|  #{predicates.join('&&')} }.map do |#@var|
        #@value_expression
      end
    EOF
  end
end

class String
  def |(other)
    raise  unless other =~ /^(.+)<-(.+)$/
    Intention.new(self, $1, $2)
  end
end

class I
  def self.[](intention, *predicates)
    raise  unless  intention.instance_of?(Intention)
    Binding.of_caller do |binding|
      intention.to_a(predicates, binding)
    end
  end
end
| YAGURA | ソフトウェア | 18:15 | comments(0) | trackbacks(0) |
Rubyで内包表現

Haskellの内包表現を知ってRubyでも使いたくなった。試しに実装。

require 'active_support/binding_of_caller'

class Naiho
  attr_reader :element, :bind, :range
  def initialize(element, bind, range)
    @element = element
    @bind = bind
    @range = range
  end
  
  def to_list(restrictions, binding)
    eval(<<-NAIHO, binding)
      #@range.select {|#@bind|  #{restrictions.join('&&')} }.map do |#@bind|
        #@element
      end
    NAIHO
  end
end

class String
  def |(other)
    raise  unless other =~ /^(.+)<-(.+)$/
    Naiho.new(self, $1, $2)
  end
end

$n = Object.new
def $n.[](naiho, *restrictions)
  raise  unless  naiho.instance_of?(Naiho)
  Binding.of_caller do |binding|
    naiho.to_list(restrictions, binding)
  end
end


=begin
class Array
  def initialize(args)
    if args.first.instance_of?(Naiho)
      naiho, *restrictions = args
      Binding.of_caller do |binding|
        naiho.to_list(restrictions, binding)
      end
    else
      super
    end
  end
end
=end
例1:
xs = [10,20,3,-5,1,10,100]
$n['x*2' | 'x <- xs', 'x <= 10']
=> [20, 6, -10, 2, 20]
例2:
def quicksort(x = nil, *xs)
  return []  if x == nil
  quicksort(*$n['y' | 'y <- xs', 'y < x']) + [x] + quicksort(*$n['y' | 'y <- xs', 'y >= x'])
end
quicksort(*xs)
=> [-5, 1, 3, 10, 10, 20, 100]

ほんとは、Arrayのinitializeを上書きできれば以下の式で済むんだけど、配列式の場合は Arrayのinitializeが呼ばれないみたいだ。set_trace_funcにすら反応しなかった。

['x*2' | 'x <- xs', 'x <= 10']

この実装のために、caller bindingが取得できなくて困っていたところに、るびまのRailsの記事でRailsはset_trace_funcで実現していることを知った。というわけで、躊躇なくbinding_of_callerを利用。スレッドセーフではなくなりそうだけど、その辺は継続を使うことでどうにかしてるのかな。そのうち見てみよう。

それにしてもメタプログラミングは楽しいや。

| YAGURA | ソフトウェア | 22:24 | comments(0) | trackbacks(1) |
ポリモーフィズム
周りでポリモーフィズムってなに?という話になったんですが、何がポリモーフィズムなのか人によってだいぶ認識が異なるようです。そこで、どんなポリモーフィズムがあるのか調べてみました。

大雑把に言って、ポリモーフィズムという言葉は三つの使われ方があるようです。
(1)同じメッセージに対して異なるオブジェクトが異なる振る舞いをすること
http://www.ogis-ri.co.jp/otc/hiroba/technical/OO_Guide/O2.html
オブジェクト指向の世界では、オブジェクト同士がメッセージをやり取りします。メッセージを受け取ったオブジェクトは、それに対して様々な仕事をします。どのような仕事をするかはオブジェクト次第です。たとえば、飛行機オブジェクトに move() というメッセージを送れば飛ぶでしょうが、同じメッセージをイルカオブジェクトに送った場合は泳ぐでしょう。
このような仕組みは、JavaやC++では継承とメソッドのオーバーライドによって実現できます。

(2)変数が一つ以上のクラスのオブジェクトを参照できること。
バートランド・メイヤーの『オブジェクト指向入門』では、ポリモーフィズムと動的束縛を次のように定義しています。
「プログラムエンティティは一つ以上のクラスのオブジェクトを参照できなければならない。そして、操作は異なるクラスについては異なる方法で実現できなければならない」プログラムエンティティとは、変数のことで、あるオブジェクトを指し示します。つまり、ここでは、変数が特定のクラスのオブジェクトだけではなく複数のオブジェクトを参照できることがポリモーフィズムだ、というわけです。C++やJavaでは、Class Aのオブジェクトを指す変数は Class Aのサブクラスのオブジェクトも指すことができます。後半の動的束縛についての記述は、ほぼ(1)と同じ意味です。

(3) Cardelli と Wegnerのポリモーフィズム(図2:CardelliとWegnerによる多態の分類参照)
これは(1)を含んだより広い概念です。継承によるポリモーフィズムの他にジェネリックやオーバーローディング、キャスティングによるポリモーフィズムがあります。これらはいずれも、型ごとの振る舞いやアルゴリズムの違いを隠蔽します。つまり、オブジェクトを使った何らかの操作(たとえばメッセージ送信や関数の引数にオブジェクトを渡すなど)を行った結果は、オブジェクト次第で異なります。

まとめると、以下のようになります。
(1)は、オブジェクトに送ったメッセージがオブジェクト次第で「様々な振る舞い」を起こすことをポリモーフィズムと呼ぶ。
(2)は変数が「様々な型」のオブジェクトを参照することをポリモーフィズムと呼ぶ
(3)はオブジェクトを使った操作がオブジェクト次第で「様々な結果」を起こすことをポリモーフィズムと呼ぶ。

#(1)や(2)は大体理解しているつもりですが、(3)は今回はじめて知ったので間違いも多そう。。

ポリモーフィズムという言葉は、結構、特殊な用語で限定された使われ方しかされていないと思っていたけど、こうして改めて考えてみるとずいぶん違う意味があるのに驚いた。さらにわからないのは、アーキテクチャやSOA、Web 2.0なわけなんですが。。
| YAGURA | ソフトウェア | 00:29 | comments(0) | trackbacks(0) |
ドメインの本質
私は仕事でオブジェクト指向を使っていますが、オブジェクト指向の理論を学んでも、上手く実践に活かせず、つまずいてしまうことがよくあります。ここでは、どのようなことにつまずいたか、なぜつまずいたのかを書いていこうと思います。(もちろん、今でもオブジェクト指向に限らずソフトウェア開発全般でいろいろな四苦八苦しているんですが)

初めてオブジェクト指向開発について教わったとき、私がもっともつまずいたのは「ドメインの本質」という考え方でした。ドメインとはソフトウェアプログラムが解決すべき問題を専門分野ごとに分割したもので、たとえばインターネットのショッピングサイトであれば発注、在庫管理、顧客管理、配送などのドメインが考えられます。私の周りにはオブジェクト指向開発の熟練者がいて、彼らはドメインの本質について考えることがソフトウェアの再利用性の重要なキーであると指摘していました。これは、ドメインの本質、つまり普遍的な性質を捉えて、それをソフトウェア設計のベースすることで、再利用性の高いソフトウェアを構築できるという考え方です。

私にとってこの考え方はなんとなくわかるんだけどいまいちしっくりこないものでした。この「しっくりこなさ」には二つの理由があったと考えています。理由の一つは、ただ一つのドメインしか見ていなかったことです。
ある程度、複雑なソフトウェアは、複数のドメインに分割できます。私がオブジェクト指向を学んだときは、演習の都合もあってある単一のドメインについてのみ考えていました。インターネットショッピングの例で言えば、配送ドメインだけを見て、他のドメインについてはほとんど知らないような状況です。この状況においても何がドメインの本質であるか主張することはできます。たとえば、配送ドメインの本質とは、何かモノをある場所から他の場所へ移すことだと。しかし、そうでない振る舞いを我々の知らない他のドメインが期待していたとしたらどうでしょう。すこし強引な例かもしれませんが、発注ドメインは配送ドメインに、物理的なモノの配送だけでなく、電子データの配送も期待するかもしれません。この場合は、モノは移動するのではなく、モノ(電子データ)のコピーが送られます。
ソフトウェアをドメインに分割するということは、ドメインを組み合わせてソフトウェアを作るということです。ですから、あるドメインが一体何であるかは、他のドメインとの関係によって決まります。この関係性を無視したのでは、ドメインの本質どころか、まともに動作するかどうかすらわかりません。当たり前のことですが、いくら自分の担当だからといってそこだけを見ていては上手く行くはずもなく、全体を見ないといけなかったんですね。

もう一つの理由は、本質だけにフォーカスしすぎていたことにあったのではないかと思っています。本質とは普遍的な性質だから、本質をソフトウェアの骨格になりえます。しかし、果たしてそれだけで再利用性が高いとまで言えるのでしょうか。骨格は大事ですが、価値のあるソフトウェアを生み出すには骨格にどれだけ適切に肉付けしなければなりません。本質だけを考えていては、骨格を再利用した新たなソフトウェアが作れるのか(作りやすいのか)は見えてきません。ソフトウェアの普遍性も大事だけれど、将来どのように変化するか(あるいは変化させたいか)という可変性も大事だということですね。

長文になってしまいまいしたが、まとめると再利用性について考えるには次の二つが必要なようです。
(1)ドメイン間の関係性が明確になっていること
(2)ドメインの時間的・空間的変化が明確になっていること

ところで、私の「しっくりこない」状態はずいぶん長く続きました。だいたい、2年ぐらい続いていたのかもしれません。きっと周りの熟練者たちに聞けばすぐに解消したのでしょうが、そのときの私は自分がなぜしっくりこないのかすらよくわかっていなかったので疑問を上手く質問という形で表現できなかったんですね。
それにしてもこうやって振り返ってみると、そもそもの問題は、一つのドメインだけを見たり、本質だけ考えたり、部分だけを見て全体を見ていないことなのかも。。
| YAGURA | ソフトウェア | 01:13 | comments(0) | trackbacks(0) |
Rails/Rubyにあって Struts/Javaにないもの
仕事で Railsを使っています。実は Webアプリケーションのフレームワークを使うのは Railsが初めて。それまでは Ruby や PerlでちょっとしたCGIを作ったことがあるくらいで、フレームワークでどれくらい開発が楽になるのか半信半疑でした。これまであまりフレームワークを使ったことがないせいか、フレームワークは面倒なことをいろいろなやってくれる半面、使い方の制約が厳しくて本当に開発が楽になるもんなのかな、と考えていたので。

Railsの場合も厳しい制約があるのは確かなんだけど、制約を上手に使っています。いわゆる Convention over configurationといやつです。オブジェクトとRDB間のマッピングやコントローラアクションとURLのマッピング、こういったアプリケーションにとって本質的ではないところに厳しい規約を設けてる。こうすると、アプリケーションを作る人は、本質的でないところは何も考えずに規約に通りに作ればくよくて、思考を節約できる。つまり、本当に作りたいものに集中できる。

この感じは Rubyでプログラムを書くときの感じと似ていて、本当に作りたいものに集中できるから、作っていてとても気持ちが良いです。Strutsも試してみたけど、疎結合を重視するせいか、設定ファイルが多かったり、RDB上のデータに対応するクラスを記述しないといけなかったり。Railsを使った後だと、「そんなのどうでもいいからフレームワーク側で勝手にやってくれ」と言いたくなるんだよな。やりたいことに集中できなくてイライラしてしまう。もちろん、StrutsとRailsが目指すものは同じではないだろうから、仕方がないことなのかも。

Rails/RubyにあってStruts/Javaにはないもの。それは本当に作りたいものに集中して作ることができる「作り手にとっての気持ち良さ」。これからフレームワークやライブラリを設計する際には、保守性や堅牢性だけでなく、これを重要な要因にして設計したいなと。具体的にはどうしたらいいかとか何も思いついてないんで、これから考えてみよう。
| YAGURA | ソフトウェア | 23:55 | comments(0) | trackbacks(1) |
RadRails

Rad RailsはRuby On Rails用のEclipseプラグインです。
Railsプロジェクト、MVCの生成、サーバの起動・終了が Eclipseからできるようになります。オートコンプリートや語句のカラー強調にも対応。



既存のRuby Projectから Railsプロジェクトに移行する方法

EclipseやRadRailsの作りに詳しくないので、これがまっとうな方法なのかわかりませんが、メモしておきます。
RDT で作成したプロジェクトは、そのままでは RadRailsで開けません。
開くには以下のようにします。


  1. RDT が生成したプロジェクトを Eclipseから削除します。

  2. Eclipseの RadRailsプロジェクトを新規作成を選びます。

  3. project contentsで、1で削除したプロジェクトのフォルダを選びます。

  4. Options の Generate Rails Apllication のチェックを外します。

これで 作成中のプロジェクトを RadRailsで開発できるようになりました。Elcispeからサーバ起動などできるので便利。ただ、RadRailsはまだ少しバギーかも。。

| YAGURA | ソフトウェア | 01:06 | comments(0) | trackbacks(0) |
Web Application開発に
JavaScriptビジュアル・リファレンス
JavaScriptビジュアル・リファレンス
シーズ
| YAGURA | ソフトウェア | 22:20 | comments(0) | trackbacks(0) |
 123456
78910111213
14151617181920
21222324252627
28293031   
<< May 2017 >>

このページの先頭へ