日曜日, 10月 18, 2009

【雑記】 そろそろMVCモデルについて一言いっておくか このエントリーを含むはてなブックマーク


 なーんて、MVCを語れるほどの知識はないのだが、琴線に触れてしまったので、私なりに言いたいことを言うことにする。
 本当は、こんな話より先に、先日参加したGAE Nightの話や、Winnyの金子さんが無罪になった話を書きたいのだけど、ココとか、ココとか、ココとか、ココとか、毎日毎日毎日毎日、MVCを語られると、何かいいたくて、もう我慢できなくなってしまった。(これはエンジニアの性なのか!?)
 中島さんのBlogのなかで最も釣られてしまうキーワードは「えせ」。これを使うということは、自分の考えだけが正しくて、他は間違いであるということを暗にいっているようなもの。多くの人はそれに反応してしまうから、感情論になって、あまりよい結論は見い出せなくなってしまっているんじゃなかろうか。中島さんの言っていることは概ね理解できるし、RESTfulな設計などは私の考えと被る部分もあって、ほぼ同意できるのだが、アーキテクチャーの議論でありがちな不毛な議論に発展しそうになっているところがちょっと悲しいところ。せっかくいいこといっているのにもったいない感じである。
 MVCモデルそのものを含めて、現時点では何が正しいかわからないわけで、むやみに「えせ」という言葉を使うべきではないと私は思うのだが・・・。
 ちなみに、私が考えているReflex設計は、ココココでもいっているように、そもそもオブジェクト設計をしないので、エセMVCモデルの筆頭みたいなものなのであるが、中島さんのいっている「核となるのはビジネスロジックを含んだModelの部分。そこをしっかりと実装し、内部構造を隠す粒度の荒いインターフェイスを定義し、外から何をされてもデータの整合性が壊れない様にすることは何よりも大切」という考えは同じである。
 エセMVCモデルでありながら、考えが同じってどういうこと?と思われると思うので、そのあたりを中心に話をまとめてみたい。
 あらかじめ言っておくと、この手の話は、本当はスルーするのが一番である。

混乱させている曖昧な言葉・・Model

 まず、曖昧な言葉の筆頭は、Modelである。Modelはビジネスロジックを指して使うこともあるが、O/Rマッパで作成したデータを扱うオブジェクトを意味することもある。後者の意味で使う人が多いので、ドメインドリブンな人から「けしからん!」とよく怒られる。
 何事も曖昧なまま強引に話を進めると酷い目にあうのが常なので、まずはModelという言葉の意味の定義が重要だ。私が好きなModelの定義は、先の記事にも書いてあるとおり、「モデリングの成果物」というもの。つまり、オブジェクトを設計していくことをモデリングいい、その成果物であるオブジェクト(=データと振る舞いをもつもの)がModelなのである。モデリングはドメイン、つまり問題領域全般にわたるので、おのずとビジネスロジックのすべてがModelに含まれることになる。なので、本来、Modelには2面性があって、ビジネスロジックを指す意味で使われることもあるし、データという意味で使っても構わないものなのである。

 また、MVCモデルはオブジェクト設計を前提にしたものであるが、多くの人はロバストネス分析をやって分析モデル(BCEモデル)を作ることを省略している。これらは脳内でやっている人がほとんどだろう。BCEモデルは、抽象クラスの「操作」と「属性」により、データはEntity、制御はControlといったように整理できる単純明快なモデルなのだが、これを設計モデルのMVCモデルに落とすときに、データであるEntityと制御であるControlの一部がModelになるため、これがモデラーのセンスを必要とする非常に難しい作業となってしまっている。
 その様子は、以下の図がわかりやすい。(参照:UMLモデリングのノウハウ、最後の秘訣)
 このとき、Modelに記述すべきビジネスロジックが少ないと、「エセMVC」とか、「ドメインモデル貧血症」とかいわれるはめになるわけだ。



 また、BCEモデルにおいては、EntityからEntityを呼ぶことはできないという制約があるが、ModelにはControlの一部が入るため、ModelからModelの呼び出しが可能になる。DDDではそれを前提に設計するため、逆にControllerの責務が曖昧になっている印象を受ける。
 SCAなどのコンポーネントアーキテクチャーではもっと進んでいて、各コンポーネントはreferenceと、serviceという口をもち、それぞれを結合できるようになっている。また、それらを内包した大きなコンポーネントを作ることができる。このアーキテクチャーにはControlerは存在しない。敢えて言うならマッシュアップサービスということになるのだろう。



