Slideshow transcript
Slide 1: CatalystCon#1 Catalyst から Model を切り 離せ - MVC の M のあるべき姿 - Dann techmemo@gmail.com 1
Slide 2: CatalystCon#1 アジェンダ WAF における MVC と WAF と M の関 係 Catalyst(WAF) から M を切り離す方法 MVC の M を構築するためのアーキテク チャ 2
Slide 3: CatalystCon#1 WAF における MVC と WAF と M の関係 3
Slide 4: CatalystCon#1 WAF の役割 WAF は基本的に Web/Http の世界の仕事をす る セッション管理 認証処理 URL ディスパッチャ フォームバリデーション Controller としての役割 M と V のノリとしての役割 モデルへ処理の委譲 モデルの処理結果を View にフォワード 4
Slide 5: CatalystCon#1 WAF の役割でないこと モデルの管理 モデルのビジネスロジック モデルの Caching の機構 Etc.. Catalyst で良くない点 Catalyst::Model::* M が Catalyst に依存している Model をプラガブルに拡張するのは、 AF の役割 5
Slide 6: CatalystCon#1 WAF と Model の関係のあるべき姿 は? 基本は、 Model は Web の世界からは 切り離されていること MVC の M は POPO(Plain Old Perl Object) で構成する Why ? 6
Slide 7: CatalystCon#1 M を WAF から切り離すべき理由 Testability が向上する モデルの Unit Test が Catalyst を使わずに可能に テストの実行速度が早くなる Web のコンテキスト以外での再利用が可能になる Catalyst::Controller M POPO POPO Model CLI Service (Schema::* など ) (App::CLI, App::Cmd) WebAPI (Catalyst::Controller::Resources) 7
Slide 8: CatalystCon#1 とはいっても、 WAF では一部 M を知る必要がある。 どうするか? 8
Slide 9: CatalystCon#1 Catalyst(VC) と Model(M) の関係別の Model の切り離し 方 9
Slide 10: CatalystCon#1 M と VC の機能の共有関係 (a) M と VC 間に機能共有が必要でない場合 (b) M,V,C の全てで共有したい機能がある場合 Ex) 国際化の機構( Controller 、 View 、 POPO Model どこでも必要) ( c ) V, C の一部で M が必要な場合 Ex) 認証の機構 M のロジックはいらないが、データは必要 このパターン別に、モデルの切り離し方、 VC との繋ぎ方 10
Slide 11: CatalystCon#1 (a) M でしか必要のない機能の場 合 モデルの切り離し方 Catalyst の Model にせず、 POPO だけを使う V Catalyst View C M Catalyst POPO POPO Model Controller Service 11
Slide 12: CatalystCon#1 (b) WAF と APP( モデル ) で機能 を共有したい場合 例えば国際化 V でも C でも国際化したい e.g (c.loc) M でも国際化したい eg. loc(‘message’) モデルの切り離し方 アプリケーション (POPO Model) 側で共通の機能 ( 国際 化)を実装し、プラグインでアプリケーションの機能を参 照する Plugin::I18N --> MyApp::I18N 国際化方法 POPO Model(MyApp::Model::Hoge) からは MyApp::I18N で国際化 . E.g) loc View では、 Plugin::I18N で国際化 . E.g) c.loc 12
Slide 13: CatalystCon#1 (b) のパターン V Catalyst View C M Catalyst POPO Model Controller Catalyst MyApp::I18N Plugin::I18Nx 13
Slide 14: CatalystCon#1 (c) WAF の一部でモデル が必要な場合 例えば、認証の機構 プラグイン側では認証の仕組みが必要で一部モデ ルが必要。モデル側では認証の仕組みは不要とい うケース。 ユーザークラスは Catalyst のモデルじゃないと Catalyst の Plugin から参照が… モデルの切り離し方 Catalyst(WAF) の世界にモデルを閉じ込めるのが いい Catalyst::Model::Adaptor が最適 14
Slide 15: CatalystCon#1 (c) のパターン M Catalyst::Plugin::Authentication POPO User ::Store::DBIC Catalyst ::Model::Adaptor 15
Slide 16: CatalystCon#1 MVC の M を構築する アーキテクチャ 16
Slide 17: CatalystCon#1 Domain Logic Patterns Domain Model(+Service Layer) Service(workflow logic) Domain Model(domain logic) Logic とデータは同じところに ask ではなく、 tell. Transaction Script Unit of Work が 1 メソッド Logic とデータの分離 Ask のモデル Table Module ※ 詳しくは PofEAA 参 17 照
Slide 18: CatalystCon#1 Service Layer + Domain Model 「モデル」を Service と Domain Model に 分ける Service Layer Application logic(Workflow logic) Domain Model に対して問題を解決するよう処理を委 譲 Publish するインターフェースの明示 Controller に見せる処理の明示 トランザクション境界 Domain Model Domain logic 問題領域のロジックは Domain Model に ここに主にロジックを記述 18
Slide 19: CatalystCon#1 多くの Web アプリケーション における一つの仮定 複雑なビジネスロジックは少ない CRUD の処理をすることのほうが多い CLI が管理用スクリプトとして必要になるケースは 多い 重い処理を Job Queue に委譲することは割にある 19
Slide 20: CatalystCon#1 仮定に基づいた Domain model と Service Layer への疑問 DB の構造を見せないリッチな OO なドメインモ デルが必要? 多くの場合不要。無駄に Domain Model をラップする ことになる DB だけの場合、 Domain Model=ER モデル で十分 ドメインモデルでは、 DB に依存しない抽象化が 必要 ? DB しか使わなければ、抽象化不要 常に Controller は Service Layer を介する必要 あり? そんなことはない。直接 Domain Model を触ってもよ い。 20
Slide 21: CatalystCon#1 Service Layer + Domain Model の現実解 Service アプリケーションロジック ( ワークフローロジック)を 書く 複数のモデルにまたがるロジック 複数のモデルへ処理をディスパッチする薄いロジック サービスは基本的に 1 ユースケースに対応させる Domain Model ドメインロジックを記述する DB のみの場合 一つのテーブル (Schema::X) に依存したビジネスロジック Domain Model= ER モデル とする Controller は、 Service or Model にアクセス Controller にはロジックは記述しない ユースケースが CRUD のみのオペレーションに対応する 場合、 Domain Model のロジックに直接アクセスしても21
Slide 22: CatalystCon#1 Catalyst にマッピングすると Catalyst View M Catalyst POPO POPO Models POPO Models Controller Service (With DBIC) (With DBIC) これが一番シンプルなマッピング モデルに対する要求は他にもあり、他のマッピング方法 もある 22
Slide 23: CatalystCon#1 モデル( Service+Domain Model) を構築するための色々な要求 POPO モデル毎に簡単な設定情報を渡したい POPO モデルを簡単に WAF から参照したい $c->model() でのアクセスはなんだかんだで便 利(インスタンス生成のロジックが隠蔽されてる から) モデルと WAF を簡単に繋ぎたい POPO モデル間の密な依存関係を断ち切りた い Testability 向上のため DI コンテナ を使ってモデルを切り 23
Slide 24: CatalystCon#1 DI コンテナ + POPO Model のアーキテクチャ Plugin or Controller で DI コンテナ を参照し、 WAF と M を繋ぐ Catalyst View Catalyst POPO POPO Model Controller Service (Schema::* など参照 ) DI コンテナで Catalyst DI コンテナ POPO を Wiring Plugin 24
Slide 25: CatalystCon#1 DI コンテナを利用したモデル構 築 DI コンテナ利用の利点 モデルは DI コンテナで Wiring されるため、モデ ルが Catalyst の context に依存することが無く なる モデル間の実装の依存関係が切れる モデル (Service, Model) の参照方法の一例 Controller から直に DI コンテナを参照する $self->model(“Service::Blog”)->create(); プラグイン化して Context から DI コンテナを参 照する $c->pmodel(“Service::Blog”)->hello(); Catalyst::Model::Adaptor じゃできない? Catalyst::Model::Adaptor では、 POPO Model 25
Slide 26: CatalystCon#1 まとめ Catalyst は WAF としては必要十分 モデル (Service, Domain Model) について モデルは WAF から切り離すべき ビジネスロジックはモデルに押し込む MVC を考えるときは、モデルの Testability を中 心に考える モデルのアーキテクチャについて Web アプリケーションの多くは、 ServiceLayer + Domain Model の変形でよいのでは Catalyst に不足しているもの WAF と POPO Model を繋ぐ仕組み DI コンテナはそれに対する一つの答え MVC の M の拡張などは WAF ではなく、 AF で 26
Slide 27: CatalystCon#1 ご清聴ありがとうございまし た! 27
Slide 28: CatalystCon#1 付録 28
Slide 29: CatalystCon#1 Service Layer+Domain Model の構築に必要な仕組み (Application Framework としての仕組み) モデルを Wiring ・設定情報を Inject する仕 組み DI コンテナ (Bread::Board. あと一歩 ) モデルの横断的な関心ごとを切り離す仕組み Caching, Transaction など Moose or Class::Trigger or Attribute で拡張 モデルをプラガブルに拡張する仕組み Class::Component 29
Slide 30: CatalystCon#1 モデルを Catalyst から 切り離すのに実装が必要なもの ConfigLoader Logger Caching Exception I18N の仕組み 30




Add a comment on Slide 1
If you have a SlideShare account, login to comment; else you can comment as a guest- Favorites & Groups
Showing 1-50 of 2 (more)