« ドキュメンテーション・ツールNatural Doc | main | Flash8の先行予約開始 »

2005年08月07日

OOP全盛期だけど、手続き型がマイブームになってる(前)

このオブジェクト指向全盛期に、なんか手続き型のプログラミングがマイブームになっています。
いや、マジに手続き型ってさ、超便利じゃないですか???

「手続き型ってなによ?」って人もいると思うので超簡単に説明しちゃうと・・・

オブジェクト指向は、データと関数(アルゴリズム)1つのクラスとして、まとめてデザインするプログラミング。
手続き型は、データと関数を分離して作成するわけです。いわゆるBasicみたいな昔っぽいプログラミング手法です。

一般的に、「手続き型は古い手法で、OOPのほうが汎用性も生産性も高い」ってイメージなんだけど、最近ほんとうにそうなのかな?って気もしてきた。

というか、(OOP言語で)あえて手続き型やるのって、超柔軟性あるんじゃね? とか思ってしまったり。


例えば、RGB(赤、緑、青)値で色を管理するColorクラスがあるとします。それを拡張して、hsb(色相、彩度、明度)で色を設定したい。こんなときにOOPだとColorクラスを拡張して、ColorHSBクラスを作ります。で、使用するときはこんな感じ

var col = new ColorHSB();
col.setHSB(240, 100,100);

var hsb = col.getHSB();

一方、手続き型で同じことをしてみます。
手続き型ではデータと処理を分離するのでColorクラスを拡張しません。かわりにColorUtilクラスを作って、そっちで処理をします。使用方法はこんな感じ。


var col = new Color();
ColorUtil.setHSB(col, 240, 100,100);

var hsb = ColorUtil.getHSB(col);

手続き型では、毎回ColorUtilを呼び出す必要があるので、処理が煩雑な感じですね。
っていうかOOPに慣れ親しんでしまうと実際スゲェ、メンドクサイです


じゃあ、なんで「手続き型」がいいのかというと、手続き型だと他人のライブラリを導入するときや、自分のライブラリを再設計するときに、既存資産の運用がく柔軟にできるのではないかと思ったりしたんです。
 
 
 
 
ちょっと具体例に、さっきのColorクラスの拡張の続を。

グラフィックエンジンを作成するとします。自分で1から作る時間がないので、他人のライブラリを使用します。しかし、このライブラリではライブラリ作者がグレースケールに対応した、ColorGrayクラスが用いられていました。ここで問題発生です。自分だって独自にColorHSBクラスを持っていますし、それを利用した色々な便利クラスを大量に持ってるわけです。


はたして自分が作ってたColorHSBは、他人の描画ライブラリと組み合わせて動くんでしょうか?あるいはColorHSBと関連ライブラリの使用は全部あきらめなければならないんでしょうか?


正直いって2つのライブラリを混ぜるのは、かなり微妙(というか危険)な気がします。相手のライブラリの中でどう型キャストが行われているかわからないし、そもそもライブラリの処理が、ColorGrayに高度に依存していたら致命的です。動いたとしても、グレースケール/HSBの相互変換で2つのクラスでデータを行き来させるなんて死んでもやりたくないです。おそらくこの場合は、他人のColorGrayクラスを拡張して、hsb変換の機能を付加するのが妥当なんだと思います。これだと、せっかくのOOPなのに過去の資産がまるきり無駄になりますよね。
 
ここで手続き型の出番です。
ColorUtilクラスはどうか?というと、これはかなりの確率で、安定して別のライブラリ組み合わせてもOKです。なぜならColorUtilクラスは単に、Colorクラスのapiにアクセスしているだけだからです。他人が作ったColorGrayクラスであろうとも、その親クラスがColorクラスである限り、apiを介してrgb値にアクセスするならばなんの問題もないわけです。なんか、手続き型のほうが、なんか柔軟性高い気がしてきませんか?
 
 
 
