26個目のアンチパターンについて『SQL アンチパターン』

SQLアンチパターンを発売日に買って、それなりに熱心に読みました。
これはどえらい本が出てきたなってことで、理解を深めるため、関連する3つのイベントに片っ端から参加しました。

一つ目は DevSumi のセッション
SQL アンチパターン – 開発者を待ち受ける25の落とし穴( 2/15 )

二つ目はジュンク堂のトークセッション
データベースを巡る世代間闘争( 2/21 )

三つ目は DevLove #110
SQL アンチパターン・レトロスペクティブ -データベース危篤患者の救出-( 2/26 )

三つめのイベントで「みなさんも26個目のアンチパターンを考えてみて下さいね」という趣向があったので、わしも一つ提案してみようと思います。

26個目のアンチパターン

名前

オーバードライ(やりすぎDRY)

目的

重複する定義の排除

アンチパターン

<例1>
「amount が色んなテーブルに定義してあるのは冗長なので、amounts テーブルを作って、各テーブルには外部キーとして amount_id を持たせましょう。amount 属性の値を入れたい時は、まず select id from amounts して、見つかったらその id を外部キーにします。見つからなかったら insert します。その後、改めて select すれば、id が得られるはずなので、それを外部キーにします」
というような事をしてしまうと、
「こっちのクラスで想定している amount は 1000 未満に制限したいんですが!」
「でも、こっちのクラスの amount は 1000 の倍数じゃないとダメです!」
「矛盾してる\(^o^)/ 」
という事態になりかねません。

<例2>
「住所と名の付く属性は addresses テーブルへまとめて、必要なテーブルから参照しましょう。addresses テーブルの属性は、住所を必要とするテーブルのニーズを全部カバーしましょう」
というような事をしていると、
「こっちのクラスの住所には郵便番号が必須ですよ」
「でも、こっちのクラスからは郵便番号が入力出来る保証が無いので NOT NULL 付けるのはやめてください」
「矛盾してる\(^o^)/ 」
という事もしばしば。

アンチパターンの見つけ方

「とにかく、同じ名前の属性が無いかどうか、徹底的にチェックしよう」
という号令で、機械的にまとめていると、事故が起こりやすい気がします。

アンチパターンを用いても良い場合

当該属性が、ドメイン的に同一の概念である事が考慮されている場合には、何とか使えなくも無い気がします。ただ、数量のようなものまで共通化してしまうと、check 制約などを付けたいときなどに困るでしょうし、何より、使いにくいです。

解決策

共通のテーブルを定義するにあたって、文脈によって必須であったりそうでなかったりする属性については、用途に応じて特化したサブテーブルを作る事によって対応するといいでしょう。例えば、郵便番号が必須なクラスが必要としていた「住所」というのは、実は「配送先」であったというような事です。サブクラスとして「配送先」を作れば、矛盾を避けることが出来ます。
『「分ける」ことは「わかる」こと』と言われることがあります。ドメインの分析をきちんと行って、同じものは同じに、違うものは別に、という分別をする必要があるという事でしょう。

感想

私のいたグループで、この話をしていたところ、和田省二先生がいらっしゃり、「住所テーブルの話ですか?本来、住所ってのは、緯度経度ですよ!」という話をされはじめて、どひゃあ!ってなりました。その後、「サブテーブルを作って余計な属性を追い出す」という本件の解決策について、教えて頂きました。ありがとうございました。

27個目のアンチパターン

名前

シックスセンス(第6正規形)

アンチパターン

こちらは名前のみの出オチで、アンチパターンと言うと語弊がありますが、付録 A.3.7 に「Bugs テーブルが完全に第6正規形をサポートするには、ほぼ全ての列に個別の履歴テーブルが必要になり、テーブル数が過剰に増えてしまいます。第6正規形は、ほとんどのアプリケーションにとって過剰な正規形です。ただし、データウェアハウスの一部では、第6正規形が使用されています」と書いてありましたね。
HBase なんかでも素でカラム毎の履歴保存をやってくれたりするみたいなので、本当に履歴にこだわるならそういうモノを使う事も検討に値するでしょう。

カテゴリー: イベント パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください