flat7th

memo/20110216

created 2011-02-16 modified 2011-03-09 

Androidにからんで、最近Javaをいじっているが、...

私はやっぱりJava嫌いだ。っていうか苦手だ。私には、Javaの原理主義的なオブジェクト指向は、古いオブジェクト指向時代の「手段と目的の履き違え」を引きずっているように見えてしまう。


時間のかかる処理の完了時の処理をするために、コールバック機構、デリゲート機構を作りたかったんですよ、今日は。

Javaでコールバックしたい場合は、(1)コールバックを分けたい単位でクラスを全部分けてやらないといけないみたい。つまりオブザーバパターン。

さもなくば、(2)リフレクションを使うか。

あるいは、(3)コールバックの呼びクチは1箇所に集約して、switch等で自分で分けるとか。


Javaではコールバックと言わず、デリゲートとも言わず、リスナー(クラス)っていうんだってさ。

Android関係のサンプルコードをみてると、やたら○○リスナーと言ってラムダ関数っていうか無名クラスが出てくるので、妙だな、単体テストしにくいだろ、とおもっていたのだが、デリゲートが使えないと知って少しだけ納得。


(1)のオブザーバパターンっていうのは、GoFのパターンの中でも「使える」パターンの一つで、M-V-VMパターンでも有効に使われてるように【プログラムの依存関係を逆転する(=プログラム変更の際の主従関係を逆転する)】ためのいい考えだとおもっています。
有効な例:これまでの3層レイヤ方式で、ロジックはデータを呼び、またロジックはプレゼンも呼ぶ、だと、一番偉いはずのロジックが、プログラム変更に際してはプレゼンとデータの両方にアタマ下げて従わなければいけない。M-V-VMでは、プレゼンとロジックの呼ぶ・呼ばれる関係を、オブザーバパターンで逆転することで、主従関係を(立場が強いほうから) データ→ロジック→プレゼン の一直線にしたと。
それはナイスな考えなのですよ。とくに、これからはスマートフォン対応などで、ロジックに対してプレゼンがマルチ(複数)になっていくから。

でもコールバックっていうのは、もっと細かい単位で使うもんだろ?と。

しかも、コールバックされた処理の中では結局何をやりたいかと言うと、ユーティリティの利用者側(=コールバックされた側)がガメていた(privateにしたかった)データをいじる訳だ。結果を格納するテキストボックスを更新する、とかね。
で、メソッド分割で作れるデリゲートと比較して、クラスが分かれる方式だと、せっかくのカプセル化を解かないといけなくなる。そうなると、もうどこにメリットがあるのか訳が分からん。

(2)のリフレクションって高価な手法だと思ってるんだが、間違ってますかね?

(3)のswitch文って結局アタマから総当たりでブランチしていくだけなので、非効率なのよね。メソッドポインタが使えればポインタ配列でO(1)でできる話なんだが。


結局、Javaでつくるとクラスが細かくなりすぎて、しかもぼんやりカプセルが開いたクラスが多くなって、「ソフトウェアをシンプルに保って管理しやすくする」「細かいことに目をつぶってザックリ理解しやすくする」というオブジェクト指向の目的からどんどん遠ざかっていく。

なんかいい方法ないのかな。


脱線:

普通、switch文を初めて見たら効率よく検索してるとおもうよね。私も昔そう思った。でも実際はif、else if、とアタマからブランチするように翻訳される。
新しいプログラミング言語の作者はなぜ、switch文を、テーブル検索するように翻訳しないのだろう?

C/C++はそう翻訳せざるを得ないんだけどさ。理由は、breakしないことをゆるしていて、判定する順番、ソースに書いてある順序が意味をもってるから。でも新しい言語はbreakなしを許さず複数のcaseに入ることを許さなければいいのに。

C/C++では関数ポインタ配列を簡単に書けるから、O(n)となることを回避する方法はあるんだが、javaは...

やっぱりJavaはフールプルーフを重視した言語なのだろうか。



まぁね、こういうこと考える事自体が楽しいからいいんだけどさ。



2011/3/9
「嫌いなものじゃなくて好きなもので自分を語れよ」
と、「国際問題をハスに流す萌えキャラ」に言われた気がするので、今後気をつけます。