<< テーブル設計 データモデリングのエッセンス (3) | main | テーブル設計 データモデリングのエッセンス(5) >>

テーブル設計 データモデリングのエッセンス(4)

ビジネスリソース

今回はビジネスリソース系のテーブル設計、データモデリングがテーマです。

ビジネスリソースとは経営の資源です。ビジネスを進めていく上で、利用可能であり、また必要不可欠な企業の財産です。

例えば、ヒト(顧客、従業員、取引先)、モノ(商品、倉庫、店舗)、カネ(資金、与信枠)、情報(コンテンツ、ノウハウ)などです。

ビジネスリソースを適切に管理し効果的に利用するためのテーブル設計、データモデリングが、ビジネスの成功要因、競争優位の源泉になりえます。

ビジネスイベントとの関係

前回まで説明したビジネスイベントは、これらのビジネスリソースとの関連で、発生し、記録します。
・受注は「顧客」が「商品」を注文したイベント
・出荷は「商品」を「倉庫」から「顧客」に発送したイベント

これらの関係を外部キー参照として設計・実装します。

ビジネスリソースの主キー

ビジネスリソースの管理は経営の重大関心ごとですから、業務上の管理番号(Identifier)があるはずです。
私は、テーブルの主キーは、システムで生成したサロゲート(代理)キーを使います。管理番号が変更されるケースとか同じ管理番号複数のレコードが存在するケースを扱うためです。

一方通行の参照(=レイヤ構造)

ビジネスイベントとビジネスリソースの関係は、Domain-Driven Design (DDD) の Responsibility Layers パターンで取り上げられている Operational Layer と Capabilities Layer と同じ関係です。

レイヤ構造ですから、上位のレイヤは下位のレイヤを参照します。下位のレイヤは、上位のレイヤの存在すら知りません。

上位のビジネスイベントはビジネスリソースを外部キー参照します。下位のビジネスリソースは、上位のビジネスイベントを知りません。外部キー参照は不可です。

集約( Aggregates )

ビジネスリソースは、さまざまな属性情報で表現されます。

顧客は、氏名、連絡方法、届先住所、購買履歴など。
取引先は、社名、部署名、担当者、連絡先(電話番号)など。
商品は、商品名、商品概要、特徴、詳細仕様など。

ビジネスリソースは、Domain-Driven Design (DDD) の基本パターンである Aggregates (集約)を適用することが多い。

一つのテーブルにすべての属性を列挙したテーブル設計を見かけます。しかし、テーブルの役割を単純にして、問題を扱いやすくするために、 Aggregates として設計し、実装すべきです。

顧客テーブルのほかに、氏名テーブル、連絡方法テーブル、届先住所テーブルがある。顧客テーブルが全体を集約するAggretate のルートテーブルという構造です。

氏名テーブル、連絡方法テーブル、届先住所テーブルは、DDD の Value Object です。単なる値のリストであり、重複した内容のレコードが存在することもあります。

氏名レコード、連絡方法レコード、届先住所レコードは、顧客テーブルの主キーを参照する外部キー制約で関連づけます。

Aggregates のモデリング方法として「○○変更」という業務の発生を判断材料にします。

連絡方法変更、届先住所変更はありそうですね。こういう変更業務の単位ごとに別テーブルにして、Aggregates パターンとして集約するテーブル設計が良い。

テーブルの数が増えると、複雑に感じる人もいます。しかし、実際にはそれぞれのテーブルに関心を持つ業務は異なります。テーブルとして関心の分離ができているので、業務ごとの設計・開発・テストが単純になり扱いやすくなります。

その業務の切り分けとテーブル分割の一つの判断材料が「○○変更」業務の有無ということです。

ビジネスリソースの登録

Aggregates パターンのテーブル構成だと、新規作成時にすべての情報を登録することは必須ではありません。

情報が発生した時点、明確になった時点で、順次、適切なテーブルにレコードを追加していけばよい。これも関心の分離の設計原則の適用です。

ビジネスリソース情報の変更

まず、内容の変更の前に「○○変更」業務の発生をビジネスイベントとして記録すべきです。誰が、いつ、なぜ、変更したかをビジネスイベント系の別テーブルに記録する。