混乱させている曖昧な言葉・・ビジネスロジック

 次に曖昧だと思う言葉はビジネスロジックである。ビジネスロジック=すべての処理ロジック(あるいはプログラムコード)というふうに理解すると、Controlに書くべきFlowや、Viewに書くべきJavaScriptも含まれることになる。これらは、それぞれのレイヤに存在すべきビジネスロジックである。ちなみに、Modelに書くべきビジネスロジックのことを、私はドメインロジックと呼んでいる。もちろん、ドメイン(問題領域)のオブジェクトに対して、「外から何をされてもデータの整合性が壊れない様にすること」の処理は当然記述することになる。
 FlowやJavaScriptのStep数が大きくなることがあっても、設計上は関係ないはずなのだが、ドメインロジック以外の部分が大きくなることを嫌がる傾向にあるようだ。
 MVCモデルでは、ドメインのすべてをModelに含めることが基本なので、すべてのビジネスロジックまでも、Modelの中に記述しなきゃならないのではないか、という発想をしてしまう。こんな窮屈な発想では、RESTfulで疎結合な設計に合わなくなると思うし、FlowやJavaScriptの利点を軽視してしまうことになって、マッシュアップやHTML5のような「いまどき」のアプリにも合わなくなってしまうと思う。

 前述したDDDやSCAで何がいいたかったかというと、ドメインにビジネスロジックを集約させることにこだわるのであれば、DDDやSCAぐらいの思い切った発想で設計すべきであろう。これに躊躇してしまうということは、後述のビジネスロジックが本当は各レイヤで分断されていて、それを良しとしているからではないか。ビジネスロジックをModelに集約すべきといったって、実際に存在する各レイヤのロジックを無視するわけにはいかず、結局は中途半端になってしまうのが現状。このあたりがModel集約化の話に私が素直に同意できない一番の理由である。

 ということで考えたのが、ココにも書いているような、各レイヤにビジネスロジックをもたせるという設計手法。ただし、ビジネスロジックは、揮発性※であるということが条件となる。また、インターフェース設計は重要で、基本的にCRUDの4つだけを定義して、パラメータはentityそのものとするのがミソ。(※ 揮発性とは永続化しないこと)

entity = blogic(entity);




先日作った請求書アプリを例に具体的に説明しよう。まず、各項目と金額はドメインであり、Entityを検索すれば正しく得ることができる。では、金額とともに表示する「¥」や「,」はどのレイヤのロジックで編集すべきだろうか?また、消費税額計算や合計はどうすればいいだろうか。私のおすすめは、View、もしくは、Controllerのレイヤで記述すること。これらは、上記のblogic関数を使って表現できるもので、わざわざModelでやらなくても各レイヤでやればよいと思う。それは、データの整合性はModelが保証していて、揮発性の上記のblogic関数を使う限りにおいては、整合性を壊すことは決してないからだ。
 
 実際にいくつかのプロジェクトでこれを実践してみたのだが、パフォーマンスや生産性の面で非常に有効という結果を得ることが出来た。パフォーマンスは、高速化プロジェクト その2 で述べているとおりである。リモートにあるModelではなく、ブラウザというローカル環境で実行する部分が増えるわけだから当然といえば当然である。生産性の面では、以下のように、それぞれのレイヤで分業できるという利点がある。このおかげで非常に短納期に開発できた。



ドメインサービスとしてのReflex BDB

 Reflexの新3層アーキテクチャーにおけるドメインは、EntityのCRUD操作以外の何ものでもないのだが、登録変更削除においては、「外から何をされてもデータの整合性が壊れない様にすること」がもちろん保証されなければならないし、検索においては、単なるPKによる検索だけではない点は補足すべきだろう。例えば、PK以外のKeyによる検索、大小比較、全文検索、Pagingといった検索などについては、要求仕様に応じて、それなりにドメインロジックを実装しなければならない。
 まだ公表する段階ではないのだが、Private CloudのソリューションであるReflex BDBの次のバージョンにおいて、単なるKey/Valueの検索ではなく、ドメインサービスとして機能するようなものを作っている。内部的にはBDBなのでKey/Valueではあるが、GAEのProperty Indexのような仕組みを追加することで、汎用的なKeyによる検索などができるようにするつもり。ちなみに、これはConsistent Hashと伝染プロトコルを使ったスケールアウトアーキテクチャーとなっており、Dynamoのようにそれぞれのノードを柔軟に追加削除できる。(予定)
 また、各ノードのアプリはOSGiで管理されており、ドメインに応じたユーザアプリの開発と配布が容易にできるようになっている。(かもしれない)
 ここで強調したいのは、ドメインサービスとすることで、RDBやKey/Valueといった下位のデータ層を隠蔽しているという点。重要なのは結果だけとなるので、O/Rマッピングとか諸々のめんどくさい話は全部ドメインサービスのなかに閉じ込めることができる。
 Reflex BDBは、単なるKey/Value Storageからドメインサービスへの進化をめざしていく。



Key/ValueStorageではなく、ドメインサービスを提供する
・ 単なるPKによるGET/PUTだけでなく、様々なKeyによるRESTfulなCRUD APIを提供
・ <>比較、Range、前方一致検索、全文検索、Pagingなど




(※ 2010/12現在、Reflex BDBは、Reflex Tagging ServiceのPrivate版として開発中。BDBではなくCasandraかHBASEになる予定。GAE版はこちら
2011/3、Reflex BDBは、Oracle Berkeley Edition版としてリリース予定。Tagging Serviceはデータ操作(Resource Operator)としてのI/Fが役割となる。)
2012/5 reflexworks で詳細を発表

やっぱりMVCモデルは進化する

 冒頭、この手の話は、本当はスルーするのが一番であるといったが、最後にそれについて補足する。
 私自身、長年にわたってオブジェクト設計やMVCなどを議論してきて、誰もが納得する解を見出すために、何百人月以上浪費してきた。しかし、コレ!というものは結局見つかっていない。(多くの支持を得ているMVCモデルでさえこの有様である)
 私以外にも、モデリングにコダワリをもつオブジェクト厨も多いと思う。誰もが納得する汎用的な完璧な解を見い出すために現在もなおモデリングを永遠と続けている輩もいる。しかし、完璧な正解はないと思うし、ある程度妥協して完成を見い出ださないと、永遠に時間ばかりが過ぎていく。人生なんてすぐに終わってしまうだろう。特に実際のプロジェクトでは納期が重要。設計に関しては、必要に応じて最適なアーキテクチャーを選択しながら柔軟に考えていけばよいと思う。Bugのない品質のよいものを作り上げるのが一番大事で、次に生産性とか、保守運用性とかの話がくるべき。
 Reflex設計が、そもそもオブジェクト設計をしないというのは、モデリングにかかる膨大な工数を削ることが第一の目的である。Entityだけに着目することで、モデラーの感性の入り込む余地を少なくすると同時に、誰でもサクサク設計できるようにしたい。そのための現実的な設計手法なのである。別に「エセMVC」とか、「貧血症」などと呼んでいただいて結構。でもこのおかげで、モデリングにコダワリをもつ輩も「穀潰し」じゃなくなるわけだから、利用する価値があるかもしれないだろう?

 ということで、MVCモデルは進化する、ってことでいいじゃん、と思う次第である。

<関連>
 MVCモデルは進化する
 Reflex Tagging Serviceについて話します

1 件のコメント:

syou007 さんのコメント...

>ということで、MVCモデルは進化する、ってことでいいじゃん、と思う次第である。
私も同じ意見です。

中島さんのブログから来て、読ませていただきました。
内容が濃くてお勉強になりました。
ありがとうございます。

 
© 2006-2015 Virtual Technology
当サイトではGoogle Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。