番号より名前。 ニーモニックコードより名前。 【パターン】

「識別キー」とか「ID」 というと、番号体系やコード体系のイメージが強いと思う。

39857, 10.13.xx.255 とかの数字ID
AK-4483 とかアルファベットと数字
UK, JP とかのニーモニックコード

などが、コンピュータの世界で、よく使われる形式ですね。

もちろん、一般の世界でも、

090-9999-0000 形式の電話番号、 113-0031 形式の郵便番号とかは、使っている。

私は、記述的な「名前」による識別のほうが、わかりやすく、良い識別方法だと思っている。

10.13.xx.255 より、somewhere.over.the.rainbow のほうが、わかりやすい。

ニーモニックも、プログラミングの世界ではあたりまえだけど、

cp より copy
mv より move

のほうが「はるか」にわかりやすい。自然言語を使った名前が、やっぱり一番。

ソフトウェア技術者は、番号やニーモニックを扱うことに慣れているけど、かなりの部分は、古びた悪しき習慣なんじゃないかと思っている。

ニーモニック


大昔、機械語しかなかった時代に、 LD(ロード命令)や、ST(ストア命令)というニーモニックは画期的だった。 0110 だとロード、1110 だとストアなんていうのが、LD / ST で書けるのは、ほんと革命。

この時代は、まさに、LD とか、 ST が「ニーモニック(覚えやすい)」コードだった。

Unix の初期の開発者たちは、こういう時代の人たちだから、ニーモニック大好き。

だから、Unix の初期の時代からあるコマンドは、ニーモニックのオンパレード。

cd, ls, cp, mv, dd, ls, sh, cc, ...

Unix( Linux ) で、文字数が多いコマンドは、まちがいなく、後から追加されたコマンド。 Unix 原始時代には、3文字、4文字のコマンドはなかった(と思う)。

50 bps レベルのテレタイプが主流で、300 bps が高速!通信回線だった時代。

メモリも、32KB とかで大容量。

この時代だと、copy より、cp の方が、効率が良い、というのが、大真面目な議論だった。
自然言語の「冗長」な表記は、とんでもない、ことだった。

もっとも、同時代の VAX は、help, link, run, ... というように、自然言語重視派。

Unix 初期の連中が、変わり者だったのかな?

まあ、いずれにしても、いまでも、ソフトウェア技術者の多くは、ニーモニックが当たり前だとおもっているし、自然言語の表記より、ニーモニックのほうが、好みかもしれない。

私は、自然言語派。プログラミングの世界といえども、人間にとっては、ぱっとわかりやすいのは、自然言語にきまっている。

だから、 def, val, var, << :: | とか連発するプログラミング言語は嫌いなんですよねえ。
生産性(可読性)が低いと思っている。

自然言語の文字列の処理という技術革命


Unix の初期開発者たちは、自分たちは、ニーモニック大好きだったけど、

The quick brown fox jumps over the lazy dog.

を単語に分解して、単語数を数えるプログラム、とか、自然言語の文字列を処理する、という分野で、コンピュータの世界に大きな変革をもたらした。

汎用コンピュータ用のOSは、「固定長」が絶対条件。
可変長とか、動的にヒープを獲得・開放するなんていう発想はなかった。

だから、プログラム設計、ファイル設計、通信電文設計、どれも、最大桁数をきめ、最初から固定で割り当てる設計する。一文字もデータがなくても、最大桁数をメモリやディスクに確保してしまう。
かなり資源の無駄遣いです。

どんな長さがくるか、予測できない、自然言語文字列の処理は、大の苦手だった。

Unix では、可変長、動的なリソースの獲得・開放を扱うための、データ構造とアルゴリズムにこだわった。
C 言語の勉強とは、データ構造とアルゴリズムの勉強だった。

また、ストリーム型の処理(文字単位で処理していく)も特徴。
メモリ上のバッファは固定長でも、データ自体は、可変長で、NL とか EOF が来るまで読み込む、という「可変長文字列の行単位の処理」というのは、画期的だった。

もっとも、一秒間に、5文字送るのがせいぜいのテレタイプ回線で、通信していたりすると、一文字ずつ、順番に処理する、という発想に自然になるんだろうけど。

Unix や、VAX では、可変長で、動的確保と開放が基本思想。現在のコンピューティングでは、もちろん、こちらが当たり前。

もっとも、OSの内部では、テーブル等は、固定長・固定数のことが多かった。
ぎりぎりの性能を重視すれば、可変長・動的割当は、かなり鈍重な処理ですからね。

長さ固定とか、コード化して短縮表記とかは、コンピュータが高価で、ソフトウェアも、原始的な時代の遺物に近いと思うんですよねえ。

もちろん、今でも、固定長とか、短縮表記が、意味のある世界もあるだろうけど、可変長の自然言語の表記、というのが、基本トレンドでしょう。

ソフトウェア技術、ハードや通信のコストからすれば「固定長・短縮表記」は、はるか昔の話し。
今は「可変長で、自然言語の冗長な表記」を扱うのに、ハードの制約もないし、プログラミングも、便利なツールがたくさん揃っている。

もっと、自然言語に近づけようよ、ということ。
DSLの議論なんかも、こういうトレンドの一つでしょう。

まあ、技術者のニーモニック好きは、そう簡単にはかわらないかもしれない。
ニーモニック好きの技術者が、ニーモニック連発の言語使って、「ドメイン固有の言語」の議論しているのは、なんか、滑稽に見える。(まじめに取り組んでいる方には申し訳ありませんが)

ドメイン固有言語は「自然言語」でしょう、やっぱり。

自然言語に近い名前空間を設計して使おう


xml の名前空間とか、URI とかは、問題領域の言葉をそのまま使った、名前空間に設計できるならそれが、一番わかりやすい。

ドメイン層のクラス名やメソッド名、テーブル名やカラム名も、全部、そう。

「識別キー」の設計は、「番号体系」や「ニーモニックコード」の設計よりも「自然言語に近い名前空間の設計」にこだわり、重視するのが、良い設計なんだと思う。

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

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

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

