設計者の発言

業務システム開発とデータモデリングに関する語り

Railsは新人教育に向いていない

 Rails(Ruby on Rails)はちょっとしたアイデアを形にするには便利な開発ツールである。扱われるテーブルを定義するだけで、CRUDアプリがサクッと出来上がる。私自身、このツールが登場した当時には、その独自の立ち位置や狙いの面白さに感心したものだ。Railsの解説書を書いた著者に京都まで行って話を伺ったのも楽しい思い出である。

  しかし、本格的な業務システムの開発者を育成するための開発環境として、残念ながらRailsはまったくといっていいほど向いていない。新人がこれを使うと、案件に含まれる精妙なデータ要件を洞察できないままで成熟してしまう怖れがある。

  どういうことか。Railsが「複合主キー」を否定しているゆえだ(使えないわけではないが後付け的で無理がある)。そのこと自体はツールのスタンスとして間違っているわけではない。一定のニッチはあるだろう。しかしそのスタンスが「複雑なデータ要件を伴わない案件」向けのものであることは、新人には想像できそうにない。

 そもそも「複合主キー」は日常的なデータ要件なので、これを含むものを「複雑なデータ要件」と呼ぶのも変だ。例を示そう。製造機械の機種毎に製品の「時間あたり製造数」を管理したいとしよう。生産管理システムではいかにもありそうなデータ要件だが、これは次のようなデータモデルとして表せる。複雑なところは何もない。

 Datamodel1_20200629101001

  多くの技術者が複合主キーの問題を「人工キーか自然キーか」に沿わせて議論していることが私には不思議でならないのだが、このモデルに人工キーか自然キーかの論点は存在しない。単に「複数項目の組み合わせに関数従属する項目が存在する」ことが淡々と示されているだけで、「自然キーはダメだから、複合主キーはダメ」といった粗雑な議論とは無縁である。

 ところが、Railsでキャリアを始めた技術者は、このデータ要件の本質部分をしばしば見落とし、次のようなモデルとして把握し実装する。

Datamodel2_20200629101001

 このテーブル構成では、機種IDと製品IDの同じ組み合わせを持つ複数レコードの存在が許される。遅かれ早かれ、矛盾した「時間当たり製造数」の登録を許してしまう。「時間当たり製造数」の矛盾であれば、製造作業の混乱程度で済むかもしれない。しかし、金額計算に関わる項目であればシャレにならない。

 機種IDと製品IDの組み合わせに対して「ユニーク制約」を付与すればいいだけの話と思われるかもしれない。甘い。機種IDと製品IDがあくまでも属性項目の位置づけであるため、遅かれ早かれそれらの値が更新されて(*1)、独特なアノマリー(更新時異状)が生じるからだ。

 この種のアノマリーはやっかいで、体の奥深くで静かに進行する癌のように気づかれにくい。たとえば、「機種別製品属性」の主キー(ID)を外部キーとして持つ、あるテーブル上の既存レコードを想像してみてほしい。これに対応する「機種別製品属性」上のレコードが”機種Aと製品Bの組み合わせでは、時間あたり75個”から”機種Eと製品Rの組み合わせでは、時間あたり75個”に更新されたとしたらどうなるだろう。明確な障害は生じないかもしれない。しかし、このなんとも名状しがたい不整合(不整合ではない可能性もないわけではないのがややこしい)が、広域に拡大するカオスの起点となり得る。

 なにしろ気づかれにくい不整合なので、「複合主キーなど使ったことはないが、問題が生じたことは一度もない」といった印象を設計担当者が持つことさえある。ようするに、重複の問題が指摘されるたびに対処的にユニーク制約を付与すれば済むという話ではない。そのお気楽さは、高層ビルの設計者が「傾いたらつっかえ棒をすれば済む」と語るようなものだ。

 重要なので繰り返そう。「機種別製品属性」の主キーをRailsの規約に従って単独主キーの{ID}とするためには、以下の2つの補完が欠かせない。(1)本来の主キーである{機種ID、製品ID}に対するユニーク制約を付与する。(2)機種IDと製品IDに対する値の更新を何らかの形で禁止する。これらはいかにも面倒ではあるが、「サロゲートキーの導入」という”正規化崩し”に伴って、開発者が引き受けるべき「報い」である。

 そもそもサロゲートキー(代理キー)というものはデータの取り回しを楽にするために、多めの項目を組み合わせた複合主キーを単独主キーに置き換える措置である。上掲の複合、主キーはたった2つの項目の組み合わせなので、わざわざサロゲートキーを導入する必要などない。

 ところが複合主キーを認めない開発環境では、サロゲートキーの導入が無条件に「強制」されてしまう。これは不自由だ。しかも悪いことに、これが正規化崩しの一環として意識されることはほとんどない。結果的に、上述した2つの「報い」のいずれかまたは両方が無視されて、システムはゆっくりと地雷原の様相を呈し始める。

 じっさいのところ、テーブルの主キーをすべて{ID}とする特殊な設計スタイルは単純明快で、新人には受けがよさそうだ。しかし指導に際してその「往きはよいよい帰りはこわい」的側面が説明されることはまずない。代わりに熱く語られるのは、複合主キーへの恨みつらみだったりする。しかしこれは建設会社が「いい加減な構造計算のせいで我々はさんざん苦労させられた。諸悪の根源は構造計算なのでこれを禁止する」と主張するようなものだ。巨大で複雑な工学構造物を生み出したいのであれば、構造計算なり複合主キーなりを確実に習得し、適切にエンジニアリングしなければならない。それだけの話である。

 まとめよう。本格的な業務システムを設計するには、複合主キーを含むオーソドックスなDB設計スキルと、必要に応じて正規化崩しするためのスキルが欠かせない。Railsを教材とする場合、これらの知識を伝えるのは難しい。誠実に伝えるほど「そもそもこの開発ツールで複合主キーが使えないのはなぜ?」といった根本的疑問を持たれかねないからだ。ゆえに、新人教育にRailsは使わないほうがいい。繰り返すが、Railsが悪いわけではない。この種のツールは、基礎的なスキルを習得した後で、さまざまな実装手段のひとつとして身につけるべきものだ。

 

*1.主キー項目の値の更新を許すRDBMSも存在するため、主キーとすることで値の更新を抑止できるとは言い切れない。しかし、主キー値の更新を許すシステムを設計しているとすれば、本テーマ以外の地雷が方々に埋め込まれていると考えていい。2つ目のモデルで主キーの値が更新されることを想像すれば、その異常さはよくわかるだろう。よほど特殊な処理要件でない限り、主キー値の更新を許してはいけない。