> 設計というよりも実装の話ですよね?

実装(制限)に合わせた設計を要求されるということある。
これは、実際のデータモデリングとは異なるスキーマ定義を
しなければいけなくなることがある、ということを意味する。

> RDBの場合は親と子の間に双方向リンクが張られているのと同義になると思い
> ます。オブジェクト指向で言う「ポインタを辿る」という操作は、RDBでは
> 「left outer join」に相当するわけだし。

left outer join を使うこと自体がトリックなのである。
left outer join はポインタを辿る操作であるが、A left outer join B とは
"A から B を辿る" ことを意味する。>>151 で例示した問題では、
"伝票明細 left outer join 伝票ヘッダ" としか書くことができない。
これは、子から親を辿っていることに他ならない。

ここで、ひとつ考えてみて欲しい。その元となる子(伝票明細)の集合は
どのようにして集めるのだろうか? 伝票番号=123 を取り出したいとき、
伝票番号=123 を持つ伝票明細を取り出し、外結合によって伝票ヘッダを
辿ることになる。これは明らかに問題が前後している。伝票ヘッダを辿る前に、
伝票ヘッダの主要素である伝票番号を伝票明細は利用しなければならないのだから。

RDB の設計に慣れた人間ほど、この問題を意識することができない。
得たい結果から、無意識のうちに RDB式のスキーマ設計を行えるようように
訓練されてしまっているからだ。

この伝票問題の設計において、ルーキーが次のような愚かな設計をすることがある。
伝票 1枚あたりの明細数が最大10明細であると決めうち、伝票ヘッダに
伝票明細1行目, 伝票明細2行目, ・・・, 伝票明細10行目 と子へのポインタを
持たせてしまうのだ。これは RDB の設計としては明らかに誤りである。
正規化されていないために、商品A を購入している伝票を検索することが
できなくなってしまうのだから。

しかし、この発想を頭ごなしに否定してはいけない。この発想こそ直接的モデル化なのである。
発想自体は非常に分かりやすく直感的なものである。ただ、RDB においてはスキーマで
表現できないために、「誤り」として否定せざるを得ないだけのことである。このルーキーの
設計を馬鹿にする前に、この発想を直接的にモデル化できない RDB の制限についても
考えてみてもらいたい。RDB がモデル化において完全ではないことが次第に見えてくる。