自然キー( 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 (識別キー)を、アプリケーションや企業をまたがった、共通の識別体系をつくるのは至難。

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

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

個人の識別キーの設計 : 名前? 番号? メールアドレス? 別名?

顧客や申込者の「個人」を識別するキーの設計は、なかなか興味深いテーマ。

分かりやすさでは「名前」。一意識別性なら「番号」。
ドメイン名や、メールアドレスは、「名前」の分かりやすさと、一意識別性を兼ね備えている。

宅配ピザ


宅配ビザに注文すると、電話番号を質問される。
顧客データベース上で、私(の自宅)を電話番号で特定しているわけだ。

データベースに登録されている住所(と名前も?)を、確認されて、顧客の確認を終了。
これで、どこに配達するか、特定できたわけだ。

簡易な識別方法として、電話番号が有効なことは多い。

宅配ピザであれば、国番号とか、市外局番も不要。東京だと、4桁-4桁の番号が、リピート顧客の識別キーになる。

利用する側も、受付側も、負担が少ない、良い設計だと思う。

クレジットカードの問合せ


クレジットカードについて、突然、使えなくなったので、コールセンターに電話。

カード番号を聞かれた後、登録済みの「住所」「電話番号」「生年月日」を質問されて、本人確認。
結構面倒。まあ、宅配ピザというわけにはいかない。

限度額オーバーだった。

ちゃんと、限度内でやっているつもりだったけど、海外で使った金額が、前月引き落とし済みと思っていたら、遅れて、今月の請求になっていたので、限度額オーバーになっちゃった。

でも、この情報が、さきほどの本人確認で聞き出せるのは、ちょっと、不安。

カード番号、住所、電話番号、生年月日、悪意があれば、他人が私に成りすますのは、それほど、むずかしくはなさそう。

もっとも、金額とかのナマのデータは、オペレータは、一切、しゃべらない。
(たぶん、画面でも、この段階では、そこまで見れない)

「限度額オーバー」という状態だけ教えてくれる。
セキュリティレベルと、問合せの利便性を考えると、ここらへんもバランスがとれた仕組みになっているのかもしれない。

何のときだったか、忘れたけど、「登録してある銀行口座番号」まで、聞かれたことがあった。
クレジットカード会社からの請求書とかには、口座番号は、マスキングしてあるので、この情報まで、私がちゃんと提示できれば、より確かな本人確認になるわけだ。

リフレクソロジー


時間があいたので、足裏マッサージでもしようかと、リフレクソロジーのチェーン店に飛び込んだ。

会員かどうか聞かれたので、会員と申告。でも会員カードをもっていなかった。

誕生日(月と日)を聞かれて、苗字を聞かれて、本人確認終了。
同じ誕生日で、同姓の人はいないみたい。

あとは、支払い時に、ポイント加算してくれたことを告げられる。

誕生日(月と日)で、ハッシングして、そのグループ内で、姓で特定にいく。
同姓同名の場合、どうやっているのか、ちょっと興味があるなあ。
(お店の人とか、この記事読んでいたら、教えてくれないかしら)

応募者の重複チェック


私のメインの活動領域、人材の募集と応募のドメインでの「個人の識別」のテーマ。

同じ人が、繰り返し応募してきたり、別の職種に同時に応募する、というのはよくある話。

で、応募情報から「同一人物」を特定するのが、結構やっかい。

メールアドレスとか、電話番号は、わりと、変わるんですよね。

いちおう、「生年月日」と「ヨミガナ」をキーにして、「もしかして同一人物」リストを出すようにしている。

漢字の姓名は、表記の揺らぎが意外とあるんですよね。(大沢さんと大澤さんとか)

最後は人間が判断


どのケースも、「本人確認」とか「同一人物」判断は、人がやっている。

クレジットカード会社とかは、情報の一致だけじゃなく、相手の応答がつまったり、へんだったりしたら、マニュアルが、しっかりしていて、質問レベルが難しくなるようになっているらしい。

そうそう、何か、住所か何かを言い間違えた時に、えらいめにあった気がする。

管理番号


システム化の王道(?)は、やはり、管理番号をつけて、一意に識別すること。

これは、電子化以前から、業務の仕組みとして、確立しているやり方。

顧客番号、注文番号、契約番号、請求番号、...

紙伝票に手書きの時代から工夫されている。

手書き時代の番号は、「年」とか、「月」を先頭につけて、それ以下を連番にする、というのが多かったような気がする。

これ、システム的にはちょっと厄介なんですよね。月ごとに、連番をリセットするというのは。

あと、最近は、分散処理というか、ネットワーク上で、複数のサービス(異なるアプリケーション)から、顧客登録が可能、というケースもでてきた。

この場合は、一意に識別する顧客番号を、発行するのは、結構たいへん。

まあ、先頭に、サービスごとの識別番号をつけるとか、いうやり方もあるにはある。

年、月、登録サービスなどの情報を、識別キーに埋め込むことは、あまり良い方向ではなさそう。

この程度のレベルであればいいけど、会員種別とか、居住地域とかの情報が、識別番号の一部にまぎれこんでくるのは、明らかに、汚染。

登録制


ドメイン名とか、ISBN は、登録制だから、グローバルに、一意識別が保証されている。
電話番号も、国番号まで使うと、いちおう、そうなっている。

通信インフェースカードの識別番号である、 MAC アドレスも、世の中のすべての通信カードで、一意に識別するようになっている。 (ろくでもない製造業者が、偽造番号で作っていることが、昔はあった。今でもあるのなか?)

JAN コード(商品のバーコードでおなじみ)も、登録制で一意の番号。ワールドワイドの商品識別体系の一部として互換性があり、世界中で一意になる仕組み。

もっとも、JAN コード自体は、一意だけど、同じコードを複数の商品に使ったりしているメーカーがあるので、商品のコードとしては一意ではない。

サイズ、色違い、バージョン違いなどは、 JAN コードでは、特定できないのが普通。

こういう共通の識別体系じゃなくても、アプリケーションで独自に「発番」の仕組みを作って、登録制にするのは、常套手段。

ネットワーク上で、他のサービス(他の識別体系)との連係が、ますます重要になってきているの。アプリケーションの独自の発番の仕組みを考えるときは、外部の識別体系との関係性や、整合性には、気を配るべき。

まあ、URI のように、ドメイン名(サービス名)以下に独自の体系であれば、一意識別は保証できる。
でも、利用者からみたら、同種のサービスは、同じ識別体系であるほうが、使いやすい。

妥当性検証


クレジットカード番号や、ISBN (本の国際識別番号体系)は、単純な連番ではない。
チェックデジットと言って、本体の番号を、一定のロジックで計算した、結果の数字を付加している。
登録データベースに問い合わせなくても、番号だけで、妥当性検証ができるようになっている。
---

とりとめなくなってきちゃったなあ。
とりあえず、識別キーネタ、ということで書いておきましょう。

URI でリクエストされた時に送るデータの設計



URI は、記述的にわかりやすく設計する。
利用者が欲しいと思っている情報を、直感的に表現した名前が良い URI。

/郵便番号/東京都/文京区/本郷三丁目

で送り出す主なデータは、 "113-0031" 。

path の先頭の要素は、「データの集合」の名前にする


関心事は、「郵便番号」だから、Path も、「郵便番号」ではじめる。そして、送り返すデータは、ストレートに、"113-0031"。

こういう単純明快さが、良い、URI の設計。

path の先頭は「データの集合」の名前にするのが原則。

「郵便番号」というデータの集合から、特定のデータを指定するための仕組みが、URI ということ。

ROA ( リソース指向アーキテクチャ)の発想だとこうなる。

アマゾンは、path の先頭を /本-和書/ とか、使っていますね。本-和書についての「データの集合」を起点に探す。

手続き的というか、機能指向だと、 グーグルのトップページのように、/search になる。
もっとも、個別の検索機能では、

/webhp Web のホームページ
/imghp イメージ情報のホームページ
/maps 地図

という感じで、対象とする「データの集合」の名前が、path の先頭要素になっている。

日本郵便の郵便番号検索のように、プログラミング指向だと、 /cgi_zip/zipcode.php を起点に探すことになる。
アンチパターン。

レスポンスデータの内容


URI の設計がよく出来ていれば、レスポンスデータの内容も、単純に決まるはず。

/郵便番号 であれば、 "113-0031" を返す。
/maps であれば、 指定位置の "地図" を返す。

/本-和書 はちょっと、悩ましい。実際に、アマゾンの場合は、一ページに収まりきらない、膨大なデータが帰ってくる。 私は、ほとんど、目的買いなんで、あんなにたくさんの情報、欲しくないんですけどね。

URI はできるだけ、シンプルで、わかりやすくあるべきだし、返すデータも、できるだけ、シンプルで、わかりやすくするのが良い設計だと思う。

もっとも "113-0031" だけでは、さすがに、シンプルすぎる。

実際の検索サービスでも、”東京都 文京区 本郷 " という 都道府県名、市区町村名、町域名もいっしょに帰ってくる。 町域名は、さらに、「ヨミガナ」も返る。

ページ自体は、パンくずリストがあって、上位の path への リンクとか、いろいろな関連情報へのリンクがてんこもり。

まあ、こういうリンクも、できるだけ目的にそって、厳選して、シンプルにしたほうが良いに決まっている。

アマゾンの本の詳細画面のように、読みきれないほどのデータを、送りつけてくるのは、どうかと思う。

表現の形式


基本の形式は、XHTML 、 XML、 JSON とかかな?

私は、XML がもっとも良いと思っている。データの要素名や構造を適切に表現するには、やはり、XML が一番。

XHTML を、画面レスポンスだけでなく、データのレスポンス形式として、そのまま使う、というアイデアもある。
これだと、画面も、REST サービスも、同じになるので、サーバーの開発側は楽かもしれない。

でも、実際には、 画面を使うシーンで、欲しい情報と、REST サービスで使うシーンで欲しい情報は、違っていることが多い。

だから、XHTML という形式で共通化するメリットを私はあまり感じていない。
クライアント側のソフトウェアを開発することも多いので、 XHTML より、XML でもらったほうが、やりやすいと思っている。

JSON は、手軽といえば、手軽なんだけど、データのメタ情報(項目の名前)とかが、表現されていないので、あまり、良いやり方じゃないと思う。

構造が、 map (連想配列) を使うのが適切な場合は、key の名前で、情報の意味を表現できるかな。

State Transfer ということ


REST は、 ご存知のように、 REpresentational State Transfer から作った造語。

"Representational" が、「表現」ということ。
つまり、「リソース」そのものではなく、その「表現」を返すという発想。

URI にリクエスト内容によっては、異なる表現形式で返すのもあり、というわけだ。
図形的な表現なら、svg のようなベクター形式もありだし、イメージファイル、として表現という手もある。
化学の構造式とかは、XML で表現するボキャブラリセットが、利用されている分野。

注目は、 "State Transfer" のほう。

"State" というのは、状態。 プログラミング的には、変数の集合、データベース的には、カラムの集合ですね。

REST は、リソースの「状態」を、「転送」する、という発想。

状態なんで、もちろん、いつも同じとは限らない。 同じ URI でリクエストしても、そのたびに、違う内容が帰ってくるのが、当たり前の世界。

郵便番号の例だと、 /郵便番号/東京都/文京区/本郷 の URI path で、"113-0033" が変わることはあまりなさそう。

でも、/住所/330-0841 という URI の path だと、昔だったら、「大宮市」が戻ってきて、現在は、「さいたま市」が返ってくる。

「住所」というデータセットは「市区町村の合併」などで、いろいろ変化している。

URI は、「識別キー」だけど、タイミングによって、異なる内容が返ってくる仕組み。つまり、「一意」の識別ではない、ということ。

エンタープライズアプリケーションでは、多くの関心事は、この「変動」する情報。リソースそのものは、 URI で、一意に決まるけど、その「現在の状態」は一意ではない。

「状態の変化」のモデリングと設計のパターン


この変化する「状態」を、うまくモデリングして、設計・実装することが、エンタープライズアプリケーションの中核の課題。

「パターン言語」として、いろいろ、考えていることも、この「状態の変化」のモデリングパターンであり、設計パターンが、いちばんの関心事。

REST の URI/表現のように、「識別キー」を指定すると、「現在の状態」の「表現」を提供する、というのが、まずは基本パターン。

「銀行口座」を指定すると、「残高」を知らせる、というパターンです。

「現在の状態」を提供するためには、「状態を変化」させることが必要。
エンタープライズアプリケーション、事業のためのソフトウェアでは、状態を変化は、誰でも、好き勝手にできるわけではない。

事実を正しく反映しなきゃいけないし、変化させるための、権限とかルールなどの決め事が多いことも多い。
また、「変化」が起きたら、それに反応する必要がある。 「変化の検知」や「変化の通知」も、エンタープライズアプリケーションの重要な関心事。

ここらへんのモデリングパターン、設計・実装パターンをいろいろ書き始めているところ。

URI 設計の例 : 郵便番号と住所

「住所」を例に、関心事オブジェクトの 識別キー(URI) 設計の例。

日本郵便の郵便番号検索を参考にしてみた。
http://www.post.japanpost.jp/zipcode/

URI のおさらい


URI は、ネットワーク上の資源(リソース)を特定するための、

Scheme : "http:"
Server : "//www.post.japanpost.jp"
Path : "/zipcode/"
Query : ?name=value
Fragment : #ページ内のブロックのid

という構造の識別方式。

「知りたいと思っていること」を、この形式で、どうやって、表現するのが使いやすいサービスだろう?

日本郵便の実際のサイトの Path と Qeury を参考にしながら、リソース指向アーキテクチャ(ROA)っぽい、URI 設計にチャレンジしてみる。

path 名は、日本語のほうが、わかりやすいので、今回は、日本語でやってみます。

path のroot


現状は、 /zipcode になっている。

このリソースを要求すると、「郵便番号検索」のメイン画面がでてくる。
よく見ると、2種類のサービスがある。

ひとつは、「住所」から「郵便番号」を探すサービス。
もうひとつは、「郵便番号」から「住所」を探すサービス。

正引きと逆引きですね。

というわけで、そもそも、ルートが2つ必要。

/郵便番号 (これ以下に、郵便番号リソースがどさっとある)
/住所 (これ以下に、住所リソースがどさっとある)

"/郵便番号"を起点に特定していく


「郵便番号」を知りたい、という要求に、日本郵便が提供しているサービスは、「都道府県」と「市区町村」で調べていく方法。

実際の画面では、 /郵便番号 の要求に対して「都道府県の一覧」を、地図とドロップダウンリストで「表現」している。

xml 形式のレスポンスなら、<prefecture id=13>東京都</prefecture>形式の要素を、47個、ならべる。

"/郵便番号" だけで要求すると、レスポンスは「都道府県の一覧」というわけだ。

都道府県まで指定したリクエスト


/郵便番号/東京都

もちろん、レスポンスは、東京都下の「市区町村」の一覧。
さらに市区町村を指定する。

/郵便番号/東京都/文京区

これで「町域」の一覧がでてくる。 ○○町一丁目 というのが多い。
(番地ではなく、「丁目」まで)

郵便番号サービスで、面白いのは、郵便番号が同じであれば「丁目」は表示せず、郵便番号を特定する時に、「丁目」まで意味がある場合は、「丁目」まで表示する。

この設計、どうなんだろう?
利用者は、郵便番号の体系とかルールとか知らないので、町域が「丁目」まであるのと、ないのが混在しているのは違和感がある。

全部「町域」は「丁目」レベルまで、というほうが自然だと思う。

まあ、実際の画面に合わせて、町域を指定する。

/郵便番号/東京都/文京区/本郷

めでたく 「113−0033」にたどり着く。
もっとも、本郷二丁目や三丁目という表示はなく、単に「文京区本郷」だけ。
こちらは、「本郷三丁目」まで、住所を知っていて、郵便番号を探しているので、「文京区本郷」だけの表示だと、正しい郵便番号にたどり着けたか、ちょっと不安になる。

実際の URI


以上のケースの実際のサービスの URI は、

/cgi-zip/zipcode.php?pref=13&city=1131050&id=47742

意味不明。

「URI は記述的にわかりやすく!」に徹底抗戦した見事なアンチパターン。

まず、cgi-zip から、始める。 cgi という仕組みから辿れ、というわけだ。

pref=13 が、呪文のはじまり。まあ、都道府県のJISコードなんだけど、意味は不明。
php という、プログラミング言語まで、指定するのが、郵便番号を知るための、お約束?

city=1131050,id=47742 になると、なにをかいわんや。

画面で誘導するからいいや、ということではなく、やっぱり、URI は、「記述的」で「わかりやすく」しておきたい。

/郵便番号/東京都/文京区/本郷三丁目

ってやると、

"東京都文京区本郷三丁目の郵便番号は、 113-0033 です”

という、設計だと、わかりやすでしょ?

良い URI 設計というのは、こういうものなんだと思います。

"/住所"を起点に特定していく


郵便番号から、住所を調べる場合。

実際のサービスは、テキストフィールドで、「最低3ケタ、最大7桁の数字」を入れるという仕様。

113-003 と、最後のひとけたを入れないと、113-003* に該当する住所がずらっとでてくる。まあ、こういう検索が意味があるのか、私にはよくわかりません。

郵便番号は、999-9999 という3ケタ−4ケタという構造になっているんだから、この構造を素直に表現したほうが良いと思う。

"/住所" だけだと、上の3ケタの一覧がレスポンスされる。

/住所/113 だと、 113 以下の 下4桁の一覧が戻る。

/住所/113/0033 だと、「文京区本郷」にたどり着く。(一つだけ戻ってくる)

まあ、この郵便番号だと、本郷までしか特定できないんだけど、本郷の「丁目」一覧がでてくるほうが、自然だと思う。

郵便局の受け持ち範囲が「本郷」なのは、わかるけど、普通の人は、「郵便局の受け持ち区域」という発想では、暮らしていない。

「郵便番号」関連のサービスを使う時でも、利用者の関心事には「郵便局の受け持ち区域」なんて、持っていない。

ここらへんをもっと気を配ると、サービスのレベルが改良できるんだろうけどなあ。

ちなみに、実際の URI は、

/cgi-zip/zipcode.php?zip=113-003&x=29&y=20

意味不明ですね。 cgi や、 php に関心があるわけないですよねえ。普通は。

google の場合


google も、郵便番号とか、住所で、検索できますね。

http://maps.google.com/maps/geo?&q=1130033
とか
http://maps.google.com/maps/geo?&q=東京都文京区本郷
とか

やると、どんな表現がかえってくるか、興味があるひとは試してみてください。

URI 設計の例としては、query 式なので、あまり興味がわかないけど、レスポンスで戻ってくる内容は、なかなか興味深い。

内容は、一般の人の関心事ではないと思いますが、この API は、どんな人たちのどんなニーズを想定しているかを考えてみるのも面白いかも。

たかが URI の設計、されど URI の設計

関心事オブジェクトの「現在の状態」を利用者に提供するパターンのひとつが、REST スタイルの GET 方式。

 GET /リソースの識別名(URI)

をサーバーにリクエストすると、「現在の状態 ( current state )」の表現 ( Representation ) がかえってくる、というやつですね。

ドメインモデリングのパターンとして、私は、「リソース」を「関心事オブジェクト」、「URI」を「識別キー」という言葉にしている。

実際に、HTTP を使うかどうかは別として、

◎ リソース(=関心事オブジェクト)の
◎ URI (=識別キー) を指定して
◎ 現在の状態(current state)を入手する

というのは、エンタープライズアプリケーションの基本価値のひとつですね。
「関心のあることを知る」という業務の基本ニーズ。

このニーズに応えるための GET 方式のモデリング・設計は、エンタープライズアプリケーションのモデリング・設計の基本になる。

GET 方式の情報入手のモデリングと設計には、RESTful web サービス の考え方が、とても参考になる。
私の考え方も、この本に強く影響を受けている。

特に、URI (識別キー)の設計は、

4章 リソース指向アーキテクチャ
 4.3 URI
  4.3.1 URIは記述的であるべき

5章 リソース指向サービスの設計
 5.5 リソースに名前をつける
  5.5.1 階層パス
  5.5.2 カンマまたはセミコロン

あたりが参考になる。

内容をかいつまんで、紹介してみます。

URI ( 識別キー ) は記述的であるべき


この本の例。

http://www.example.com/relationship/Alice;Bob ( アリスとボブの関係は?)
http://www.example.com/sales/2004/Q4  (2004年、第4四半期の売上は?)
http://www.example.com/bugs/by-state/open (未解決のバグは?)
...

こんな感じで、「知りたいこと」をそのまま、表記する、というのが、この本の主張です。

example.com 社の公開リソース(www) の例ですね。

社内(イントラ)の業務システムなら、

http://intra.system-sekkei.com/customer/contactinfo/masuda220 (masuda220 の連絡先は?)
http://intra.system-sekkei.com/project/by-state/on-going (実施中のプロジェクトは?)
http://intra.system-sekkei.com/human-resource/skillset/masuda220 (masuda220のスキルセットは?)
...

こんな感じになる。

クエリ文字列方式


クエリ文字列、たとえば、 find?id=masuda220&infotype=contact との違いに注目。

この本は、クエリ文字列は、否定はしていない。しかし、パラメータ名は、"SHOW" とか、特定の名前、汎用的な名前に限定するという考え方。

REST スタイルでは、基本コマンドは、事前定義された、GET/PUT/DELETE/POST に限定している。
この考え方を延長すると、クエリ文字列のパラメータ名も、よく使われる汎用的な名前に限定する、という発想になる。

設計課題は、URI (識別キー)


REST スタイル、あるいは、リソース指向では、いちばんの設計課題は、リソース(=関心事オブジェクト)の、識別キーを設計すること。

逆に、「コマンド(=処理命令)」は、REST スタイルでは、設計課題ではない。
必要最小限の well known のコマンドセットが事前に定義されているから。

SQL文でも、コマンドは、 select/insert/update/delete に限定している。

リソース指向やデータ指向だと、機能(コマンド)は、最初から決まっている、という考え方。
その視点からは、クエリ表現は、 URI の設計ではなく、コマンドの設計、という捉え方なんですね。

/find?id=masuda220&type=contact&format=xml

find( id, type, format ){}
というメソッドの設計をそのままだから、リソースの識別キーを設計する、という発想とは、別の考え方だよ、ということ。

リソース指向で、エンタープライズアプリケーションすべてをモデリングして設計することが良いのか、わからないけど、「関心事オブジェクト」の「現在の状態」を取得する、というニーズのモデリング・設計には、REST スタイルの GET 方式、つまり、URI(識別キー)の考え方が、ぴったりくると思っている。

階層パス、コンマ区切り、セミコロン区切り


5章の「リソースに名前をつける」も興味深い。

階層パス


これは、見慣れていますね。
/main/sub/sub-sub/sub-sub-sub/...
という階層構造で詳細化していく。

ツリー構造。
ファイル管理では、一般的なやり方ですね。

しかし、世の中、すべてがツリー構造で整理できるわけではない。
「階層」にすることが不自然なケースも多い。

ソフトウェアの開発をしていると、ディレクトリ構造、クラスパス、URL、...というように、木構造にどっぷりつかっている。

ただ、なんでもかんでも、ツリーで表現しようとすると、あちこちで不自然で、ぎこちないことが発生する。

コンマ区切りの列挙、セミコロン区切りの列挙


本の例から...

/position?latitude=36.313&longitude=124.234
よりも
/position/36.313,124.234


/colorpair?color1=red&color2=blue
よりも
/colorpair/red;blue

/articles?start=20061201&end=20071201
よりも
/articles/20061201-20071201

のほうが、わかりやすい(自然な記述)でしょ、という考え方。

コンマ区切りは、順番を表現したい場合 ( List だな )。
セミコロン区切りは、順番に意味がない場合 ( Set だな )。

from-to は、ハイフン区切りが自然。

できるだけ、日常の表現形式にあわせた URI 表記が良いといっている。

もっと、記述的に


まあ、普通の技術者は、?start=20060701&end=20061201 でも、わかりやすいと思うかな?

この本の考え方の本質は、もっと別のところにあると思う。

たとえば、期間を限定する方法として、 from-to ペアは、とてもなじみがあるやり方。
この機能を実現すれば、どんな、期間指定でもOK、というのが技術者の発想。

でも、実際の業務は、from-to ですべてやっているわけではない。

/sales/today
/sales/yesterday
/sales/thisweek
/sales/lastweek
/sales/thisyear
/sales/lastyear
...

という感じ。
もちろん、内部的には、from-to ペアの検索の仕組みを使えば、それでOK。

重要なのは、「関心事」の「識別キー」として、汎用的な from-to ではなく、

today
yesterday
thisweek
thisyear
...

という、もっと、記述的な表現のほうが、業務のニーズ、感覚にあっている、ということ。
事業の関心事、業務の関心事は、form=YYYYMMDD to=YYYYMMDD という形式ではなく、「今日」とか「今月」とか「今期」で表現するのが自然。

まあ、ユーザが、from-to ペアを希望することもあるけど、実際には、today とか thisweek のほうが、業務の関心事であることが普通だと思う。

内部の仕組みとして from-to ペアが有用でも、使う側から見た、業務の道具として、from-to ペアが良い識別方法とは限らない。

ここらへんの気配り、検討が、アプリケーションソフトウェアの分かりやすさ、使いやすさに大きく影響する。

URI (識別キー)の設計といっても、奥が深いし、どういう設計にするかは、「関心事」の把握・理解と直結しているわけです。

URI (識別キー)の設計は、アプリケーションの構造設計、あるいは「関心事の空間」全体の体系を設計する、ということです。

「知りたいこと」を提供する 【パターン】

エンタープライズアプリケーションは、「関心事オブジェクト」の状態を管理し、必要な時に、必要な情報を、適切な利用者に提供するための道具。

初期のモデリングは「知りたいこと」の把握から始める。
新規に登録したり、状態を更新する機能はもちろん大切だけど、基本の目的である「知りたいこと」を手に入れる、という利用シーンから出発してみる。

2つの提供方法


情報の提供方法は、2つある。

ひとつは、 REST スタイルの 「GET」方式。

ユーザが、「情報の要求( GET コマンド )」を発行する。
システムは、要求された情報を、一定の表現形式で、ユーザに送り返す。

もうひとつは、イベント駆動型の、「通知」方式。(メッセージの送信)。
システムは、関心事オブジェクトの状態が変化したら、それを表現する「イベント」メッセージを作成し、適切な宛先に送る。

知りたいことを適切に伝える

両方提供することもあれば、片方だけのこともある。

モデリングの基本手順としては、

・利用者(アクター)の洗い出し
・利用者が、どんなことに関心を持っているかを「関心事オブジェクト」として表現。
・利用者への情報の提供方法の検討 ( GET 方式 and/or 通知方式 )

GET 方式のモデリング課題


REST スタイルなので、基本課題は、たった(?)の2つ。 「URI」と「表現形式」。

URI = 識別キー


最初の課題は、「知りたいこと」に「識別キー」をつけること。
REST スタイルのサービスの URI 設計です。

大切なポイントは、

query 式 ( bankaccount-inqury/?bank=smartbank&number=1230012&type=balance ... ) ではなく、URI で設計すること。

この場合なら、
http://smartbank.com/japan/aoyama/1230012
のような設計になる。

スマート銀行の日本の青山支店の 口座番号 1230012 に関心を持っている、という設計。

ユーザの知りたいことを、 URI 形式で、特定できないケースもでてくる。
そこがポイントで、「URI形式で特定できる」ところまで、具体案をみんなで、考えることがたいせつ。

みんなで考える過程で、ぼんやりとした「関心事」が、「関心事オブジェクト」として、だんだん、明確になってくる。

表現形式


URI が、決まれば、その GET リクエストが来た時、何を返すかの「表現形式」を設計する。
XML ドキュメントの設計、ということですね。

アンチパターン


まず、表現形式(XMLドキュメント) の項目の列強から入るパターン。

これは、エンタープライズアプリケーション開発の世界に蔓延している伝統的な病気ですね。

「知りたいこと」の「識別キー」の設計をあやふやにして、「データ項目」の一覧を出したがる。

「顧客」に番号つけて、それで、 GET リクエストすると、100項目も200項目を、データが戻ってくる、というような設計。

「何が知りたいか」、この文脈では、「どんな項目が必要か」ということを、ほとんど考えずに、なんでもかんでも、「顧客」オブジェクト(テーブル、XML)に詰め込む。

仕様の追加や変更が増えるたびに、項目が膨らんでいる。

どこでも、誰でも目にしている、アンチパターンですね。
肥大化して、意味の不明な項目だらけになってきって、結果的に、だれも、理解も変更もできない、というパターン。

アンチパターンにならないために


大切なのは、「知りたいことはなんだ」という議論。

URI のパスの設計の中に、contactInfo (連絡先)とか、purchaseHistory (購買履歴)とか、をどう、埋め込んでいくか、という設計を、まじめに繰り返すと、このアンチパターンからのがれることができる。

設計の選択肢として、

contactInfo/顧客ID
purchaseHistory/顧客ID

にするか、

顧客ID/contakuInfo
顧客ID/purchaseHistory

にするか。

前者の場合だと、 contactInfo だけを指定した場合は、全顧客の連絡先を一覧がでてくる。
後者の場合だと、顧客ID だけを指定すると、その顧客について、提供可能な、 情報リソース、(連絡先とか、購買履歴)の一覧がでてくる。

どちらの設計が、現在のアプリケーションに、適切だろう?

こういう検討をみんなですることで、そのアプリケーションの「関心事オブジェクト」の姿が具体的になってくるわけです。

こういう議論を経て URI (識別体系、識別キー)が決まってくると、表現形式は、わりと単純に決まることが多い。

何に関心があって、何が別の関心事かは、 URI ( 識別キー ) 設計の段階で、具体的に議論されているから。

---

ちょっと、中途半端だけど、別件が入ったので、ここで、いったん投稿しちゃいます。

「状態の変化」のモデリング

エンタープライズアプリケーションは、関心事オブジェクトの「状態の変化」を扱うための仕組み。

その枠組みを、絵にしてみた。

状態変化のフレームワーク

3層構造


全体の構造は、REST スタイル、 イベント駆動、 データ中心 の三つの情報の扱い方を3段に積み重ねている。

REST スタイル


REST スタイルは、関心事オブジェクト(=リソース)の、「現在の状態」を GET したり、「意図する状態」を PUT する、モデル。

「現在の住所」を GET してきて、「新しい住所」に書きなおしてから、それを、PUT する、ことで、「関心事オブジェクト」の状態を変化させるパターン。

「状態」は、リソースそのものの状態ではなく、XHTML とか、 XML とかの形式で「表現(represent ) 」したもの、というところが、ポイント。 

状態をある表現形式にして、「 転送 (transfer) 」するというスタイル。

イベント・メッセージング


真ん中は、イベント駆動アーキテクチャ (EDA) スタイル。
イベントのメッセージングが、基本モデル。

アプリケーションの外部で発生した、何らかの変化が「イベント」メッセージとして送られてくる。
変更イベントを受信したら、イベントの内容に応じて、関心事オブジェクトの状態を変化させる。

振り込みが発生したら、残高を更新する、というパターンですね。

関心事オブジェクトの状態を変更したので、今度は、アプリケーションの内部で、「変更イベント」が発生する。
必要に応じて、そのイベントを、外部へ、送信する必要がある。

残高が更新されたことを、口座の名義人に、メールで通知する、ときのパターン。

記録


データ中心(DOA)の主な関心事。

記録する対象としては、

1. イベント・メッセージの受信の記録
2. 関心事オブジェクトの(変更後の)現在の状態
3. 関心事オブジェクトの変更履歴(=過去の状態)
4. イベント・メッセージの送信の記録

がある。

REST スタイルと イベント・メッセージング


両方とも、現在の状態を変更する。

大きな違いは、

◎ REST では、「状態」全体を、転送しようとする。
◎ イベントは、「必要最小限」の情報だけを送受信する。

ということ。

REST では、XML などで、情報「全体」を表現する形式を、設計することになる。

イベント駆動では、伝えるべき「最小限」の情報は何か、という設計をする。

また、REST は、 PUT する側は、「変更」を明確に意図している。

一方、イベント駆動では、「イベント」を送る側が、受け取ったアプリケーション側で、何が起きるかは、知らない。 そもそも、受け取り側のアプリケーションが、誰であるか、どんな関心事オブジェクトを管理しているか、ということすら知らない可能性がある。

メッセージングサービスは、イベントメッセージの発信側は、 End to End の通信を想定していない。

後続のサービスに、イベントを送信したら、それが、どこの誰に届くかは、知らない。

REST も、比較的、疎結合のスタイルだけど、イベント・メッセージングは、もっと、疎結合の仕組み、ということ。

記録


現実のアプリケーションでは、すべてのケースを、記録するとは限らない。

もっとも単純なアプリケーションでは、データベースに「現在の状態」を上書きするだけ。
これだと、変更の履歴が一切ない。メッセージの受信や送信の記録も残さない。

さすがに、エンタープライズアプリケーションだと、これではまずいことが多い。

基本的には、メッセージの受信送信の記録は残すべき。

ファウラーは、「 Domain Event 」パターン、それと関連する 「Event ソーシング」パターンで、面白いことを言っている。

だいたい、こんな感じのことを言っている:

>変更の動機となった、外部からの刺激(イベントメッセージ)だけを、
>永続化しておけば、十分かもしれない。
>つまり、「現在の状態」は、イベントの履歴から導出できるので、永続化の必要はない。

>もちろん、導出には時間がかかるので、
>「現在の状態」を、メモリ上に「キャッシュ」しておく。
>キャッシュのバックアップという意味で、データベースに書き込んでも良いが、
>アプリケーションの基本モデルとしては、
>「現在の状態は、永続化しない」という可能性がでてくる。

これ、なかなか興味深い議論。

状態の変化のフレームワーク


エンタープライズアプリケーションの中核課題である、関心事オブジェクトの「状態の変化」を扱うための仕組みとして、三層のモデルを提示してみた。

モデリングのためのツール


この枠組みは、ドメインの「モデリング」のパターンを考えるためのツールと考えている。

それぞれの要素(楕円)と、その間のアクション(矢印)を、具体的に、業務の関心事、やり方、ルールに当てはめながら、関心事オブジェクトの「状態の変化」を、具体的にモデリングするための手掛かり、として考えている。

例えば、関心事オブジェクトが、「銀行口座」であれば、

・「残高照会」は、REST の GET
・現金引き出し(の反映)は、 REST の PUT。
・外部からの振り込みは、 イベントで通知され
・振り込みで、残高が変わった場合、口座名義人にメールで入金通知がいく

そして(おそらく)すべての変化は、記録することになる。

関心事オブジェクトが、「本」の場合は? 「顧客」の場合は?、「to-do タスク」の場合は?

こういう例で、もう少し、具体的に、関心事オブジェクトの「状態の変化」のモデリングパターンを、追いかけてみようと思っている。

実装技術


この枠組みで、モデリングができれば、それは、そのまま、具体的な実装技術にマッピングができる。

REST 層は、もちろん、そのまま REST API として実装できる。
EDA 層のイベントの扱いは、 メッセージングサービス用のミドルウェア ( MOM ) とか、Mule ESB のようなフレームワークで実装できる。
データの記録層は、もちろん、データベースと、O-R マッピングのフレームワークなどが実装できる。

今回は、意識的に、「画面アプリ」、画面の MVC については、触れていない。
この「状態の変化」のモデリングの枠組みと、「画面アプリ」という実装技術の問題は、別の記事で書く予定です。

REST と画面アプリというテーマになるかな。

ドメインオブジェクトは 「固定」属性と「変動」属性を見分けるべし 【パターン】

エンタープライズアプリケーションの中核になる、ドメインオブジェクトは、その事業の関心事を表現した、「関心事オブジェクト」

関心事オブジェクト

識別キー


どの関心事か、特定するための、「識別キー」が必須。

注文オブジェクトだったら「注文番号」。
顧客が関心事だったら、「顧客氏名」。
本が関心事だったら、「本のタイトル」。
...

「固定」属性と「変動」属性を見分ける


関心事オブジェクトは、利用者の問い合わせに答えるために、さまざまな「属性」を持っている。

注文だったら、注文内容、出荷状況、代金回収状況。
顧客だったら、注文履歴、連絡先。
本だったら、内容説明、在庫数(販売可能数)。
...

いろいろな属性情報は、「変更」という視点で、2つのグループに分かれる。

(1) 変更されない=異常 という属性
(2) 変更されない=正常 という属性

例えば、注文内容は、変更されないほうが正常。
でも、出荷状況が、いつまでも、「未出荷」のままとか、代金回収状況が、いつもでも、「未回収」のまま、というのは異常事態。

顧客だと、「注文履歴」は、頻繁に追加されるのが、正常(期待していること)。 一年以上、履歴が更新されなかったら、異常(困ったこと)。

本は、内容説明は、通常は、変更しない。在庫数は、頻繁に変わるのが正常。
売れて、追加で仕入れて、また売れて、というのが正常な(あるべき)姿。

この違いは、アプリケーションのモデリング、設計・実装に大きな影響がある。

固定と変動を見分けない【アンチパターン】


ありがちなのが、ドメインのオブジェクトの属性に、すべて setter をつける。
テーブル設計も、すべてのカラムは、どれでも、随時 update することを想定。

ようするに、「なんでも、いつでも、自由に」変更、という設計・実装。

これは、事業のやり方からみると、かなり、杜撰(ずさん)な設計。

事業の関心事とか、業務のやり方を、うまく支援できる仕組みになっていない、典型的なアンチパターン。

事業を支援する道具である、エンタープライズアプリケーションは、もっと、「固定」属性の扱いと、「変動」属性の扱いに、気を配る必要がある。

固定属性も、変更する可能性はある。 変動属性は、もちろん頻繁に変更する。 だから、すべて、同じように「変更可能」にしておけば、良い、というのは、業務の知識が貧弱すぎる。

固定属性の変更


固定属性は、最初に設定する時とか、変更する時には、「申請」とか「承認」の手続きがからむことが多い。
また、通常は固定なので、それが「変化」した時は、影響を受ける部門とか、顧客に、変更を通知すべきことが多い。

そういう「固定属性」の「登録の手続き」、「変更の手続き」、「変更の検出と通知」には、いろいろな業務上のルール、取り決めごとがたくさんある。

あるいは、ある時点からは、完全に「確定」させ、変更をさせない、取り決めがある場合も多い。
例えば、「注文内容」は、出荷指示後は、数量変更は不可とする、というようなケース。

固定属性の変更は、単純に、 setName() とか、 update name とかだけ、設計・実装しておけば済む話ではない。

これは「固定属性」だな、という当たりをつけたら、その「登録手続き」「変更手続き」「変更に関するルール」について、業務の知識を、うんと増やしながら、モデリングと、設計・実装をやる。

それが、業務のための道具を造る、ということ。

変動属性の変更


変動属性は、変更が、正常だから、どんどん、更新するようにしておく。
しかし、こちらも話は簡単ではない。

事業においては、なんでも、いつでも、どうにでも、変更して良いわけではない。

出荷状況は、一定のルールにのっとって、状態が変化していく。
ある時、とつぜん「出荷済」になるわけでもないし、また、「出荷済」が、いきなり、「未出荷」の戻っていいわけがない。

杜撰なアプリケーションだと、更新画面から、こんな乱暴な変更ができてしまう。なんどもそういうのを現場で見てきた。

業務をやっている人たちが、使い方に気をつけて、ひどいことにならないようにしているけど、この造りだと、必ず、事故がおきる。

そいういうアプリケーションを造ってはいかんわけです。

「変更」属性も、「どうやって変更するか」「どんな変更は正常化?」「異常な変更は何か?」という業務知識を、徹底的に掘り起こしながら、モデリングと設計・実装を進める。

属性のグルーピング


固定属性も、変動属性も、「変更のタイミング」が同じになる、属性のグループがある。

例えば、「連絡先」は、基本は固定の属性。
ただし、引っ越しとかのイベントが発生すると、連絡先を表すさまざまな属性が、一斉に変化する。
郵便番号、住所、電話番号、...

こういう、変化が同じタイミングで起きる属性をひとつのグループにする。
そして、変化のタイミングが異なる、属性を別のグループに分ける。

「変化」の視点で、グループ分け【パターン】


この、「変化」のタイミングが同じかどうかは、オブジェクトやテーブルの粒度設計で、基本の着眼点です。

オブジェクトやテーブルは、「同じタイミング(同じ理由)」で変化する属性が集まったものにする。

だから、「連絡先」は、顧客オブジェクトの中に、「郵便番号」「住所」「電話番号」とかいう持ち方をしない。

「連絡先」オブジェクトとして、別にくくりだす。

そうすると、「連絡先の登録」とか「連絡先の変更」とかの業務のルールを、この連絡先オブジェクトに、集めることができる。

これが、良質なドメインオブジェクトをモデリングし、設計・実装する、良い実践テクニック、つまり、モデリングの「パターン」。

エンタープライズアプリケーションは、「状態の変化」を適切に扱うための

・業務知識の獲得
・モデリング
・設計・実装
・実現の技術方式(アーキテクチャスタイルやフレームワーク)

が、中心課題になる。

最近、書き始めている、エンタープライズアプリケーションのためのモデリングの「パターン言語」も、「状態の変化」の扱いが中心テーマ。

そしての、この中心課題を、うまく扱うためには、

◎ 固定の属性と、変動の属性を分けて考えること (変化が正常か、異常かで区別)
◎ 同じタイミング(理由)で変化する属性をひとつのグループにまとめること
◎ 異なるタイミング(理由)で変化する属性は、別のグループに分けること

というのが鉄則になる。

もちろん、属性のグループが、「オブジェクト」や「テーブル」の有力候補というわけだ。

これから、いろいろ書こうと思っている「状態の変化」を扱モデリングパターン(と実装の技術)は、この「鉄則」が、前提になります。

つまり、同じタイミング(理由)で変化する、ひとかたまりのドメインオブジェクトの「状態の変化」を扱うための、いろいろなパターンを書きたいと思っている。

SOA も、ロバストネス分析で

SOA というか、Mule ESB を使って、こんな感じのサービスを、いろいろ開発している。

Mule ESB サービス

一番、多いのは、DB to DB のデータ転送サービス。

データベースにレコードを書きこんだら、その「書きこみイベント」を、サービスに通知する。
サービスは、その結果は、別のデータベースへの書きこみメッセージとして通知する。
(実装は、 Mule ESB の JDBC endpoint を使えば、メッセージの検知・消費・生成方法を簡単に宣言できる)

通知は、SMTP でメール発信でも良い。
CSV ファイル読み込みの場合は、 CSV ファイルを読み取り、一行ごとに、 JMS メッセージを生成(送信)する、という方法で実現している。

この、Mule ESB を使った、メッセージングスタイルのサービスを、どうやって、「分析・設計」するか、いろいろ考えていた。

で、ICONIX のロバストネス分析、そのまま、使える、という発想にたどりついた。

メッセージング 予備設計

画面アプリ( Web アプリケーション ) は、MVC スタイル。

で、画面で、 submit ボタンを押す行為は、「メッセージの送信」ということ。
画面に、何か表示するのは、「メッセージの受信」ということ。

つまり、画面アプリも、メッセージングスタイルのアーキテクチャで考えればいいんじゃないかと。

そうすると、画面アプリも、ESBも、「サービスコンポーネント」に対するメッセージの送受信というモデルで、分析・設計できる。

私たちは、画面アプリの分析・設計は、ICONIX プロセスで、「ロバストネス分析」で、ずっとやってきた。
その方法が、そのまま、メッセージングスタイルのサービスにも、使えるのは、なかなか良い感じだと思っている。

アクターが「人」であれば、画面アプリ、アクターが、外部システムであれば、メッセージングスタイルのアプリ、というわけだ。

calendar
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< May 2010 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM