<< 個人の識別キーの設計 : 名前? 番号? メールアドレス? 別名? | main | 番号より名前。 ニーモニックコードより名前。 【パターン】 >>

「自然キー」で識別するのが、もっとも「自然」 【パターン】

「自然キー」は、データモデリングの用語からの借り物です。
データモデリングの世界では、システム内部で機械的に発行する「人工キー」との対比で使われる用語。

「レコードを一意に識別するキーの候補には "自然キー" と "人工キー" がある、というように使われる。

自然キー( natural key ) は、名前、電話番号、メールアドレスなど、人間が使っている情報。
人工キー( surrogate key ) は、システム的に生成した番号。人間にとっては、意味のない情報。

人工キーは、人目に触れない、内部限定、というのが本来の意味らしい。

ここでは、「人間が使っている識別情報」を自然キー、システムで機械的に作成した番号を、人工キーとしておきましょう。

ソフトウェアのモデリングと設計・実装は、「自然キー」を大切にすべき。

自然キーは主キーとしては扱いにくい


データモデリング的には、自然キーで、一意に識別するためには、通常は、複数の属性を組み合わる必要がある。
「同姓同名」が、わかりやすい例ですね。
「同姓同名」に生年月日を組み合わせても、完全に「一意」になるわけではない。

データベースの実装の視点からは、主キー (と外部参照)は、人工キーでやったほうが確実だし、SQL 文の JOIN 句は単純になる。

注文番号とか、契約番号というように、人工キーが、実際の業務で、つまり自然キーとして使われていることもある。

「人」は、人工キーより自然キーを好む


当たり前だけど、人にとって「自然」だから、「自然キー」なんです。
データベース的に、完全に一意にならないとか、多くの属性を組み合わせた一意識別は、扱いにくい、というような議論は、システム内部の議論。

人は、いつでも「自然キー」を好むんです。

「注文」を、注文番号で探すより、注文した人、受注日、受注内容から、「自然」に識別しようとする。

「契約」も、契約番号より、契約の種類と契約相手から探す。

「人」にとって、役に立つ、使いやすいソフトウェアを造るには、「自然キー」を使って仕事がやりやすい仕組みにすべき。

候補の提示と選択


自然キーは、複数の属性を組み合わせて、はじめて、一意になる。

たとえば、郵便番号を特定するには、東京都文京区本郷 という 都道府県+市区町村+町域という三つの属性で一意に決まる。

URI 式だと、 /郵便番号/東京都/文京区/本郷 という形式。

業務上、こういう一意識別できる属性の「完全」な組み合わせを使うことよりも、不完全な情報、一部の属性だけで探したいことがはるかに多い。

郵便番号の例だと、「本郷三丁目」の郵便番号は、という感じ。本人は、そこが、東京都で文京区であることを、無意識に前提にしている。 明確に意識する属性は「本郷三丁目」。 これで、一意に識別できると漠然と期待している。
(実際に、一意に識別できてるかもしれない)

自然キーは、一意に決まるとは限らないので、「候補」を提示して、選択する、というのが自然で使いやすいと思う。

ジョルダンの乗換案内の駅名入力は、ajax を使って、一意でない場合の候補の提示を自然にやろうとしている。

もっとも、「北名古屋」とか、実際にはない(?)駅名を入れると、怪しげな選択リストになるけどね。

ajax のように、あまり凝ったことはしなくても、

一覧表示 → 詳細表示、というように、「候補」を提示して、人間が選択、というのは、アプリケーションの基本パターンですね。

URI 方式でも、

/郵便番号 で、都道府県の一覧
一覧から都道府県を選ぶと、市区町村の一覧
一覧から市区町村を選ぶと、町域の一覧
一覧から町域を選ぶと、郵便番号の一覧

というように、「候補の提示、人間の選択」というのが基本パターン。

注文だったら、当日の注文一覧から選択とか、特定顧客企業の注文一覧から選択。
会員検索なら、姓で検索した一覧から、選択。

こういうパターンが自然だし、実際に多い。

自然キーを、テーブルインデックスとして実装する


