« 真のIT企業はメディア企業を目指す | トップページ | 【感想】Kansai.pm第9回ミーティング »

2008/05/29

オブジェクト指向言語と関数型言語の書き方の違い

【1】オブジェクト指向言語の書き方は「set-do-get」

複数の引数を渡して、価格を計算する処理を実装するとしよう。

手続き型言語なら、下記のようなシーケンス図になるように書くだろう。
つまり、1個の関数にたくさんのロジックを詰め込む。

C


例えば、Cのmain関数のように、1個だけの関数にロジックを詰め込んで、下手をすれば数千行に及ぶソースになる。
そうなると、もはや保守していくうちに、誰もが修正できなくなる。

オブジェクト指向言語なら、下記のようなシーケンス図になるだろう。
つまり、1個のクラスに必要な情報をsetし、状態を変化させて、必要な情報を最後に取得する。
副作用を起こす関数(set, do)と副作用の無い関数(get)を使い分ける。

いわゆる「set-do-get」の書き方。

Java

オブジェクト指向に基づいて綺麗に設計したシーケンス図は、階段状のシーケンスになることが多い。
つまり、複雑なロジックは、各クラスへ適切な粒度で分割される。

例えば、購入した商品の計算は、商品の価格と個数だけでなく、内税や外税のような消費税計算、あるいは、ポイントを使った割引など計算ロジックが複雑になりがち。

更に、会員が上得意か新規かという会員区分、あるいは、ギフト商品や優待会員向け商品など商品によって計算ロジックを動的に変えたい時が発生する。

だから、計算クラスを更に分割するなどのクラス設計をするのが普通。
この時に、ポリモルフィズムを使う。

Javaでは、ポリモルフィズムをState/Strategyパターンで実現する。
この時に、継承構造を使うことが多い。
そして、機能追加や保守していくうちに、継承構造が深くなり、サブクラスから親クラスをコールするような依存循環構造が発生して、手に負えなくなってくる。

Ajaxのような関数型言語の出現によって、オブジェクト指向によるポリモルフィズムは限界があるのではないか、と最近感じる。

【2】関数型言語の特徴~クロージャと継続

プログラミングGauche」では、関数型言語Schemeの最も基本的なルールは下記の2つだと喝破している。

2-1.lambda式は「レキシカルな環境を保持した手続き」(クロージャ)へ評価される。
2-2.手続き呼び出しは継続を使った引数付きgotoである。

クロージャの例として僕が分かりやすかったのは、クイックソート。
C言語で実装したクイックソートの関数では、ソート関数を関数ポインタとして引数で渡す。

PerlやRubyでは、テキストファイルを読み込んで、ゴニョゴニョ処理するロジックでクロージャを使う時が多い。

プログラミングGauche」では、「継続とはプログラムのその時点より後に行う計算」と説明している。

継続の使い道は、Webアプリなら、ログインチェックだ。
つまり、ログインに失敗して、再入力してログインに成功したら、途中まで読み込んだ処理の途中から再開して実行する。
更に、Webアプリで継続が使えれば、いつも問題になる「戻るボタンの遷移」が簡単になる。

クロージャと継続を使って、ポリモルフィズムを実現できないか?
つまり、複雑な条件分岐を、クロージャと継続を使って、もっとエレガントに書けないだろうか?

関数型言語でポリモルフィズムを実現する手法は、リフレクションだと思う。
複雑なループ処理、深くネストしたIF文などの制御構造そのものを一つの手続きに抽象化する。
IF文の判定式、条件分岐後の実行ロジックは、リフレクションで後から動的に決める仕組み。

関数型言語は、手続き型言語やオブジェクト指向言語と書き方がまるで違う。
もっと研究する余地がある。

|

« 真のIT企業はメディア企業を目指す | トップページ | 【感想】Kansai.pm第9回ミーティング »

プログラミング」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック


この記事へのトラックバック一覧です: オブジェクト指向言語と関数型言語の書き方の違い:

« 真のIT企業はメディア企業を目指す | トップページ | 【感想】Kansai.pm第9回ミーティング »