タグ: PoEAA

モデルビューコントローラー

注: PoEAA, 14-1: Model-View-Controller をまとただけの記事です

UIの相互作用を3つの明確な役割に分割するパターンを「モデルビューコントローラ」とよぶ。

mvc

ViewとControllerは互いに依存してよい。ViewとControllerはそれぞれ、Modelに依存してよい。

パターンの仕組み

 モデルはUIに関わらないドメインについてのデータやふるまいが表現されたオブジェクト。ビューはUIの中でモデルを表現する。ビューは情報の表示だけを責務として負う。コントローラは、ユーザーからの入力を受け取り、モデルを操作して、ビューを適切に更新する。このようにUIはビューとコントローラの協調によって構成される。

プレゼンテーションとモデルの分離

 根本的にプレゼンテーションとモデルは異なる関心事を持っている。ビューはどのように良いUIを提供するかということに興味があり、モデルはどんなロジックでデータを取り扱おうかということに関心がある。したがって分離を行い、各関心事に応じて構造化するために分離を行う。

 非ビジュアルなオブジェクトは、ビジュアルなオブジェクトよりテストがしやすい。当たり前のことではあるが、プレゼンテーションとモデルを分離することにより、ドメインロジックのテストは容易になる。

 プレゼンテーションはモデルに依存するが、モデルはプレゼンテーションに依存しないようにする。こうすることによりモデルを構成するときに、どんなプレゼンテーションから使われるかということを全く意識しなくてすむようになる。また、これによりモデルを利用して新たなプレゼンテーションを追加することが容易にもなる。

複数のウィンドウを持ったクライアントにおける問題

 複数のウィンドウを持つリッチクライアントでは、あるモデルを参照する複数のプレゼンテーションが同時に表示される可能性がある。その際、ユーザーが1つのプレゼンテーションを更新したら、その変更は伝播されなければならない。モデルがプレゼンテーションに依存を作らずにこのようなことを実現するためには、オブザーバーパターンの実装が必要になる。プレゼンテーションはモデルのオブザーバーとして動作させ、モデルが変化するごとにイベントが発生して、情報が更新されるされる仕組みを実現する必要がある。

ビューとコントローラの分離

 こちらは、プレゼンテーションとモデルの分離に比べると重要度は下がる。例えば、編集可能な振る舞いと編集不可能な振る舞いを同時にサポートをしたいときに、ビューとコントローラを分離したいといったモチベーションが生じる。1つのビューに対して、2つのコントローラを作ることにより対応できるが、通常はそのような分離は行われていない。

 プラットフォームによってはUIにおける入力と出力はしばしば不可分であり、GUIフレームワークではビューとコントローラを組み合わせていることが多い。Webインターフェースではコントローラとビューの分離が行われることが多い。

パターンを用いるタイミング

 モデルビューコントローラは、プレゼンテーションとモデルおよび、ビューとコントローラの分離に特徴がある。前者については非常に重要で、ほとんどの場合、分離をすべきである。後者についてはわりあい重要ではなく、必要なときにだけ分離をすることを推奨する。ネイティブクライアントにおいて、分離することはほとんどないが、ウェブフロントエンドにおいて、ビューとコントローラを分離することは珍しくない。

感想

モデルビューコントローラについては POSA を読まないとダメそうだ。正直PoEAAの説明、わりと雑では?と思ってしまった。あと このあたり を読んでおきたい。

Web Presentationのアーキテクチャ

注: PoEAA, Chapter 4: Web Presentation をまとただけの記事です

 ウェブブラウザベースのユーザーインターフェースには、特別なクライアントソフトウェアをインストールしなくてよい、UIに対して共通のアプローチをすることができる、世界中からのアクセスができるなどのメリットがあります。またウェブアプリケーションは、多くの環境でビルドすることが可能であるということは大きな利点です。

 ウェブサーバーアプリケーションは通常、各URLに対してどのプログラムが対応して処理を行うかを記述した設定ファイルを持ちます。これをもとにウェブサーバーはURLを解釈して、それに紐付いたプログラムに制御を渡します。そしてそのプログラムは動的に結果を生成し、レスポンスを返すなどということを行います。このようなウェブサーバーアプリケーションの構造化には、スクリプトとしての構造化とサーバーページとしての構造化という方法があります。

スクリプト形式

 スクリプト形式のプログラムは、HTTP呼び出しに対して対応する関数やメソッドを呼び出して対応するものになります。CGIスクリプトやJavaサーブレットといったものはスクリプト形式に分類されます。スクリプトはさらに細かく分割することができたり、他のサービスを操作することができます。レスポンスはストリームへの書き込みを行うことで実現します。

サーバーページ形式

 スクリプト形式におけるHTTPレスポンスのストリームへの書き込みは非プログラマにとっては困難であり、プログラマであっても煩わしい作業となります。これを解決する方法として、サーバーページ形式というものがあります。これはHTML形式で書かれたレスポンスページ内に実行可能なスクリプトを記述し、ある時点で実行処理を行うというものになります。PHPやASP、JSPなどがサーバーページ形式に分類されます。そもそもASPは、Active Server Pagesの頭文字、JSPは、JavaServer Pagesの頭文字から来ています。スクリプト形式はリクエストの解釈が簡単に行える点で優れています。また、サーバーページ形式はレスポンスのフォーマットを定める方法として優れています。

