Webプログラミングは何故オブジェクト指向でない?~WicketはWebプログラミングにオブジェクト指向を取り戻す
JavaでWebアプリを10年書いて思ったこと。
Webプログラミングは全然オブジェクト指向でない。
Sevlet+JSP主体のプログラミングスタイルは、リクエストとレスポンスへPrimitiveな値をどうやって渡すか、という手続き型の発想でしか書いていない。
従来のWebプログラミングスタイルの問題点について書いてみる。
以下ラフなメモ書き。
【参考リンク】
Wicketって?
Wicketで始めるオブジェクト指向ウェブ開発:第1回 Hello, Wicket|gihyo.jp … 技術評論社
【コラム】イマドキのIDE事情 (39) Wicket、Grails、Click - IDEでみる軽量Javaフレームワーク | エンタープライズ | マイコミジャーナル
【レポート】Wicket入門 - JavaとHTMLだけで作るWebアプリケーション (1) Wicketとは? | エンタープライズ | マイコミジャーナル
Javaで軽快に使える「軽量フレームワーク」特集 ~Apache Wicketで簡単Webアプリ作成(1)(1/5):CodeZine
【問題点 1】MVC2モデルは全然オブジェクト指向でない
オブジェクト指向はデスクトップアプリのプログラミングで試行錯誤した歴史から生まれた。
その基本思想は、MVCモデルにある。
MVCモデルは、Model・View・Controllerがあたかも生きているように、お互いにメッセージを通知して自分自身を更新する。
この設計思想のおかげで、複雑なデスクトップアプリを作れるようになった。
しかし、Webプログラミングは基本は、MVCモデルを変形したMVC2モデルから成り立っている。
StrutsもRailsも同様。
StrutsならActionServletがHTTP経由のやり取りを制御し、擬似的なMVCモデルを作り出す。
しかし、MVC2モデルでは、本来のモデルは出てこない。
JSPとServletの間では、従来と同じく、String型の値を渡しているだけ。
ServletはActionにリクエストパラメータを渡し、ActionはまさにVBライクに手続き型でプログラムを書いて、レスポンスへ結果を渡すのが普通。
だから、GoFのデザインパターンをフルに使えていない。
Webアプリにはイベントという発想がそもそもないのだ。
その根本原因は、Webアプリには「画面の状態を保持する」という仕組みがないことに尽きる。
そこから派生する問題については、以前Blogにも書いた。
Webアプリのセッション管理はデスクトップアプリのメモリ管理と同じ: プログラマの思索
【問題点 2】JavaよりもXMLを書いている時間が長い
Strutsが出現した2002年頃は、画期的なWebフレームワークだった。
何故なら、従来のJavaのWebフレームワークは大手SIが独自に開発した俺俺フレームワークが主流で、どれも使うのが苦痛だったから。
Strutsによって、ActionServletがJSPとActionの橋渡しを担当して、プログラマはXMLに設定ファイルを書いて、Actionだけに業務ロジックを書くのを専念すれば良くなった。
SeasarもRailsもStrutsの進化系に過ぎない。
しかし、XMLに画面遷移やフォームのバリデーションチェックなど各種のロジックを書くスタイルのために、JavaよりもどんどんXMLが膨らむ。
そもそもXMLに書いた方がJavaプログラムを変更しなくていいというのが利点だったらしいが、そのために、あちこちにロジックが散在してしまう。
Webプログラミングとは、ミドルウェア構築作業のように、たくさんのソースと設定ファイルの海を泳ぎ渡るもの、というイメージを大半の人が持っているのではないか?
だからこそ、SeasarやRailsはConversion on Configuration(CoC)の思想によって、コーディング規約を徹底することによって、設定ファイルをなくす方向へ進化した。
JavaではXMLは必要悪。
Railsはメタプログラミングできるので、XMLを保持しなくても、データがRubyプログラムのように扱えることでカバーしているが、発想は同じだ。
【問題点 3】セッション管理が大変
Webアプリで最も難しいのがセッション管理。
Webアプリのセッション管理はデスクトップアプリのメモリ管理と同じだ。
セッションがWebアプリで重要な理由は、画面の状態をセッションに保持する必要があるからだ。
どのタイミングでセッションにデータを入れて、いつ更新して、いつ消すのか?
そのライフサイクルをプログラマが逐一考慮しないといけない。
C++のメモリ解放の問題のように、セッションクリアを忘れると、意味不明なバグが多発する。
セッション管理の問題点は下記に書いた。
Webアプリのセッション管理はデスクトップアプリのメモリ管理と同じ: プログラマの思索
Railsが持つCookie Session Storeは、セッションに保持した画面の状態をクッキーに保持しようとする。
利点は、画面の状態を復元するのが簡単なこと。
でも、根本的な解決方法ではないと思う。
Webアプリによく現れる問題「戻るボタン(バックボタン)」「注文ボタンの2度押し(二重ポスト)」「マルチウィンドウ」などは、従来のWebフレームワークでは解決できていない。
ブラウザの戻るボタンを使った後に再実行すると、予期しない結果に陥る。
注文処理を実行中に注文ボタンを2回押すと、2回注文されてしまうバグが発生する。
注文画面で同じ画面を複数個立ち上げると、予期しない動作が起きてしまう。
これらの処理を制御するために、Webプログラミングはややこしいロジックをいつも入れている。
【Wicket】
最近、Wicketに興味を以ている。
WicketはJavaのWebフレームワークで、Strutsのソースと全く違う。
C#のデスクトップアプリのプログラミング、Java のSwingのプログラミングみたいに、内部クラスや匿名クラスを多用する。
C#のDelegateがJavaにサポートされれば、もっと短く書けるんだろうと思う。
Webアプリを書いていて、オブジェクト指向って本当は何なの?みたいな気がずっとしていた。
Wicketなら、Webアプリをデスクトップアプリみたいに書ける。
オブジェクト指向、デザインパターンをフルに使える余地がある。
「オープンソース徹底活用 WicketによるWebアプリケーション開発」を読んで理解できた点を書いてみる。
【Wicket 1】「Webアプリにオブジェクト指向を取り戻す」。つまりデザインパターンがフルに使える。
デスクトップアプリは手続き型からオブジェクト指向へ進化した時に、デザインパターンという優れたプラクティスを発見した。
だが、Webアプリではデザインパターンはそんなに使えていないのが現状。
MVC2モデルでは、所詮は手続き型プログラミングだから、Strategyパターンぐらいしかまともに使えていない。
でも、Wicketのソースはデスクトップアプリのプログラミングスタイルそのもの。
イベントを内部クラスや匿名クラスで書くから、デザインパターンをフルに使える。
Commandパターンは、イベントをキューに貯めるのに使えばいい。
Stateパターンは、画面の状態に応じてイベントを振り分けるのに使えばいい。
ObserverパターンやMulticastパターンは、オブジェクト変更の通知と更新に使えばいい。
これがオブジェクト指向なんだ、と理解できるから、書いていて楽しいはず。
【Wicket 2】セッション管理を考えなくていい
Wicketでは、HTMLはオブジェクトになる。
つまり、画面の状態はオブジェクトがいつも持っている。
その状態はセッションに保持されている。
「オープンソース徹底活用 WicketによるWebアプリケーション開発」を読んだものの、Wicketのセッション管理についてはまだ理解出来ていない。
でも、メモリ管理のガベージコレクションのような機構をWicketは持っているみたい。
つまり、セッションの解放をプログラマが書く必要はないはず。
「オープンソース徹底活用 WicketによるWebアプリケーション開発」を読んで面白かったのは、「戻るボタン」「二重ポスト」「マルチウィンドウ」の問題をWicketは解決出来ていることだ。
「オープンソース徹底活用 WicketによるWebアプリケーション開発」の「すべてのページはURLを持つ」で詳しく説明されているが、Wicketでは、処理結果を表示するURLとフォーム送信先のURLを分けていて、処理結果を表示するURLのページオブジェクトを作った後に、フォーム送信先のURLへリダイレクトしているのが味噌だ。
更に、Wicketでは画面をバージョン管理して画面の状態を保持している。
デスクトップアプリなら、とても当たり前の動作なのだが、Webアプリではとても難しい。
そのおかげで、いつも画面の状態を知っているから、「戻るボタン」を使ってもどのタイミングで戻ったのかが分かる。
「注文ボタンの2度押し」があっても、同じ結果ページを再取得するだけで何も変えない。
「マルチウィンドウ」になっても、複数の画面はどれも独立している。
Wicketで面白いと思ったもう一つの特徴は、RedirectToUrlExceptionというリダイレクトを行う例外クラスがあること。
RedirectToUrlExceptionの使い道としては、現在の処理をすべて破棄して、別画面へリダイレクトできること。
よくある例は、注文や会員登録で再ログインさせる処理があるだろう。
リダイレクト処理はWebアプリでは結構面倒なのだが、Wicketならば、Javaの普通の例外処理として扱える。
【Wicket 3】Ajaxのように画面の部分更新機能を持つ
Ajaxの特徴の一つは、オフラインでも画面の一部を部分更新出来ることがある。
これによって、逐一サーバーに問い合わせて、セッションの状態を確認しなくても、画面のユーザインターフェイスをリッチに変えることができる。
「オープンソース徹底活用 WicketによるWebアプリケーション開発」を読むと、WicketはAjaxの機能を使って、HTMLの一部を部分更新する機能を持っているらしい。
例えば、実行中であることをインジケータで表示したりすることもできる。
すると、サーバーに問い合わせて画面遷移して更新する場合とローカルで画面を部分更新する場合の2種類をWicketは意識的に使い分けることができる。
特に、後者のやり方だけで画面遷移できるならば、デスクトップアプリと同じ動きになる。
つまり、画面遷移する場合と画面の部分更新を意識して使い分ける設計が優れていれば、画面のユーザインターフェイスはかなり使い易くなるだろう。
Wicketは書いたことないけど、書いていて楽しそうな気がする。
| 固定リンク
「プログラミング」カテゴリの記事
- Javaのモジュールシステムの考え方をまとめてみた(2022.10.21)
- Javaのモジュールシステムは複雑性をより増している(2022.09.10)
- Javaはなぜ関数型言語になろうとしているのか(2022.09.02)
- Javaのラムダ式の考え方(2022.08.10)
- Javaはオブジェクト指向言語ではなく関数型言語だった~「[増補改訂]関数プログラミング実践入門」はお勧めの本だ(2022.08.06)
「ソフトウェア」カテゴリの記事
- Javaのモジュールシステムの考え方をまとめてみた(2022.10.21)
- Javaのenum型はシングルトンクラスみたいだ(2022.06.20)
- テスラが従来の自動車メーカーと異なるところは工場までソフトウェア化すること(2022.02.09)
- 「RubyやRailsは終わった」という記事のリンク(2022.01.09)
- 実践した後に勉強するのがエンジニアの本来の道(2022.01.09)
コメント
賛同します。
セッションやDBはグローバルデータですから。
投稿: さかば | 2010/06/13 21:57