自然キーは、最初に書いたように、テーブル実装で、主キーになることは少ない。

でも、人間が、自然に識別に使う属性(カラム)は、テーブル設計で、主キー意外に考慮すべきことがある。

それは、「インデックス」の作成。

インデックスは、開発の後半で、性能チューニングのために作成するものではないです。

人間が識別に使いたい情報を、把握して、テーブルの「インデックス」の設計・実装に反映させる。

画面デザインで、カテゴリー式のナビゲーションや、検索条件の指定などを議論したら、それは、そのまま、カテゴリーID カラムのインデックスや、検索対象のカラムのインデックスの作成に直結する、ということ。

利用者が、業務の中で、識別の手がかりにしようと思っているカラムは、インデックスを作成すべきです。

姓で検索することが多いので、「姓」カラムは、インデックスを作成する。
名(単独)で検索することは、ないので、「名」カラムは、インデックスは、作成しない。

こういうのがインデックス設計の基本だと思う。

文脈から絞り込む


人は、文脈、前後関係から、うまくスコープを絞って、少ない情報で一意に識別している。

「中村」さんは、たくさんいるけど、「この会社」とか、「最近注文した」という条件をつけて、「中村」で一意識別している。

ソフトウェアも、こういう自然なやり方を、サポートする仕組みを組み込む努力をすべきだと思っている。

中村さんの注文、という問合せがあったとき、可能であれば、文脈を判断して、特定してあげたい。

Google 検索に、 "I'm Feeling Lucky" ボタンがありますね。
あれは、文脈を判断してくれるわけではないだろうけど、「一発で目的にたどり着く」ことを狙った、おもしろい仕掛けだと思う。

もっとも、私は最近は、あのボタンを使ったことはないですねえ。
一発でたどり着けないことが多い。
それから、一覧自体が「関連情報」として価値があることが多いので、最近は、 I'm Feeling Lucky ボタンがあること自体、忘れかけている。

「関連情報」とか、「安心感」という意味では、「文脈から判断して、一意に特定できたら直接詳細画面へ」という設計は、よくないかも。

一件だけでも、「一件だけだった」という情報を、一覧画面で見せるべきかな?
それが、目的の情報だったら、それを選ぶ。目的の情報じゃなかったら、検索のやりなおし、という設計のほうが、自然かな?


API とか、システムが相手の場合


人間が、会話的に利用する時は、

・部分的な識別情報の入力
・候補一覧の提示
・人間が選択

という流れが自然だと思う。

API による情報提供とか、メッセージングなどのアプリケーション連係だと、そうはいきませんね。

一意に識別できなかった場合は、たぶん、エラーとして扱わないといけない。
データベースの主キーでの操作と同じ世界になる。

API とか、メッセージングの場合の識別キーとしては、データベースと同じように、人工キー、つまり、機械的に生成した一意識別用の番号を使うという方法がある。

もうひとつは、URI のフルパスを指定する、という方法。
個人的には、最近は、URI のパス指定方式が良いのかな、と思っている。

URI で、記述的に、

/銀行口座/東京銀行/本郷支店/普通/223344

という指定の方が、

<bankaccount id="89034933482" />

より、良い感じだなあ、と。

目的にもよるけど、自然キーと人工キーの両方を記述するほうが、実用的かな?

問題は、公開する API とか、外部のアプリケーションとの連係とかで、意味のある「ID」設計は、難しいということ。

書籍のように、そのドメインで、ISBN という ID 体系が確立していれば、それを使える。

でも、私たちの問題領域(転職サポート)では、「求人」や「応募者」の ID (識別キー)を、アプリケーションや企業をまたがった、共通の識別体系をつくるのは至難。

そもそも、単独のサービス内でも、「重複応募」で、同一人物の特定、という問題がある。
「求人」も、内容の変更や、再掲載ができるので、何を持って「同じ求人」と捉えるかも問題。

なんか、いいアイデアないですかねえ。

コメント
コメントする









この記事のトラックバックURL
トラックバック
calendar
 123456
78910111213
14151617181920
21222324252627
28293031   
<< October 2018 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
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