レイヤ化アーキテクチャ

注: Patterns of Enterprise Application Architecture, Chapter 1 Layering をまとただけの記事です

 レイヤ化は、複雑なソフトウェアのシステムを分割するために使用される技法です。コンピュータの構造やネットワークなどソフトウェア以外の設計でも使われています。各レイヤはその下のレイヤに依存します。レイヤ3はレイヤ2を利用して、レイヤ2はレイヤ1を利用します。レイヤ化アーキテクチャにおいて最も難しいのは、必要なレイヤと各レイヤが行うべき内容を決定することです。

レイヤ化のメリット

  • 他のレイヤを気にせず、1つのレイヤを全体として考えることができる
  • 同じインターフェースを持つだいたい実装でレイヤを置き換えることができる
  • レイヤ間の依存を最小限にできる
  • レイヤは標準化に適している
  • レイヤを構築することにより、多くの高水準サービスがそのレイヤを使用できるようになる

レイヤ化のデメリット

  • 物事をカプセル化してしまうため、連鎖的な変更が起こる場合がある
  • パフォーマンスを損ねる場合がある

 UI上で表示すべきフィールドの追加が、前者の具体的な例になります。追加されるフィールドに対応するものがデータベース上に存在する必要があります。このためUIからデータベースまでのすべてのレイヤにそのフィールドを追加する必要が生じます。後者についてはパフォーマンス損失以上にトランザクションの制御などの最適化によって得られる恩恵が多いケースもあるので検討が必要です。

レイヤ化の発展

 90年代に登場したクライアント/サーバシステムは2レイヤのシステムでした。クライアントはUIとアプリケーションコードを保持して、サーバーは通常のRDBという構成でした。アプリケーションがRDBの内容の表示と更新といった単純なものであれば適切に動作しましたが、妥当性の検証など複雑なドメインロジックを伴い始めると、たちまち重複コードが増えたり、コードの扱いが難しくなったりする局面がでてきました。そのころオブジェクト指向も注目を集めていて、コミュニティではプレゼンテーション、ドメインロジック、データソースの3レイヤにすることにより、ドメインロジックに関する問題を解決しました。最終的にはWebやJavaの登場により、こうしたやり方が受け入れられ、定着することとなりました。

3つのレイヤ

プレゼンテーションレイヤ

 ユーザとソフトウェアの相互作用を扱うのがこのレイヤの役割になります。ユーザーに情報を表示したり、ユーザーからのコマンドをドメインやデータソースでの動作に変換したりするようなコードがここに含まれます。

ドメインレイヤ

 システムそのものであるロジックを置くレイヤです。ビジネスロジックとも呼ばれます。入力データや格納データに基づく計算や、入力データの妥当性検証、また状況に応じたデータソースの選択などがこのレイヤに含まれます。

データソースレイヤ

 他のシステムとの通信を行い、アプリケーションのためにタスクを実行します。

レイヤ化アーキテクチャとヘキサゴナルアーキテクチャ

 ヘキサゴナルアーキテクチャは、外部システムへのインターフェースで囲まれた核としてシステムを視覚化したものです。外部にあるものはすべて外側のインターフェースとします。よって、ヘキサゴナルアーキテクチャは他への提供するサービスと他のサービスを利用することを区別しない、対称的な構造を持っています。対して、レイヤ化アーキテクチャは、他へのサービスとして提供するインターフェースと、他のサービスを利用することを区別する、非対称的なスキーマになっています。そして、この部分がプレゼンテーションレイヤとデータソースレイヤの違いとなっています。

レイヤリングの方法

 システムの規模によって異なります。単純なものであれば、各レイヤのふるまいをサブルーチンとしてあげるだけで大乗ウブです。より複雑なときにはクラスに分割を行い、さらに複雑な場合には幾つかのパッケージにクラスを分割してあげるということができます。状況によって一番適切な分割をするのが望ましいですが、最低でもサブルーチンレベルでの分割を行う必要はありそうです。

レイヤ間の依存関係

 ドメインとデータソースはプレゼンテーションに依存しないようにします。ドメインとデータソースの関係は複雑なため、データソースのアーキテクチャに応じて考えていく必要がありそうです。

レイヤの実行

 PoEAAの内容のかなりの部分は、論理的なレイヤについて解説したものになっています。システムを分割して、その境界部の結合を減らすことについての説明が書かれています。レイヤの分割は1台の物理マシンで実行していたとしても役に立ちます。しかし実行場所が異なることによって違いがもたらされることもあります。

 クライアント/サーバーなアプリケーションを例にとれば、サーバーですべてを実行すると、アプリケーションの更新は容易になります。一方クライアント側での実行はレスポンスや切断時の操作を考えると優れています。