ひがさんのBlogのまとめサイト (6)
wikiroom.com 閉鎖
を読んで勉強するシリーズ第6弾
業務ロジック層
Statelessでやる場合は、実装クラスの生成やDIは、DIContainerがすべて面倒を見てくれます。
こう考えていくと、プレゼンテーション層から最初に呼び出されるクラスは、Statelessにすべきだと思います。その後は、
- 状態をドメインオブジェクトに変換して、ドメインオブジェクトのメソッドを呼び出すドメインモデルと
- 状態をDTOとして、業務ロジック層でそのまま処理するリッチな業務ロジックモデルの2パターンに分かれると思います。
ざっくりと勝手にまとめると↓。
- Stateless: インスタンス変数を使わないクラス
- Stateful: インスタンス変数に状態を保持して、メソッド呼び出しでその値が変更になるクラス
- Statelessであればスレッドセーフなので、Webアプリにはちょうど良い
追記:これは、「データと振る舞いは常に分離した方が良い」ということではありません。業務ロジックは、データよりは、業務機能の方においた方が良いと思うということです。複数の業務機能で、同じデータを使うことは良くありますが、ロジックは、業務機能ごとに異なる場合が多いでしょう。
業務系アプリという限定ドメインでの1つのパターンだということで理解。
DIの本質
DIの本質は、仕様と実装を分離することです。コンポーネントの利用者は、仕様を知っていれば、実装は気にする必要がありません。
2004-11-07 - ひがやすを blog
くーすリファレンス実装
ついに発見!リファレンス実装!
つか、ダウンロードしてあるけどあまり見てなかった…。
S2JSF EA2で出てくるExampleは、くーすのリファレンスモデルにかなり近くなってます。最も応用が利くだろうと思われるマスターメンテ系の画面構成(検索条件入力、検索結果一覧、編集、確認)になっています。
2004-11-13 - ひがやすを blog
DTO
DTOはデータ転送オブジェクト(Data Transfer Objects)と呼ばれています。重たいリモートコールを使ったデータの移行が目的だからです。このインターフェースはパフォーマンスのために粗く作られたリモートインターフェースです。ローカルコールでは使う必要はありません。粗いAPIは使うのが難しいですし、ドメインやデータソース層からDTOにデータを移す作業をすべて自分で行わなければなりませんから。
Martin Fowler's Bliki in Japanese - ローカルDTO
むう。Fowler氏の意味するDTOをはじめて理解した。リモートコールありき、ですか。
DTOのようなものを使うとよいのは、プレゼンテーション層のモデルとドメインモデルとの間に大きなミスマッチがある場合です。
Martin Fowler's Bliki in Japanese - ローカルDTO(同)
くーすではこの場合に該当するわけだ。
PresentationModel=(リモートコールの文脈ではないという意味で)ローカルDTO。
なるほど。すっきり理解できた。
そこで私が主張するのは、RDBMS<->ドメインオブジェクト<->DTOではなく、直接、RDBMS<->DTOしてしまえというものです。これなら、ドメインオブジェクトとDTOの相互変換のコストはかかりません。業務ロジックは、Statelessな業務ロジック層(サービス層)にもたせます。
2004-12-07 - ひがやすを blog
この構成は非常にわかりやすい。イメージしやすいし、実際に実装しやすい。
でも、
DTOをこのように使うときに重要なポイントがあります。DTOはエンティティ(ドメインオブジェクト)を継承するということです。DTOの構造をプレゼンテーション層の都合のみで考えると、同じような業務ロジックが分散する危険があります。
2004-12-07 - ひがやすを blog(同)
が、ちょっとよく理解できないです。
エンティティを継承すると何がうれしいんでしょう?
「同じような業務ロジックが分散する危険が」とあるので、DTOもそのまま業務ロジックの引数に渡すことが前提になっているんでしょうか。
だとしたら、話は通じるか。
第4回で
こう考えるとエンティティって結局何をするために存在するんでしょ?
前の記事で「振る舞いを持たない」ってあったし。
と書いたけど、それはどうなったのか?
複数のエンティティに関連する振る舞いがある以上、どのエンティティがどの振る舞いを持つかという話は、あいまいであり、人によってまちまちになります。
このようにあいまいになるんだったら、業務機能に振る舞いを持たせるという風に決めてしまえば、あいまいさはなくなり、保守も容易になります。
データ(状態)はDTOが持っていますから、業務機能の振る舞いを持つクラス(業務ロジッククラス)は、自然とStatelessになるのです。
DTOと振る舞い
あれ?やっぱりエンティティには振る舞いは持たないのか。
ということは、DTO(=プレゼンテーションモデル)とエンティティの違いは、単なるデータ構成だけってことになる。ホント?それだけの理由でほとんど同じようなオブジェクトを使い分けるメリットがあるんでしょうか。
あれか。
ビューでマスタデータとプルダウン項目用の情報が必要な場合、画面に対応したアクションクラスから、業務ロジックを1つ実行した結果としてそれらが一緒くたに詰まったDTOが返ってくる、と。そういうイメージ?
でも、それだとDAO一発でDTOが取得できる、というわけにはいかないような。
やっぱりRDBMS→エンティティ×N→DTO×1という変換が必要になってしまうな。
うーん。またわからんくなってきた。悩んでるよりS2JSFのリファレンス実装を見たほうがいいのかなぁ。
ちょっとまとめると、くーす的には
- エンティティは状態だけを持ち、振る舞いは外部(業務ロジック)に持つ。
- エンティティは外部リソースに永続化される。DTOはされない。
つーことは、あれか。エンティティはDAOにお願いすると永続化できるけど、DTOはDAOに渡せない?でもエンティティを継承するんならDAOに渡せるよね?
ますますわからん。
DTOとかエンティティとか用語を使いわけるからわからなくなるのかな。
- 状態、データは単にValueObject(Fowler氏が嫌がる方の意味で)に持たせよう
- このValueObject活動場所は全層だ
- いちいちプレゼンテーション層で別の構成にしない
そう割り切ればすっきりする気もするんだけど。
ん。でもそれって(振る舞いを持たない)エンティティをプレゼンテーション層でも使おうよ、ということと何にも変わらないな。ひがさんは明確にそれを否定してたし。違うか。
やはりわからん。(ループ)
正解が1つではないのはまったく持ってその通りでそれはわかるんだけど、どういう実装構成を想定してこういった表現がなされるのかが理解できないのが気持ち悪いところなんですね。バックグラウンドを知らずして深い意思の疎通は難しいわけで。
型を知らずして型からの逸脱はなし。守・破・離。
まあ四の五の言わずにリファレンス実装見ろと。
リッチな業務ロジック層とDTOパターンは、すべての層をDTOが流れていくパターンで、DAOがDTOを直接永続化します。業務ロジックは、業務ロジック層に置かれます。
2004-12-20 - ひがやすを blog
あ、やっぱりDTOも直接永続化するんですか。そうですか。
また、多くの場合、プレゼンテーション層のモデルとドメインモデルには、ギャップがあります。例えば、コードと名称を汎用コードテーブルで管理しているとしましょう。ドメインモデルに汎用コードテーブルへの関連を持たすのは、違和感がないでしょうか。
2004-12-20 - ひがやすを blog
その程度のギャップだとあまり違和感がないような…。
自分の経験不足を露呈しているだけなのかもしれない…。
めげずにもう一回頭の中を整理。
DAOからDTOを直接もらう場合というのは、
- create/update/deleteする必要がない単なる表示データをプレゼンテーション層に渡すとき
- CRUD操作が必要なデータではあるが、単に画面表示用にプレゼンテーション層に渡せばいいだけという場面のとき (マスタメンテ閲覧とか?)
かな。
前者の場合、エンティティは不要で単にDTOだけがあれば良いですね。
後者の場合、内部でCRUD操作を含む業務ロジックで使うためにエンティティがまずありきで、あとプレゼンテーション層用にエンティティを継承したDTOを作成する。
エンティティを継承しているがゆえに、
- CRUD操作Logicに直接渡すこともできる
- (もしあれば)エンティティが持つ振る舞いを実行することもできる
- 業務ロジックに依存しないsetter/getterに毛が生えた程度の振る舞いにしといた方がくーす的には良さそう。
というメリットがある。
と整理すればDTOの位置づけは見えてくる。
で、エンティティは原則、業務ロジックの裏側で業務ロジックによって使われる。
- 業務ロジックはプレゼンテーション層から「○○番号」とかの主キー的情報やDTOそのものを受けとる。
- 業務ロジックは受け取った情報を元にエンティティを生成する。
- 業務ロジックは実行結果としてのエンティティをDTOに変換して、プレゼンテーション層に返す。
こういう使い分けですかね。なんかすっきりしたかも。