ドメイン管理のデータモデリングにおける重要性

最近、データモデリングにおいて **ドメイン管理** をしているプロジェクトを見かける機会が減ってきた気がするので、

1. ドメイン管理とは何か
1. A5:SQL Mk-2 におけるドメイン管理の例
1. ドメイン管理をすることのメリット
1. ドメイン管理の難しさ

について記しておきたいと思います。

より詳しい説明は「実践的データモデリング入門」という本に記載があります。

https://www.shoeisha.co.jp/book/detail/9784798103853

ちなみに、「ドメイン」の意味はおそらく数学の [Domain of function](https://en.wikipedia.org/wiki/Domain_of_a_function) から来ていると思っています。ドメイン駆動設計やネットワークにおけるドメインとは異なりますので注意してください。

# 1. ドメイン管理とは何か

DMBOK の「5 章 データモデリングとデザイン」では「属性の定義域（ドメイン）」について以下のように説明されています。

> 各属性が取りえるすべての値一式

私なりに補足すると、**複数の属性に横断して存在する、データの意味や取りえる値のルール** と言えるかなと思います。

以下の ER 図をベースに具体的な説明をしたいと思います。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388675/0b35851c-0e22-cd2d-1b66-7bcfe290c766.png)

例えば、```社員``` テーブルの主キーである ```社員ID``` に関して以下のような意味・ルールがあるとします。

- 社員一人一人に割り振られる一意の識別子
- 入社時に割り振られ、退職まで変わることはない
- 退職者の社員IDは再利用されない
- 先頭１文字は A or B で、その後ろに 6 桁の数字（ゼロ埋めあり）で合計 7 桁の文字列

このようなデータの属性について、属性の意味やその属性が取りえる値のルールを定義したものがドメインと呼ばれます。

先の補足説明では「複数の属性に横断して存在する…」という表現をしました。これは１つのドメイン（意味やルール）は複数の属性に適用されうるということを指しています。具体的には、```社員.社員ID``` のドメインは ```社員.社員ID``` を参照する ```社員.上司ID``` にも適用されるはずです。（もちろん独自の意味・ルールが追加されることはあります）

上の ER 図で例を示すと他には

- ```社員.部署ID``` と ```部署.部署ID```
- ```社員.電話番号``` と ```社員.緊急連絡先``` （前者は通常時の業務利用電話番号、後者は緊急連絡用の自宅や親族の電話番号を想定）

などで共通のドメインを持つと考えられます。

ドメイン管理とは雑に言うと、システム（もしくは組織全体）で利用する属性の意味やルールを定義して、それらと属性の紐付けを作成・維持するということになります。

# 2. A5:SQL Mk-2 におけるドメイン管理の例

先の 1. で概念的な説明をしてきましたが、具体例を見た方が分かりやすいので A5:SQL Mk-2 におけるドメイン管理の例を示します。

ER 図の編集モードでメニューから [ER図] → [ドメインを編集する] を選択すると、以下のようなダイアログが開きます。ここでドメインを定義します。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388675/2e060efc-86f6-a09e-087a-006cfa3f1d73.png)

今回は先のサンプル ER 図に基づいて、```社員ID```、```部署ID```、```電話番号``` という３つのドメインを定義してみます。それぞれに対して以下を記載します。

- ドメイン名
- データ型
- コメント（意味やルールなど）

（コメントに何を書くかは悩ましいですが、取りえる値のルールの記載という観点では DMBOK にいくつかのパターンが説明されています。悩んだ場合は参照すると良いかもしれません。）

その後に、テーブルの編集画面で属性にドメインを割り当てます。

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388675/ca75ad3e-7718-73c1-d45a-dd9dd62b09da.png)

ER 図上は以下のように見えます。

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388675/005223a8-60e9-a897-e2a1-7dff914a8873.png)

（本来は ```氏名``` や ```部署名``` に関してもドメインを定義、適用すべきですが、今回の例では省略しています）

こう見ると、ドメインは抽象的＆プリミティブなデータ型とみなすこともできますね。もちろんこのデータ型は DBMS には実在しないですが、A5:SQL Mk-2 から DDL 文を生成する際はドメインに割り振られたデータ型が自動で属性のデータ型として展開されます。

ちなみに今回は A5:SQL Mk-2 を用いていますが、以下のような不満を感じる・聞くことも多く、それなりの規模でドメイン管理するプロジェクトでは別のツールを使うことが多いようです。

- ドメインが階層化できない
- コメントに改行が書けない

# 3. ドメイン管理をすることのメリット

なぜドメイン管理がデータモデルにおいて重要かを、いくつかのメリットを挙げることで説明します。もちろん、各属性で個別に意味やデータのルールを定義することと比較すると DRY 原則（同じ知識を複数の箇所で管理ない）を守っているという点は大きいのですが、それ以外の理由を挙げたいと思います。

#### (1) 属性の命名に対するインプット

先に挙げた ER 図の例で ```社員.上司ID``` という属性があるのですが、これは命名としてはあまり適切ではありません。属性名を見て社員 ID が格納されているとは分かりません（もしかしたら別のマスターテーブル ```上司``` があり、そちらを参照しているかもしれない）。

このような問題を避けるために属性を命名する際は以下のルールに従うことが好ましいとよく言われています。

> **[修飾語] + [主要語] + [区分語]**

