アーキテクチャスタイルと重きを置いているレイヤを見ていただきたい。これは2年ぐらい前の絵なので、ちょっと古いし、正直、適切でない言葉が使われていると思う。RESTはSOAと同列に書くとすればROAだろう。SOAなんてカッコつけないで、Webサービスぐらいにしておけばよかった。また、Web2.0をBoundaryに置いているが、広範囲に使われる言葉になった今では違和感がある。当時はAJAXブームもあり、クライアント技術が先行していたので、それほど違和感なく見れたのだが、それにしても、この業界の進化は早い。今これを書き直すとすれば、View、Mashup、Resource、といったところかな。実装技術では、Viewのところが、JavaScript, Flex2 AIR, PHPで、Mashupのところが、PIPES, Plagger, sMash、Resourceのところが、Hadoopやhbase, ネット上のRSS,ATOMとするのがしっくりくる。Reflexはどのレイヤにも当てはまるがResourceに置くのが一番適していると思う。(書き直した絵=>RESTful設計におけるレイヤと主な実装技術
長々とわけ分からん絵の説明をしたが、いいたいことは設計をどうすべきかということ。
オブジェクト指向設計では、まず、ユースケースの図と記述を作成して分析クラスを導き出す。プロジェクトでも同様にやったのだが、これは非常に有効な手法であった。しかし、分析クラスから、その後の設計クラスをどのように作っていくかについては、モデラーの感性に依存するというか、正直なところ曖昧で、あまり機能していないのではないかと感じている。世の中にはこれを課題と感じないスーパーなモデラーがいるのは承知している。分析クラスをそのままStrutsのMVCモデルに落とし込めないのが分かっていても、彼らは平気な顔して設計クラスをサクサク作っていける。(もしかしたら彼らには分析クラスは必要ないのかもしれない)あるいは、経験を積んだモデラーにとっては(※)モデリングがパターン化されており、単純な工程で済んでいるのかもしれない。
(※ オブジェクトを設計していくことをモデリングという)
分析クラスのBoundary、Control、EntityがそのままStrutsのMVCモデルに落とせない、なんていいだすと、スーパーモデラーじゃなくても異論が噴出するかもしれない。(面倒なので詳細は省略するが)単純にいうと、分析クラスのBoundaryは主に画面(入出力装置)、Entityはデータ、Controlは要求に応じてデータを集めたり加工して返すところとなる。問題は、Strutsに落とし込んだときに、Controlのおき場所に困ることだ。StrutsにおけるControlerはフレームワーク自身を指す(あるいは含んでいる)ので、アプリケーションのControlerの立場はどうするの?といった話になる。多くはModelに集約されることが多いようだが、これはこれで面白くない。なぜなら、せっかく分析クラスで分けたものを設計クラスで一緒にするなんてモデリングの意味ないじゃん、と思うからである。稀に、Controlerのパッケージを作って、きっちり別管理しているプロジェクトもあるようだが、管理に強制力はないため、プログラマーによってグチャグチャにされてしまい、どれがModelでどれがControlerか区別がつかなくなるのが現状のようだ。まあ、ControlerとModelをきっちり分けることで、いいことがあるとすれば、ワークフローを導入してControlerを外だしにするような場合だろう。そんな話は滅多に聞かないから、グチャグチャになっても、それほど大きな問題はないと思われるが・・。
いずれにせよ、Modelの実装はけっこう面倒で工数がかかる。テーブルはRDBの世界であり、一方のEntityはObjectの世界なのでインピーダンスミスマッチを解消するためO/Rマッピングが必要となる。私はこのO/Rマッピングが工数増大の大きな要因と見ている。オブジェクト設計のドメインモデルでは、Entityからテーブルを作成していくのが基本だが、テーブルは非常に重要な部分なので、人によってはテーブル設計から先に始めるかもしれない。(分析クラスがなくてもモデラーが平気な顔して設計できるのはテーブル設計があるからだろう?)しかし、ボトムアップ的にそうやってしまうと、Rの都合により作成されたEntityクラスとなって、モデリングが無視されたオブジェクトになる。そのままだと今度はControlerやViewから使用できなくなるので、O/Rマッピングしたクラスをさらに組立て直して、Modelの形を崩さないよう努力するはめになる。そのような組立直しクラスをDXOと呼ぶそうだが、そんな無駄な処理をモデルの中でゴニョゴニョやっているのである。これはもはやオブジェクト設計ではない。
そこで、得た結論は、
否定の6.オブジェクト設計をしない
である。正確には、設計クラスのModelをオブジェクトにはしないで、オブジェクトで扱うデータに関心を集めようというもの。Modelとは、モデリングによってできた成果物(※)でありオブジェクトであるから、データとプログラムがくっついている状態。それからプログラムを切り離してデータのみに関心を集めて考える。データだけであればオブジェクトではないのでオブジェクト設計をしないことを意味する。とはいえ、分析クラスまでは設計して論理ビューを作る。論理ビューで定義したサブシステム内であれば、勝手に設計/実装して構わないという感じになる。具体的な実装例の記事を書いているのでこちらを参照願いたい。
ZEROからRESTfulアプリを作成
ビューの実装
リソースの実装
フローの実装
(※ Modelの定義は曖昧で様々な説明が存在する。私はこの説明が一番好きだ。)
しかし、これでも同様にO/Rマッピング問題は存在する。Entityは本来はオブジェクトの視点で設計するが、実際にデータを格納するテーブルの設計とどう整合をとるか。これは次の2点で解決する。要は、設定よりも規約(Convention over Configuration,CoC)をやろうということだ。参考:Entity設計
1.Entityはデータ構造の集まりであるから、これをそのままRDBにマッピングする(Reflexはその機能をもっている)
2.ControlやViewからEntityへのアクセスはCRUDのみとする
Entityの設計では、まず、データ構造を定義して単純なAPIを公開する。公開の手段は、XMLやJSONなどを使って表現する。また、APIはデータ操作だけなのでCRUDのみとする。HTTPであれば、GET/POST/PUT/DELETEの4つだけだ。これはRESTと呼ばれるアーキテクチャスタイルだ。Webサービスであればサービスごとに定義されたインターフェースとなるところを、RESTでは4つのAPIでリソースを操作することになる。
データのみに関心を集めたEntityでは構造化はされているがRのイメージに近い。
テーブルのカラム名がクラスのフィールド名と同一となり、それをシリアライズした、JSON、XMLのタグ名も同じになる。テーブルは、O/Rマッパで隠蔽されているイメージから開放され、語彙が統一できてシステム全体で見通しがよくなる。
あと、忘れてならないのはビジネスロジックの存在だ。これは今までModelの中に実装されていたが、Modelはデータだけになったので、別途管理する必要が出てくる。また、実行時にModelをパラメータとして渡すことになるが、まあ、これはこれでテストが楽になるのでOKかなと思っている。
<関連>
RESTfulな新3層アーキテクチャ
ドメインモデル貧血症、サービスと振る舞いについて
3分で分かる設計の話
0 件のコメント:
コメントを投稿