この1年ぐらいはSOAのアイデアを、どうにかしてアプリケーション開発に利用できないかと考えています。まだまだアイデア段階なのですが、ちょいちょい書いていきます。
マルチレイヤーでは統合が重要
Javaに限らずアプリケーションというのは複数の層によって開発するというのが一般的です。MVCモデルのようなプレゼンテーション層とパーシステンス層の分離が有名ですが、間にファサード層、ビジネスロジック層など挟み込むというのも良く行われています。
アプリケーションをモノシリックな仕組みで作ってしまうと複雑性が増し柔軟性が失われてしまいます。そこで、層ごとに分離することでシンプルさを保つことようにします。層ごとには責務や役割を明確にされ、それ応じたエンジニアが開発を行います。
層を分離するからには層を統合しなくてはなりません。層をいかに統合するのかというのは、層を分離することよりも重要です。
メッセージによるレイヤーの統合手法
具体的なレイヤーの統合方法はレイヤー間の通信によって行われます。メソッド呼び出しでも、Webサービスでもそれは同じことです。
統合で重要なのは柔軟性の確保です。せっかく分離したものを密結合してしまっては意味がありません。そこで通信されるメッセージに柔軟性を担保するというテクニックが良く知られています。メッセージのセマンティックを重視することでインターフェースをシンプルに保つわけです。
例えばAmazonウェブサービスの商品検索に関するインターフェースは1つです。それを通じて本やDVDなどの情報を柔軟に取得することができます。APIのバージョンアップとはインターフェースの変更ではなくメッセージスキーマの変更という形で実現されているのです。
もっとアプリケーション設計寄りで言えばDAOのパラメタオブジェクトをあげても良いでしょう。UserDaoのメソッドsearchを定義するなら、引数はクラスUserSearchRequestとします。こうすれば検索条件が増えたとしてもクラスUserSearchRequestの属性を変更するだけでよいわけです。
もちろんインターフェース設計はどうでもいいということではありません。ビジネスロジック層へのアプローチがすべてパラメタで処理されるとなると、それはそれで柔軟すぎて複雑になってしまいます。適度にドメイン分割をすることが必要です。とはいえ、ここの適度感は非常に難しく未だに的確な分割方針を聞いたことがありません。
余談ですが、個人的にはインターフェースが「システムの見える化性」からもデザインされるべきだと感じています。インターフェースはシステムの監視ポイントです。メッセージの意味まで解釈して監視するのはけっこうめんどうなのです。遠い例ですがWebサイトのディレクトリ設計(ようはURL設計)をアクセス解析のために行うようなものです。あとで理解しやすいようにURLが取得されていないとアクセス解析しても意味が分かりません。解析ができれば対応を行うことができます。これはスケーラビリティやメンテナンスビリティなどの要素に大きな影響を与えます。
あ、あとは現状のAOPがインターフェース単位でしか機能しないことも上げられるでしょう。将来、コンテキストやメッセージパラメタによって適用ができるようになるかもしれませんが、そこまでくると、なんだか高機能なネットワーク機器のようでもありますね。
SOAのアプローチで実現するメッセージの柔軟性
あぁ、話がまるごと横道でしたね。ようは層を分割するってことは統合しなきゃいけなくて、柔軟じゃなきゃいけないよと。で、柔軟にするにはメッセージを重視するのが流行っていると。
というわけで、SOAの思想というのは非常にうまく作られています。初期のころのWebサービスというのは、所詮はインターフェースと実装の分離でしかないわけで、僕らはDIコンテナでうまくやっています。
ですが、ESB(エンタープライズ・サービス・バス)ぐらいになってくると話が変わってきます。ESBはメッセージの経路を丸ごと外部化しています。クライアントは、「あて先名をつけたメッセージ」を送出するだけでインターフェースを選択することなどなく処理を行わせることができます。さらに処理をチェーンさせることも可能になります。クライアントからは1つの処理要求であったとしても、複数のコンポーネント間をまたがって処理を行い、その結果をアグリゲーションして処理することもできます。こうしたコンポーネントの組み上げをESBがメッセージを中心に肩代わりしてくれるのです。
もちろん、こうした設計をアプリケーション内に持ち込むとなると問題はあります。簡単に思いつくのは以下の2つ。
1.交換ルールの複雑化による設定地獄
2.メッセージ交換のオーバーヘッドによるパフォーマンス劣化
1ですが、これは、もうおっしゃるとおり。SOAだってEAIだって、そこで苦しんでいます。これにはスマートなアイデアが必要です。1つはコンポーネントをアセンブルするための専用記述言語(文字でも絵でもいいけど)を考えること。XMLじゃ無理なのは明らかです。アプリケーション内のルーティングルールは、それなりに複雑になります。いちいち画面で作るなんてことはしたくありません。ここにスクリプト言語を使えば?というが、僕の意見。
2ですが、これは、実はあまり気にしていません。なぜなら非同期処理(並列処理)を見据えられるからです。同期・非同期処理を明示的に分割してコンポーネントを配備しておければ、アプリケーション全体としてのパフォーマンスを優位に処理することができるようになります。最近ではCPUは発展もコアの増加に向かっていますし、さまざまな分散処理アーキテクチャが生まれています。CPUをぶん回すよりも、小さな処理を大量にこなす方が重要になるのです。
元々、SOAはサーバ間のファイル交換とかEDIから発展したものです。EDIの仕組みから考えると、IPやポートというインターフェースしかなかったので、このようにメッセージがリッチになる仕組みであったわけですが、これを従来のアプリケーション側から考えてみるとけっこう面白いのです。
