『システム開発・刷新のためのデータモデル大全』 要点まとめ
『システム開発・刷新のためのデータモデル大全』(ISBN-10:4534057776) を読んだ。
自分にとって役立ちそうな箇所をまとめる。
(この本独自のER図はテキストまたはdraw.ioで再現する)
第1章 『かね玄』のデータモデル
物理フィールドと論理フィールド
- 物理フィールド: 永続化される物理的な値を持つフィールド
- 論理フィールド: 他の物理フィールドや論理フィールドから導出するフィールド。導出フィールドともいう
- 例: 取引年月(論理フィールド)=関連する取引見出しの取引日(物理フィールド)から算出
テーブル関連と多重度
この本では「1:多(0以上)」を以下2つに分けている。
- 親子関係: 「多」側の主キーが「1」側の主キーを部分的に含む。この本のER図の表記では「∈」
- 参照関係: 「多」側の主キーが「1」側の主キーを含まない。「1」側の主キーは「多」側において単なる属性。「1」側を参照先、「多」側を参照元という。この本のER図の表記では「⋯」
例は以下。
親子関係の例
`取引見出しテーブル`(主キー{伝票番号}, ⋯)
+
┗----∈`取引明細テーブル`(主キー{伝票番号, 行番}, ⋯)
参照関係の例
`商品テーブル`(主キー{商品名}, ⋯)
+
┗----⋯`取引明細テーブル`(主キー{伝票番号, 行番}, 商品名, ⋯)
主キーの特性として「ユニーク制約」と「更新不可制約」がある。
親子関係では、主キーは更新不可なので、一度設定したレコード間の親子関係は変化しない。
参照関係では、属性を更新可能なので、レコード間の参照関係を変化させられる。
第2章 主キーの重要性
派生関係
この本では「1:1または0」の関係を「派生関係」という
派生関係の例
┏+ `取引先属性テーブル`(主キー{取引先ID}, 取引先名, 所在地, ⋯)
┗o+`得意先属性テーブル`(主キー{得意先ID}, 入金サイト, ⋯)
┗o+`仕入先属性テーブル`(主キー{仕入先ID}, 振込先口座, ⋯)
入金サイトは取引先IDに関数従属するが、「取引先が得意先でもある場合」に限る。
このような条件付き関数従属に基づく関連を「派生関係」という。
主キーのフィールド名は異なるが、同一の値。このようにしたほうが実務上扱いやすいためとのこと。
データモデルの基本的なトポロジー
親子関係、参照関係、派生関係の3種類をデータモデルの基本的なトポロジーと呼ぶ。
どんな複雑でもこれらを組み合わせたものでしかない。
第3章 正規化と正規化崩し
スナップショット属性
スナップショット属性 = その時点での値を保持する。過去の取引データを分析・集計する際などに便利。
スナップショット属性であればその旨を注釈するか、 「仕入時品種区分」のようなフィールド名にするべき。
正規化のための3つのルール
(1) 入れ子構造の排除
内部構造の排除
例: 商品コードの1~2桁目が「商品区分」で、3~4桁目が「荷姿区分」
対処法: 独立したフィールドに分割
繰り返し構造の排除
例:
`Aテーブル`(主キー{a}, b, c, d1, e1, d2, e2, d3, e3, d4, e4)
対処法:
`A見出しテーブル`(主キー{a}, b, c)
+
┗----∈`A明細テーブル`(主キー{a, 行番}, d, e)
※ただし、繰り返し回数が十分に少なければ許容されると考えて構わないとのこと
(2) 不要な関数従属性の排除
「推移的関数従属性」をフィールドに含めないこと。
「成立すべきでない関数従属性」を含めないこと。
「推移的関数従属性」の例
スナップショット属性以外で、「参照元(子)」に「参照先(親)」の属性を二重に置かないこと。
値が二重管理され、矛盾した状態が生じ得る。
(3) 有効な識別子の網羅
主キーには「意味のある値の一覧が保持される」という役割がある。これを「定義域制約」という。
「有効な定義域制約に対してテーブルが用意されているか」、
また「無意味な定義域制約を規定するテーブルが盛り込まれていないか」注意する。
例:
「機械と工程と品種の有効な組み合わせ」が決まっている。
それに加え、「機械と工程の有効な組み合わせ」の制約も存在している場合、
以下の様な機械工程テーブル
が必要になる。
`機械テーブル`(主キー{機械No})
`工程テーブル`(主キー{工程C})
+
┗----∈`機械工程テーブル`(主キー{機械No, 工程C})
+
┗----∈`機械工程扱い品種テーブル`(主キー{機械No, 工程C, 品種C})
正規化崩しの3パターン
(1) 論理フィールドの物理化
性能のための正規化崩し。各テーブルに膨大なレコードが保持されているような場合に検討する。
- 例1: 検索操作時の結合を避けるために、「参照先(親)」テーブルのフィールドを「参照元(子)」テーブルにも配置する
- 例2: 関連する「参照元(子)」テーブルの合算値を取得するような場合、「参照先(親)」テーブルにあらかじめ集計しておいた値を記録するようにする
ただし、正規化崩しをすると読取操作のレスポンスが向上する一方、更新系ロジックが複雑化する。データ不整合が起こりやすくなる。
(2) サロゲートキーの導入
特に、複合主キーを単独主キーに置き換える場合に有用。キー構成の複雑さを低減する。
例:
-∈`テーブルACE`(主キー{a, c, e}, i, ⋯)
↓
-⋯`テーブルACE`(主キー{j}, i, {a, c, e}, ⋯)
サロゲートキーを導入すると、
- (1)もともとの複合主キー項目に対するユニーク制約の付与
- (2)もともとの複合主キー項目に対する更新不可制約の付与
という2つが強制される
(3) テーブルの統合と抽象化
共通する属性を持つ複数のテーブルを廃して、1個のテーブルにまとめる。
テーブル群に同一のインタフェースを与え、様々な業務の動きが統一的な視点で眺められるようになる。
例:
`テーブルX`(主キー{x}, a, b, c, ⋯)
`テーブルY`(主キー{y}, a, b, c, d, ⋯)
`テーブルZ`(主キー{z}, a, b, c, e, ⋯)
↓
`テーブルI`(主キー{i}, I区分, a, b, c, d, e, ⋯)
「I区分」にはそのレコードが本来X, Y, Zのどれかを表す値が設定される。
Xの場合にはa, b, cのみに値が指定され、
Yの場合にはa, b, c, dのみに値が指定され、
といった妥当性検査が仕様化される必要がある。
第4章 データモデリングの進め方
プロセス指向アプローチ(POA)
現行のアプリ構成と業務構成 + 顧客の改善要望 → あるべきアプリ構成と業務構成 → あるべきデータモデル
歴史的経緯
オブジェクト指向(OOP)は、POAの「データはプログラムの従属物」の価値観を推し進めたもの。
データはオブジェクトに内包され、永続化するにせよしないにせよ、オブジェクト内部で個別に対処すべきとされた。ここにRDBとOOPの齟齬が生まれた。
この問題を緩和するのがObject-Relational Mapping(ORM)。
ORMの影響で「全てのテーブルをIDの単独主キーに統一する」という設計スタイルが広まった。
その結果、精妙な関数従属性や更新不可制約が見落とされるようになった。
データ指向アプローチ(DOA)
比喩的には、皮膚がUIやビュー、筋肉が業務体制や業務ルール、骨格がDB構造。
DB構造はシステムが出来上がったら変えるのが困難。責任重大。
皮膚を先行して確定しても、筋肉や骨格を導けない。
分析的DOA
現行のデータ構成 + 顧客の改善要望 → あるべきデータモデル → あるべきアプリ構成と業務構成
これでPOAよりはうまくいくが、、、。
多くの場合、対症療法的な改善が施された代わり映えのない仕様が生み出される。
創造的DOA
顧客の非定型な思い + 設計者の経験と知識 → あるべきデータモデル → あるべきアプリ構成と業務構成
この本がおすすめするやり方。
設計者は様々なモデリングパターンや他業種での経験を援用する。
現行仕様の分析に意味がないわけではない。モデルの妥当性検証や、詳細仕様を詰めるための材料として使える。
創造的DOAで確立した「あるべきモデル」によって、大量のアプリや業務が不要とみなされたり、当初の「改善要望」が的外れに見えることが頻繁に起こる。
コツは、大枠については創造的に、詳細仕様については分析的にアプローチすること。
モデリング&プロトタイピング手法
設計者自身がシステム全体を手早くプロトタイピングする。プロトタイプをユーザに使ってもらったり、現行のデータをDBに取り込んでみてモデルの妥当性を検証する。いまいちなら気楽に破棄して作り直す。
この本の著者はこれで効果を上げている。
これは一般的なアジャイル手法とは異なる。一般的なアジャイル手法のイテレーションで出来上がる「動くソフトウェア」は小さなモジュールに限られる。広域のデータモデルに対する妥当検証が後回しにされる。
第5章 企業と事業
部門と部門階層
「自己参照」パターン
シンプルなのは下図のような「自己参照」パターン。
このパターンには現在の値しか保持できないという問題がある。
時間軸が不要ならこのパターンでも問題はない。
時間軸を含むパターン
下図パターンであれば時間軸を組み込む事ができる。
このパターンの特徴・注意点は以下。
- 部門階層の最終年月は前後のレコードから導出される論理フィールド
- 部門テーブルにも有効期間があることに注意
- 部門階層の開始/最終年月は部門自身のそれと矛盾しないように更新される必要がある
無責任な「削除フラグ」
「有効期間」の代わりに、または併用して「削除フラグ」をもたせるのは悪手。
削除フラグの扱いにくさは、レコードの「有効・無効」と「必要・不要」を区別しない点にある。
「無効だが必要」と「無効かつ不要」を区別しないで組み込まれることが多い。
「無効だが必要」の例は「有効期間を過ぎて失効した部門」。無効ではあっても、関連する過去の取引が存在するので削除されてはいけない。
「無効かつ不要」の例は「間違って登録したレコード」。関連レコードが存在するなら修正して関連をなくしたうえで物理削除してかまわない。
Discussion