情報の変更内容は、該当するテーブルに新規作成します。
例えば、届先住所が変更された場合、新しい届先住所のレコードを追加する。

イベント記録と新情報のレコード追加は、1トランザクションにする。

この結果、変更前と変更後の複数のレコードが存在することになります。
ビジネスリソースを参照する多くの業務は最新の状態だけに関心があります。旧レコードは、物理削除してしまうのが単純でわかりやすい方法です。 DDD の Value Object パターンのテーブル設計への応用です。

論理削除フラグを更新して、参照するときには、いつも、そのフラグを検索条件に含める、というのは、面倒なわりには、間違いが多く、メリットが少ない方法だと思います。

データの信頼性や追跡性を確保するためには、

・削除と追加を1トランザクションにする
・削除時にトリガーで、履歴テーブルに、削除内容を記録しておく

などの手法があります。

物理的に削除せず、追加のみにする方法もあります。
この場合は、どの住所レコードが現在有効であるかを示す、現住所テーブルをトリガーで維持します。導出テーブルですね。現住所テーブルは、ドロップしても、オリジナルの届先住所テーブルから、導出可能です。

変更前の情報も必要?

変更前の情報を、参照する業務ニーズをよく検討してください。ビジネスリソースは、通常の業務(オペレーション)では、現在有効な情報のみで十分です。

もし、変更前の情報も参照する業務があるなら、管理番号を新規に発行して、新しいビジネスリソースとして登録すべきです。それが、管理番号の意味だし、ビジネスリソースの管理の正しいやり方のはずです。

ビジネスリソースの利用停止

ビジネスリソースそのものを削除する(ないことにする)、リソースの管理番号を廃番にすることは、通常のビジネスではありません。多くのビジネスイベントの記録から参照されるので、安易に物理削除はできません。

しかし、今後は、この商品は販売停止、受注は不可にする、ということはよくあるケースですね。

この場合、「販売停止」ビジネスイベントをまず別テーブルに記録することが必須です。

論理的には

(全商品 MINUS 販売停止商品)

で、現在、販売可能な商品を特定できます。

実用上は、トリガーを使って、「現在販売可能な商品」テーブルを自動的に維持する方法があります。商品登録時に、トリガーで追加し、販売停止イベント時に、トリガーで削除する。

「現在販売可能な商品」テーブルは、ビジネスルールのテーブルという性格もあります。ビジネスルール系のテーブルについては、次回で説明します。

コメント
ウサと申します。

すみません、ここの記事について教えて頂けませんでしょうか。

「ビジネスリソース情報の変更」の所で、
「物理的に削除せず、追加のみにする方法もあります。」

と、ありますが、それはどのようなケースでしょうか。
考えてみたのですが、

1. 「ビジネスリソーステーブル」と「ビジネスイベントテーブル」を兼ねたい場合
2. レコードの物理削除を、業務の発生していない夜間に行いたい場合

のいずれかの場合でしょうか。
それとも、上記3点とは別のケースなのでしょうか。

仮に2.であった場合、変更履歴を保存しておく為に「変更イベントテーブル」が
必要になると思いますが、1.の場合でも「変更イベントテーブル」を設ける方が
masuda220さん的に、より良い設計となるのでしょうか。

お手数おかけしますが、お考えをお聞かせ頂けませんでしょうか。

よろしくお願いいたします。
  • ウサ
  • 2010/08/27 1:54 PM
ウサさん

自分で書いた記事なのに、ご指摘の箇所、読み直してみると、正直、自分でも意図がよくわかりませんでした。(すみません)

もういちど、自分なりに改めて考えてみました。

意図は、次のようなことなんだと思います。

業務のニーズとして「履歴」情報を使いたい場合、リソーステーブルに変更後のレコードを追加したとき、変更前を削除せずに残しておくというやり方で、実現できる。

「履歴」というニーズをどう設計・実装するか、ということです。

【基本の役割】

私は、ビジネスリソーステーブルと、ビジネスイベントテーブルの基本の役割を、はっきり区別しています。

ビジネスリソーステーブル:
 業務で関心のある情報を格納。
 つまり業務ユーザが「問い合わせたいこと」が詰まったテーブル
 通常は、「最新の情報」を知りたい。

