「単独主キー専用環境」と賢くつきあうために
「ORマッピングの功罪」の続きである。複合主キーが忌避される開発環境について、もう少しつっこんで考えてみたい。まともなORマッパーであればふつうに複合主キーを扱えるのにもかかわらず、ORマッパー上で組み立てられた開発環境ではしばしば複合主キーが非推奨とされる。なぜなのか。
その種の開発環境において、データ要件を「オブジェクト(クラス)構造」として認識し、それをRDBに落とし込むといった設計スタイルを実践することが前提になっているためだ。個別案件においてOOP(オブジェクト指向プログラミング)を使う余地が大きい開発環境ほど、この傾向が強まる。その独特なスタイルは、かつてはOOA/OODと呼ばれ、今ではDDDと名前を変えつつも(*1)、OOP使いの間で根強い人気がある。
その枠組みにおいてクラスの実際値(オブジェクト)は、RDBテーブルのレコードとして永続化(保存)されることになる。オブジェクトは暗黙的な単独主キー(オブジェクトid)で識別される。必然的に、その枠組みを利用する限り複合主キーは不要で、単独主キーだけでいいということになる。
オブジェクトの永続先としてRDBを持ち出す必要もないと思うのだが、オブジェクト間の存在制約が複雑でなければ、それなりに合理的な設計方針ではある。じっさいのところ、開発分野を限定すれば有用な実装手段であることに違いはなく、現代社会における貢献は小さくない。また、「開発環境そのものの開発者」にとって、単独主キーだけでよいという方針は喜ばしい。レコードを単独主キーのみで特定できるDB設計を前提することが許されるのであれば、開発環境内部の制御構造は単純な形で済むからだ。この種の環境を「単独主キー強要専用環境」と呼んでおこう。
単独主キー専用環境は、そういった「制限つきの便法」であるのだが、その経緯や機微が理解されていないと、Railsの開発者(DHH)のような「複合主キーへの痛烈な拒絶」の姿勢が生まれる(M.ファウラーによる関連記事)。DHHに言わせれば、「複合主キーなんか使うから、話がややこしくなるのだ」となるのだろう。しかしそれは、「構造計算なんかやるから、ビルの設計がややこしくなるのだ」みたいな暴論である。
言うまでもなく、項目が無駄に複合されているとか足りないといったキー設計は明らかな失敗だが、複合主キーでしか表現できないデータ要件も厳然として存在する。わかりやすい例で言えば、仕入先からの仕入価格は、仕入先と商品と開始年月が複合した概念「商品仕入契約」の属性であって、そのインスタンスは「仕入先ID+商品ID+開始年月」で識別される。そして、これら3項目の組み合わせが重複するようなインスタンスが存在してはいけない(ユニーク制約)。それらの項目値が更新されてもいけない(更新制約)。そしてこれらの制約は、サロゲートキーを導入しようがしまいが保全されなければいけない。
複合主キーを含むユニーク制約や更新制約を適切に設計することは、理論に従った正規化と並び、データ指向設計における重要課題である。データベースとは、ようするに「帳簿」であり、帳簿とは「何か」に関する記録の集合であり、その「何か」をユーザ視点で識別する手がかりが複合主キーとなるケースはふつうにある。
OOP好きからは「テーブルに別途ユニーク制約を置くなり、クラスの中に制約のためのロジックを盛り込むなりすればよいだけではないか」と反論されそうだが、それで話は済まない。そういったエンティティのまとまりやそれに適用される複雑な制約が、開発者自身によって見い出されない点こそが問題だからだ。そこらへんを他人に指摘されて反応するばかりでは、システムはまともな形で出来上がらない。
じっさい、OOA/OODやDDDをいくら学んでも、複合主キーを含むユニーク制約や更新制約を洞察できるようにはならない。「いかなる"何か"であってもクラス構造として認識・記述可能である」と考えることの限界がここにある。一定以上複雑な"何か"をソフトウエア開発の対象とするためには、開発者自身が"何か"についての専門家(ドメインエキスパート)でなければいけない。複合主キーを含む複雑なデータ構造を相手にするには、「帳簿組織に関する専門性」が求められる。これはオブジェクト指向を学ぶだけでは身につかない。
このへんの事情を知らないままで「単独主キー専用環境」を活用すれば、開発事業としても困ったことになる。複雑な制約を含むシステムの構築に挑戦して失敗することが、「みんなが通る道」となってしまうからだ。どんな開発環境においても、扱われる案件は遅かれ早かれ最適なサイズや複雑さを越える。事業というものは、みずからの業容拡大を狙う運動を止めないからだ。
しかも各事業者は、限界以上の案件を扱って「何度も」失敗することになる。なぜなら、事業者らが失敗経験を共有し合うこともないし、そもそも失敗の原因が「複合主キーを扱えない」という環境自体の特性ゆえであることが、彼らには想像しにくいからだ。そのため、「DDDの知見が足りなかった」とか「プロジェクト管理が甘かった」といった的外れな反省がなされて、同じような失敗が繰り返される。
単独主キーにこだわることを含めて、クライアントにとって使いづらく保守しにくい業務システム開発が生まれる原因の大半は、DB設計の拙さにあるというのが私の実感だ。何度か述べたように、複合主キーを効果的に用いて設計するのは簡単ではない。しかしだからといって、一見すると簡単そうな単独主キーだけを用いた設計スタイルに逃げ込んでも、問題が見えにくくなるだけで事態はさらに悪化する。もともとDB設計というものは高度な専門職であって、必要とされる職業適性や訓練はプロミュージシャンあたりに求められるものより敷居が低いわけではない――まずはそのことを認めよう。下手に手を出せば、まわりに大迷惑をかけるだけだ。
そういうわけで、単独主キー専用環境を使うかどうかに関係なく、開発事業としてやってゆくのであれば、複合主キーを含めてオーソドックスに設計して、その成果を必要に応じて「正規化崩し」するためのスキルを確保しておいたほうがいい。まさに「大は小を兼ねる」で、そのスキルがあれば、さまざまなサイズや複雑さの案件を扱えるからだ。少なくとも、単独主キー専用環境で生産管理システムあたりを構築するといった無謀は避けられる。まずは「どんなシステムであろうと、単独主キーのみでDB設計は可能である」といった思い込みを捨てよう。それは教訓さえ与えない厄災しかもたらさない。
*1.この解釈は誤解だとも言われている。DDD本の著者であるエリック・エバンスがそのつもりでなかったとしても、事例説明にOOPが使われた時点で、OOP好きな技術者によって「DDD=より洗練されたOOA/OOD」と誤解されることは、自然な成り行きだったのではないだろうか。
| 固定リンク
この記事へのコメントは終了しました。
コメント