イミュータブルデータモデル(入門編)

24
イミュータブル データモデル (入門編) kawasima

description

更新日時を排除していくことでそこそこのモデルを書けるようになる手法です。

Transcript of イミュータブルデータモデル(入門編)

Page 1: イミュータブルデータモデル(入門編)

イミュータブル データモデル

(入門編)

kawasima

Page 2: イミュータブルデータモデル(入門編)

背景

• 正しくデータモデリングを学んだ人(1NF~5NFの違いがわかる人)がモデルを書くのが理想だが、現実は難しいところもある。

• そういう状況において、モデリングのエキスパートでなくても、致命的な問題を起こしにくいモデルを作るための手法で

す。

Page 3: イミュータブルデータモデル(入門編)

ゴール

• モデルの複雑性を増すのは、CRUDのうちのUPDATEに関する要件です。

• モデルに対するデータの更新を極限まで削ることによって、拡張に対して開いていて、修正に対して閉じている堅牢なものにします。

Page 4: イミュータブルデータモデル(入門編)

イミュータブル?

• 実際にはUPDATE全くなしに業務アプリケーションを作るのはハードル高すぎるので、ミュータブルな箇所を特定し、一定の意味付けをおこないUPDATEを許可する、という文脈です。

• 「更新日時」という属性を徹底的に排除することにより、イミュータブルなモデルの獲得を目指します。

Page 5: イミュータブルデータモデル(入門編)

モデリングの手順

Page 6: イミュータブルデータモデル(入門編)

Step1 エンティティの抽出

発送担当者が受注リストをもとに、商品の在庫を確認し、在庫があれば商品を発送する。

① 要求仕様の「動詞」を抜き出しエンティティとする。 ② ①に関わる「名詞」を抜き出しエンティティとする。 ③ エンティティ間の関連に線を引く ④ 属性や候補キーも分かる範囲で書いておきます。

間違い! この段階で実装をプロパティファイルにするとか、Enumにするとか決め打ちでエンティティとして表さないのはやめましょう。

まず、はじめにエンティティを抽出します。

Page 7: イミュータブルデータモデル(入門編)

エンティティ名の付け方

エンティティの名前は、短くその意味を的確に表現するものでなくてはなりません。なくても意味が通じるワードは使わないようにしましょう。 なくても意味が通じるワード

情報 データ 処理 ~物 マスタ 記録 管理

Page 8: イミュータブルデータモデル(入門編)

ときどき論理設計=日本語名称、物理設計=英語(ローマ字)名称とプロセス定義して、英語名称を付けるのを後工程にまわすプロジェクトがありますが、そんな必要はありません。命名は和名/英名セットでおこないます。 名付けには用語辞書を作って、ある程度機械的におこなうのがよくあるパターンですが、安易に短縮名称を使わないようにしましょう。 母音を抜いて短くする短縮名付け文化圏があるようですが、これを機械的にやるとヒドイ英名が付けられるもとになります。 QUEUE → Q KIKAKU → KKK

論理設計と物理設計

Page 9: イミュータブルデータモデル(入門編)

Step2 エンティティの分類

会員ID

姓 名 郵便番号 住所 電話番号

注文番号

注文会員ID 注文日時

注文 会員

リソース イベント

洗いだしたリソースとイベントに分類します。 基準は属性に”日時” をもつかどうかです。 または、Step1の①の動詞から抜き出したエンティティは“イベント”に、②の名詞から抜き出したエンティティは“リソース”になるはずです。

Page 10: イミュータブルデータモデル(入門編)

エンティティを分類するのに、未だ“マスタ”“トランザクション”というものを使うプロジェクトがありますが、この定義は曖昧で大抵どっちに分類するかでムダな議論のもとになります。

「システムで更新しないものを“マスタ”とします」 「マスタメンテ機能でされるんじゃない?」 「あぁ、マスタメンテ機能での更新はノーカンです」 「日に1回、社員マスタは社員管理システムから送られてきて洗い替えするんだけど」 …

その点、リソース/イベントの分類は非常に明快で迷うところがありません。

マスタ/トランザクションという分類

Page 11: イミュータブルデータモデル(入門編)

Step3 イベントエンティティは1つの日時属性

しかもたないようにする

受付番号

注文会員ID 注文日時 注文確認者 注文確認日 請求書出力フラグ

入金予定日 入金日時 入金者氏名 登録日時 更新日時 キャンセル日時 キャンセル取消日時

発注

注文番号

注文会員ID 注文日時

注文

発送指示ID

発送指示者 発送指示日 注文番号

発送指示

One fact in one place.

Page 12: イミュータブルデータモデル(入門編)

イベント系エンティティは、業務の記録です。すなわちイベント系エンティティに対する更新は、記録の更新、悪いいい方をすれば記録の改ざんになる訳です。 したがって、イベント系エンティティは更新が入らないデータが格納されるものと考えることができます。

業務の“記録” がイベントである

Page 13: イミュータブルデータモデル(入門編)

よく全てのエンティティに一律で登録日時や更新日時を付ける設計ルールを見かけます。あまつさえ、それを自動的に登録してくれるフレームワークもあるようです。 これは何のためにあるのか再考してみましょう。 おそらく最初の動機としては、何か問題があったときにトレースするためと思われますが、リソース系エンティティにつけても1世代の更新しかわかりません。そして更新前の状態もわかりません。本当に問題をトレースしたいのであれば、変更履歴を別のエンティティとして記録するべきです。 一方、イベント系エンティティは登録/変更の日時を属性としてただ1つもつので、同じ意味の属性を別にもたせる必要はありません。

