MVCとオブジェクト指向(2)

id:EnogunoCap様から頂いたコメントに返信するように、この話題の続きです。
もっぱら、自分の個人的な解釈を書く事になるとは思うのですが、ご容赦を。ちょうど自分も5年くらい前、初めてMVCモデルで実装されたFrameworkを触った際は、しっちゃかめっちゃかでしたので、話題は全然他人事じゃないです。


ControllerとModelの区別は、実は意外に難しいと思ってます。Modelの解釈が人によって変わってしまう為です。


TransactionScriptによる実装を考えた場合、このModelは単純なDaoになります。となると、DaoのコントロールはControllerが行わなくてはならない為、結果的にControllerとして定義されたモジュールはServiceメソッドとして業務ロジックをごっそり持つ事になります。

反面、DomainModelによる実装をした場合、業務ロジックは全てDomainModelに乗せなくてはならなくなりますので、Controllerは純粋なイベント・ハンドラとしての役割しか持たなくなります。Modelからデータ・アクセスをする為のDaoは別途定義され、Controller-Model-Daoという流れでサービスが実装されます。


もうお気づきかと思いますが、Modelという概念の使い方によって、Modelの役割が全然変わってしまいます。TransactionScriptを用いた場合のModel層の役割は、単なるDaoでした。しかし、DomainModelでのModelは業務ロジックを具象化したものです。

そして一番混乱を生んでいる原因だと思っているのですが、Daoは実はModelではなくControllerです。

Daoはデータを扱う事から、しばしばデータ構造と同等に扱われがちなのですが、あくまでデータを永続化させる、または永続化されたデータを参照する為の制御モジュールです。

  • バウンダリ(画面とかUI。)
  • コントローラ(UIからのイベントをハンドリングする)
  • サービス(コントローラから対応するユースケースを実現する)
  • エンティティ(業務ロジックを実装する)
  • Dao(コントローラ・サービスと経て渡された入力値を永続化する)
  • 永続化オブジェクト(永続化されたデータを表現する)

DomainModel風に機能をレイヤリングすると、こうなります。(ロバストネス図を描けば済みそうなんですが、なんかめんどくさいのでまた今度)
TransactionScriptの場合、上記のレイヤのうち、コントローラ・サービスをControllerとして実装し、Daoと永続化オブジェクトがModelとして実装されます。DomainModelの場合は、コントローラ・サービス・Daoをそれぞれ独立したControllerとして実装しないと、エンティティとの境界が曖昧になったり、エンティティに実装すべき役割が他のレイヤに流出してドメイン貧血を起こしたりします。


このように結果的なモデルが乖離するものを一括りにMVCと認識させる為には、ModelとしてControllerとして捉える条件を事前にしっかり決めて(=設計して)おかないと、id:EnogunoCap様が書かれていた通り次工程の人が混乱します。というか、混乱しないわけがないです。
中には、どんなにアーキテクチャに関する設計書、仕様書、概要書、利用手順書を用意しても、片っ端からルールを無視していくデストロイヤーな人もいますので、そういった人間へのリスク・マネジメントも含めて、手順というレールを敷設できる人がいないとなかなか難しいですよ。

まぁ、このへんは表題とはあまり無関係ですけど。


id:EnogunoCap様の事例は、まさしくこれだったのではないか、と思ったりします。