で、ここからが応用。
「手続き型」は関数の呼び出し作業が煩雑なのがネックなわけですが、これをOOPで解消するっていうのはどうでしょう?手続き型関数ColorUtilを作成した上で、Colorクラスを拡張してColorHsbを作ります。そして、ColorHsbのsetHSB()の処理では、内部的にColorUtil.setHSB()を呼び出すように処理するわけです。


function setHSB(h, s, b){
ColorUtil(this, h, s, b);
}

こうすると、ユーザー的には手続きを意識しないでOOPで作業ができます。またColorGrayのような他人のクラスであっても、ColorGrayを拡張して内部でColorUtilにバイパスしてやれば、ColorGrayにsetHSBを実装するのも一瞬ですみます。超楽チン。変に多重継承するわけでもないので、オブジェクトツリーがレガシーで埋まることもなく、自分のライブラリをブラッシュアップとかするのも凄い楽になります。

こうすると、OOPの利便性を機能を保ちながら、オブジェクトとアルゴリズムを分離できるんじゃないかと思ったわけっす。処理は微妙に重くなるけど、最近のパソなら大丈夫っしょ。

と、この前思いついて1人で感動していたんだけど、既出ネタだったらスマソ。

投稿者 Taka : 2005年08月07日 16:38

book

dotfla.gif

bookmark

はてなブックマークに追加

del.icio.usに追加

trackbacks

this entry's trackback URL:
http://www.fladdict.net/cgi-bin/mt3/mt-tb.cgi/272

このリストは、次のエントリーを参照しています: OOP全盛期だけど、手続き型がマイブームになってる(前):

» RubyのMix-inによるColorUtilの解決!? from 満足せる豚。眠たげなポチ。
fladdict.net/blogさんの「OOP全盛期だけど、手続き型がマイブームになってる(前)」を読んで、んー、これってMix-in的なあれなんだろうか、と... [read more]

トラックバック時刻: 2005年08月08日 04:12

comment

「委譲」のような気がします、これって。

by dev : 2005年08月08日 00:17

確かに便利なんだけど、このやり方だと基底クラスとなるColorクラスのsetRGBメソッドだとか
その辺のメソッドを全部publicにせざるを得ないので、使いどころを見極める方に神経使いそう。
大規模なプロジェクトだと管理しきれないかなー

by mune : 2005年08月08日 06:18

方向性はいいと思うのだけれども
普通にデータの構造体をレコード型にして
ポインタ渡しで手続き型関数を使うって形でよいのでは?

つーかZlibとかLIbpngとかそういう構造では?

by とおりすがり : 2005年08月08日 10:35

デザインパターンの Decorator が近い気がします。
が、よく理解できてない上に詳しくないので嘘だったらごめんなさい。

by hiyon : 2005年08月08日 21:53

>devさん
ですよね、基本的に委譲です。ただ自分的には委譲って、に別のインスタンスを内部で格納するイメージがあって、静的関数をラップするのはあまりないのかなぁ、って思ってました。どうなんでしょう?

>ムネゴンさん
>大規模なプロジェクトだと管理しきれないかなー
マジっすか?? 大規模なのやったことないのでちょとわからんのですが、注意して使うようにしてみますー。

>とおりすがりさん
>つーかZlibとかLIbpngとかそういう構造では?
すいません、そこらへんの分野全然わからないのです。完全な手続き型にしないのは、個人的に普通のOOPのビルトインクラスと同じ手法でコントロールできるようにしたかったからです。

>hiyonさん
うーん、デコレーターとはちょっとだけ違うような気がします。というか僕もそこまで詳しくないので気にしないでください。


by Taka : 2005年08月10日 19:00

coolblooded is feature of lazy game: http://news.bbc.co.uk/ central game is always red table , greedy pair destroy or not

by Carlos Carpenter : 2006年03月28日 12:11

コメントしてください




保存しますか?