全エンティティに付ける登録日時や更新日時

Page 14: イミュータブルデータモデル(入門編)

都道府県コード

都道府県名 都道府県略名 登録日時 登録者ID 更新日時 更新者ID

思考停止の象徴エンティティ

都道府県にすら、更新日時 Σ(゚д゚lll)

Page 15: イミュータブルデータモデル(入門編)

Step4 リソースに隠された イベントを抽出する

会員ID

姓 名 郵便番号 住所 電話番号

会員

リソースエンティティに更新日時を持たせたくなるのは、リソースにまつわるイベントが洗い出せていないことが原因と考えます。

• 何かトラブル起こった時に原因をトレースするため会員が自分自身で会員情報変更ページから変更する。

• 規約に違反した会員であったため、お客様センターのオペレータが強制退会を行う。

• 会員からの誤った退会をしてしまったが、取り消してほしいとの問合せを受けて、お客様センターのオペレータが会員の復会を行う。

更新日時

Page 16: イミュータブルデータモデル(入門編)

会員ID

姓 名 郵便番号 住所 電話番号

会員

会員変更ID

会員ID 姓 名 郵便番号 住所 電話番号 変更日時 変更イベントID 変更理由

会員変更

大抵の会員を管理するシステムではこういうモデルになるのでは ないでしょうか?

Page 17: イミュータブルデータモデル(入門編)

リソースに対する変更の記録としてのイベント系エンティティは、いわゆる履歴テーブルと言えます。 履歴テーブルの実装には、「これが正解!」といえるものはなく、業務要件などに照らしあわせて設計することになります。 このイミュータブルデータモデリングの手順のように、リソースに対する変更日時を記録したいと思ったら、これをイベントとして切り出すことを考えると、比較的失敗しにくいように思います。

履歴テーブル

Page 18: イミュータブルデータモデル(入門編)

リソースは、イベントによって引き起こされる属性の変化の 一時点でのスナップショットである。

会員ID: 001

姓: Kawashima 名: Yoshitaka 郵便番号: 111-XXXX 住所: 東京都台東区 電話番号: 090-xxx-xxx

会員ID: 001

姓: Kawashima 名: Yoshitaka 郵便番号: 111-XXXX 住所: 東京都台東区 電話番号: 070-xxx-xxx

会員ID: 001

姓: Kawashima 名: Yoshitaka 郵便番号: 167-XXXX 住所: 東京都杉並区 電話番号: 070-xxx-xxx

電話番号変更 住所変更

業務的に計画された更新がない、または更新のイベントをトレースする必要がない、場合に限り、このスナップショットだけを変更イベントをもたないリソースエンティティとして定義される、と考える。

Page 19: イミュータブルデータモデル(入門編)

Step5 非依存リレーションシップを交差エンティティにする

リレーションが非依存である場合、外部キーにNULLを許し、後でアップデートすることが可能になってしまいます。 こうした要求の裏には、別のイベントが隠れていることがあります。

プログラマID

姓 名 プロジェクトID (FK)

プログラマ

プロジェクトID

プロジェクト名

プロジェクト

プログラマは、担当するプロジェクトがなくても、存在しうる。 「アサイン」というリレーションシップが間にあるのでは?

Page 20: イミュータブルデータモデル(入門編)

R-R間の交差エンティティ

社員ID

姓 名 部門ID (FK)

社員

部門ID

部門名

部門

新人が部門に配属されたら部門IDに 値を入れる。

社員ID

姓 名

社員

部門ID

部門名

部門

部門ID 社員ID

配属日

配属

配属イベントが潜んでいる。

Page 21: イミュータブルデータモデル(入門編)

E-E間の交差エンティティ

請求ID

請求日時 請求書宛先 請求金額

受注ID

受注日時 請求ID

受注 請求

請求ID

請求日時 請求書宛先 請求金額

受注ID

受注日時

受注 請求

複数の受注をまとめて請求する。

受注ID 請求ID

受注-請求

対応する請求のデータができたら請求IDに値を入れる。 (時系列の逆転したリレーション)

E-E間の場合は、イベントが潜むのではなく、対応表が必要になる。時系列の逆転が起こらないように設計する。

Page 22: イミュータブルデータモデル(入門編)

交差エンティティは多対多の場合だけのものではない

B A

ER図で、このような形だけみて、「エンティティAとエンティティBは、多対多じゃないんだけどっ!」というカーディナリティだけでリレーションシップを決めてしまう人がいます。 重要なのは、非依存リレーションシップということは、互いに独立に存在しえて、何らかのイベントによって、それらに関係性が作られるという、このイベントが何か洗い出せているか? という点です。 これをやらずに、カーディナリティだけでリレーションシップを考えると、業務上必要だったイベントエンティティを見落としてしまうことに繋がりかねません。

Page 23: イミュータブルデータモデル(入門編)

まとめ

Page 24: イミュータブルデータモデル(入門編)

• 更新日時に着目し、それらをエンティティから追い出すだけで、それなりの堅牢なデータモデルが書けるようになる。

• ただ、これだけでは不十分なところあるので、ちゃんと本を読もう。

佐藤正美(2005) 『データベース設計論 T字型ER』 羽生章洋(2006) 『楽々ERDレッスン』