|部位  | 概要 | 例 |
|:--|:--|:--|
|修飾語   |その属性固有の意味を表す単語   |上司、所属   |
|主要語   |その属性が指している対象を表す単語   |社員、部署   |
|区分語   |その値の種類を表す単語   |ID、名   |

このルールに従うと先の例では ```上司社員ID```（```上司``` + ```社員``` + ```ID```）になるかと思います（まどろっこしいと感じるかもしれませんが、属性の命名は名前を見て意味を理解できることが重要です）。

この際 [主要語] + [区分語] がドメイン名と一致することが多く（今回だと ```社員ID```）、ドメイン管理をしておくと命名の揺れを抑える、ルールに沿った機械的な命名やそのチェックがしやすくなるなどのメリットがあります。

（もちろん、こんなに単純でないケースはありますし、べき論としてはより細かく修飾語、主要語、区分語を辞書として管理した方が良いということはあるのですが）

#### (2) データ型などの修正時の影響範囲明確化

システムの開発や改修を続けていると、属性のデータ型を修正する必要性が出てくることがあります（```varchar(100)``` を ```varchar(200)``` にしたり、```date``` を ```datetime``` にしたり）。この際に、同じ意味を持つ属性は漏れなくすべて修正する必要がありますが、テーブル数が多いと全属性の中から影響がある属性を拾い上げるのは大変な作業です。

例えば、住所の最大文字列長を大きくしたいとなった場合、システムの全属性から住所を含むカラムを洗い出す必要があります。属性の命名が適切になされていれば「住所」というワードを属性名を含む属性を検索するという方法で洗い出せるかもしれませんが、実際にはなかなか期待できないことも多いかと思います。

そこで、ドメイン管理において属性とドメインを紐付けておき、ドメイン側で実際のデータ型を指定しておくと、ドメインのデータ型を一箇所修正するのみで事足ります。実際にはドメインと属性の対応を確認して影響範囲を確認してから行う必要がありますが、それでも全属性を精査するよりは楽になります。

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388675/f7c79ed6-528b-007a-a038-a1125f595ec0.png)

ちなみに、今回はデータ型の変更について取り上げましたが、それ以外の修正（例えば氏名を姓と名の２属性に分割するなど）の影響範囲調査にも活用できます。

#### (3) 属性設計の標準化

要件や設計者によって属性の設計内容にブレることがあります。例えば一般的なドメインでも以下のような差異が考えられます。

- 住所
    - １つの文字列として保持するのか、都道府県コード + 市区町村 + 町名・番地 + 建物名などに分割して保持するのか
    - 外部ツールなどを使ってクレンジングや記述統一が許されているか（システムで処理する場合やデータで分析する場合はクレンジングが好ましいが、送り状などで使用する場合は修正自体が NG なケースもある）
- 金額
    - 円貨 or 外貨
    - 小数点を許すか（外貨決済の金額を円貨に換算する場合など）
    - 消費税を含むか

このように似た意味でも違うものをはどうしても開発を進める中で出てくるのですが、これらを統一したドメイン、もしくは個別のドメインとして事前に定義しておくことで、統一を図ったり、設計者に細かい意味の違いを意識して選択させたりすることができます。（要件による部分もあるのですべて統一は難しいですが、設計者の考慮漏れを防ぐ意味でも重要です）

# 4. ドメイン管理の難しさ

ここまで、ドメイン管理の概要について述べてきましたが、実施しているプロジェクトや組織は減ってきているように感じます。

私の想像ですが、以下のようなことが理由なのではないかと思います。

- データモデリングを従来はプロジェクト内の DBA チームが集中的に担当していたが、最近は各機能チームで分散して実施するケースが増えたため、集中的にドメインを管理する役割が宙に浮いている。
- 意味や値が取りえる範囲のルールなどを DB で管理することより、アプリ側で管理することが増えた。
- ドメイン管理は手間が掛かる一方、それだけで解決できない問題も多い。（例えば、ルールの強制や遵守状況のモニタリング、属性独自の意味の管理など）

ただ、１システムに閉じた話であれば何とかなるのですが、複数のシステムのデータを集約・統合して利活用していこうとなると、ドメイン管理が担っている標準化や情報の提供は形を変えたとしても必要なのではないかと思います。

とはいえ、理由の３点目に述べている手間が掛かるという課題は改善する必要があるので、こういうことが可能になったら嬉しいなぁと思っている内容をいくつか挙げて、記事を締めたいと思います。

- ドメインの意味・ルールの自動生成
    - ドメインに対して個別に意味やデータのルールを記載するのは大変です。
    - 生成 AI が出てきているので、ドメインの意味やルールを一般常識や業務ドキュメントなどから生成できたら、管理はかなり楽になりそう。
- ドメインの自動判定
    - 属性がどのドメインに紐付くかを判断・登録するのも大変です。
    - 属性名やデータの中身を見てある程度自動化することはできるのではと思うのですが、どうでしょう。過去に実施した属性＋データとドメインの紐付けのペアを学習すれば可能そうと思っているのですが。
    - 多くのデータカタログでは一部の種類のデータについてドメイン（という名前ではないですが）の自動推測機能が付いています。ただし、対象が個人識別情報（PII：氏名、住所、クレジットカード番号など）が中心で、目的もセキュリティー寄りなんですよね。
    - リネージや外部キー制約などテクニカルメタデータから判定できる部分は自動でやって欲しい。