kbigwheelのプログラミング・ソフトウェア技術系ブログ

プログラミング・ソフトウェア技術系のことを書きます

PofEAA感想 9章~13章

第9章

P123

ドメインモデルっていろいろ曲解誤解されがちだけど、基本的にはデータとメソッド(振る舞い)を同じものに持たせるという古典的なオブジェクト指向そのものなんだよな。 トランザクションスクリプトやテーブルモジュールなんてものがむしろ基本的なオブジェクト指向の考えに反しているだけで。

~さらに継承が使われるのである。

現代のモダンな言語では継承は使いたくないなあ。

読んでいて思ったけど、近年の言語ではデータとメソッドとの区別が非常に曖昧になりつつある(RubyしかりScalaしかり)。 もはやオブジェクト指向定義上の「オブジェクトとはデータと振る舞い(メソッド)を持つ」というのは古くて、 内部状態としてのデータと外部インターフェイスとしてのメソッドを持つ、といった表現のほうがよりモダンなんじゃなかろうか。

P128

ドメインモデルで共通して見られるのは、複数のクラスが最もシンプルなタスクでも相互作用する方法である。この方法では、オブジェクト指向プログラムで膨大な時間を掛けてクラスからクラスへと探し続けなくてはならないというストレスを引き起こすことがある。

わかる。 ただドメインモデルのためにその欠点を飲んでやるってことは、長期的・より発展的な開発ではメリットがあっても短期的にはむしろトランザクションスクリプトでオブジェクトを活用せずprimitive型とarray、あと関数のみで書いたようなひどくシンプルなものののほうがわかりやすくなるっていうのが逆説的にはっきりした。

(意訳)ドメインモデル、というよりより純粋なオブジェクト指向は分岐をなくす

たしかに。

P 134

anEmployeeModule.getAddress(long employeeID)

テーブルモジュール、今まで1テーブルを1オブジェクトに紐付けると書いてあって訳し間違いか解釈の違いかと思ったら本当にそうだったのか! 複数レコードの集合としてクラスを定義するのはアリだとしてもそれは1レコードに対して1オブジェクトを対応付けた後のオブジェクト集合としての立ち位置が本筋で、集合の方のみをオブジェクトとするのはナンセンスな気がする。 これは現代ではまったく主流じゃないし、アクティブレコードすら1レコード1オブジェクトを返している。これは詳しく読まなくても良いかもなあ。

9.4

ここら辺のサービスレイヤの話はかなり眉唾。 DBやビジネスロジックなどのより具体的なレイヤーわけ理由がサービスレイヤにはない気がする。 アイデアとしてはありなのかもしれないが実態としてはエンジニアそれぞれが自分のサービスレイヤ定義を持ち始めて収集がつかなくなるリスクのほうが高い。 私はできるかぎりサービスレイヤの定義・利用は避けたい。

9.4.2

(意訳)クライアントが1種類で、リクエストレスポンス上で複数のトランザクションが絡んでいない場合は不要。 言い換えると複数の種類のクライアントをサポートしたい場合のみ利用するべき

だよなあ。ただしこの記述に反してサービスレイヤは乱用されている気がする。

第10章

テーブルモジュール、だいぶイメージがわかってきた。.NETで顕著らしいがUIのカラムビューでそのまま表示できるように、複数レコードをそのままアプリケーション内で長く持ち運ぶような環境だとよいっぽい。 でも実質的に.NET専用なんじゃないかなと思う。

今更だけど、この使用するタイミングって節死ぬほど大切だな。ここをちゃんとチェックすれば誤用を避けられるし変な使い方をしている人やシステムに対してこれをproofとして反論できる。

(意訳) 行データゲートウェイとアクティブレコードの違いは前者はオブジェクトにドメインロジックが含まれないが後者は含まれる

なるほど、これで行データゲートウェイが完全にイメージできた。

P170

Active Record uses the most obvious approach, putting data access logic in the domain object.

アクティブレコードはこれを使ってデータアクセスロジックをドメインオブジェクトに配置する。

これも相当やばい翻訳。 正しくは以下。

アクティブレコードはドメインオブジェクト内にデータへアクセスするロジックを置くという最も明快な方法を使う。

ここはてなブログが経過を消しやがって10ページほど記述なし

P183

一意性マッパー、やはりプログラム内でのここのテーブルに紐付けられたキャッシュ層か。 これはアプリケーションサーバが水平展開されるとまったく使えないテクニックなので基本スキップしていいかな。 この層をredisやmemcacheと言った揮発性の共有できる永続化層にて行う方法もあるが、そこまでやるならクエリベースでキャッシュするほうがシンプルそう。

一意マッピングはDBへクエリを投げるオーバーヘッドが期待より大きく、よっぽどパフォーマンスを最適化しないといけないケースでは選択肢の一つとなりえるかもしれない。それでもクエリベースのほうが良いような気はするが。何よりサーバが複数になると矛盾が発生するのが良くない。

第11章

なるほど、ユニットオブワークは単なる登録所、文字通り作業単位としてドメインオブジェクトを登録しておいてプログラムからのコミット呼び出しで登録されていたオブジェクトすべてに対してcommitを発信するのね。

登録時と比較して更新がなかったオブジェクトはSQL送らなくて良いとか書いてあるけど細かすぎる最適化の気がする。 おまけにオブジェクトが変わったかどうかでSQL発行されるかされないか変わるとなると挙動が複雑でよくわからないバグの温床になる。

これってtransactionとほぼ昨日同じでは?外部永続化装置がRDBMSのみならユニットオブワークを使う意味なさそうだな。

11.3 レイジーロード

ちょっとよくわからないものもある。レイジーイニシャライズとゴースト以外は具体的にイメージがわかない。 レイジーロード自体テクニックとしては重要だが必ずしも毎回使うわけではないのでレイジーイニシャライズ以外のテクニックはほとんど使わないんじゃないかと思う。レイジーロードをまとめる手法などはやりすぎだ。こんなものを使う前にオブジェクトの構造を見直したほうが良い。

レイジーロードの追加は、プログラムが若干複雑になるため、私としては本当に必要なとこき以外はあまり使いたくない。

禿同

P235

キーテーブル、こういった手法を見たことがある気がする。java用のスキーマ管理ツールやSCT・DMSなどでこういったものがあったよね。

第12章 オブジェクトリレーショナル構造パターン

この章、オブジェクト(レコード)間の相互参照をどうRDBMSオブジェクト指向言語の間で変換するかって話なのね。 オブジェクト指向言語ではひどく単純に参照元に参照先のポインタを保存するメンバー変数を用意するけど、リレーショナル・データベースでは1対多や多対多のケースで素直には行かない。 なのでRDBMSオブジェクト指向言語プログラミングの間では関係性をうまくマッピングしてやる必要があると。

12.5 依存マッピング

DDD本にエンティティ単位のオブジェクトグラフのアイデア(エンティティだっけ?)があった気がするけど、その単位でDBから読み出し/書き出す話。 根っこのドメインクラスにしかマッピング機構を持たないというのは自然だがたしかに良い方法。

12.6 シリアライズLOB

パフォーマンスクリティカルでもない限りそうそう使わない。だが文中でXMLならいいとこ取りできると言っていることは今ならJSONカラムがよりスマートに解決している。

レポート用

以前もレポート目的という記述があったが具体的にそれが何を指すかはまだ出てきてない。 さっさと実態を知りたいが、索引に載っている?

12.6~9 シングルテーブル継承、クラステーブル継承、具象テーブル継承

全部継承を使う前提なので基本悪手。オブジェクト指向の論理をRDBMSに持ち込もうとしているので簡単な部分ではうまく行くが問題が複雑になればなるほど歪みが増え、やがて破綻する。 そして僕らの仕事で簡単なことをできるケースはまれ。

第13章 オブジェクトリレーショナルメタデータマッピングパターン

メタデータマッピング、scalikejdbcだとcase class周りな感じか。 ただメタデータというメタデータは実際にないよね。scalaは表現力が高めなので内部DSLでなんとかできると解釈するか。

13.2 クエリオブジェクト

scalaの内部DSLSQLクエリを直接書くのではなくオブジェクトとメソッドの呼び出しで擬似的にSQLクエリを組み立てるテクニック。C#にもこういうのあったよな。

13.3 リポジトリ

ここの記述ではクエリオブジェクトを使うこと前提みたいに書いてあるけど、単純にエンティティツリーとRDBMSを直接紐付けるだけのレイヤーでもいいんじゃないかな。むしろクエリオブジェクトをわざわざ作るのはイケていない気がする。