ビジネスイベントテーブル:
 業務上、おきたことの記録。
 アプリケーションからは、基本的に参照しない。
 (監査用や、データ保護のための記録)

【アプリケーションで履歴を扱う】

これが、「物理的に削除せず、追加のみにする方法もあります」の意図だと思います。

住所変更であれば、上記の考え方では、

・リソーステーブルは、最新の住所だけ
・イベントテーブルは、過去の住所も持っているが、アプリケーションからは、参照しない。

となります。

この考え方で設計した時に、業務のニーズとして「履歴」を利用したい、という場合にどうするか?

選択肢は2つ。

A案:イベントテーブルをアプリケーションで利用する
B案:履歴テーブルを別途作成する

私の考えは、B案です。

【監査ログと履歴とは目的が違う】

イベントテーブルは、

・データの不整合が発覚した時の、調査目的
・業務上、不正が起きていないかの調査目的
・最新状況がなんらかの理由でロストした時に、最新状況を導出するためのソースデータ。

など、業務システムの運用管理が目的の情報。
そういう意図で、データを作成し、バックアップや保管期間の戦略を決める。

業務ニーズとして、アプリケーション機能として「履歴」画面がほしい場合とは、ちょっと違う。

業務ニーズでは、たとえば、直近の5件だけが、必要かもしれない。
あるいは、直近の一ヶ月間の履歴があれば十分かもしれない。

つまり、

・業務上、利用したい履歴



・イベントとして記録され、また保管すべき全レコード

と同じではない、というように考えます。
必要なデータは、イベントレコードのサブセットかもしれないが、目的・意味が違う。

イベントの全レコードを検索する、SQL 文(WHERE 句)で、業務ニーズごとの、履歴を動的に抽出することは、もちろん可能です。

正規化したテーブル構成だけにして、導出テーブルは、できたら、持つべきではない、という考え方なら、こうなります。

でも、私は、正規化したテーブル構成にプラスして、必要であれば、導出テーブルを持つほうが、業務モデルの設計・実装として、ベター、という考え方なんです。

コアのデータモデルは、正規化は重要だと思っています。
しかし、業務のデータモデルを設計し、実装する場合、導出テーブルも、同じように、重要だと思っています。

業務上「直近の5件」というニーズがあるなら、直近の5件だけを持つ履歴テーブルがあるほうが、業務を、すなおに、実装していることになるという考え方です。

たとえば、銀行口座の残高というのは、

入金レコード
出金レコード

だけあれば、現在の残高は、SQL 文で、導出可能です。

でも、「残高」を知りたい、という業務のニーズは、データモデルから消えてしまう。

直近5件の履歴も、同じ発想で、イベントテーブルから、SQL で導出は可能だけど、「直近5件の履歴」という業務のニーズは、データモデルからは消えてしまう。

直近5件の履歴がほしいニーズがあるなら、イベントテーブルからSQLで導出するより、「履歴」テーブルが存在したほうが良い。

そのアプリケーション視点の履歴テーブルは、変更発生時の、リソーステーブル側のレコードの作成と削除のコントロールで、維持できる、というような考えです。

この記事を書いていたときに、明確に、こう考えていたかは、さだかではありませんが、今、自分で読み直してみて、自分の考えを整理してみると、

・イベントテーブル (システム監査やデータ管理が目的)
・履歴テーブル (業務で使いたい情報=リソーステーブル系)

  • masuda220
  • 2010/08/27 6:54 PM
コメントする









この記事のトラックバックURL
トラックバック
calendar
   1234
567891011
12131415161718
19202122232425
2627282930  
<< November 2017 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
  • 番号より名前。 ニーモニックコードより名前。 【パターン】
    師子乃 (03/10)
  • Smart UI が優れている?
    masuda220 (03/10)
  • Smart UI が優れている?
    kagehiens (03/09)
  • オブジェクト指向プログラミングの教え方?
    masuda220 (12/05)
  • オブジェクト指向プログラミングの教え方?
    ZACKY (12/04)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    kompiro (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    JHashimoto (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (02/28)
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM