自分は元プロゲーマーで、今はAIを使いながらWeb開発をしています。エンジニアとしてはまだ初心者です。
要件を渡すと、DB設計から実装、テストまで進めてくれるので、かなり頼っています。ただ、出来上がったものを見直すと、自分がよく分からないまま受け入れている箇所もある。
最近引っかかったのが、DBに直接書かれていた上限値でした。ゲームのバランス調整に置き換えてみると、何がまずいのか分かりやすかったので、その話を書きます。
DBでもチェックしてくれるなら安心、と思っていた
ある機能で、法令によって決まる上限値を扱っていました。AIが作った設計には、イメージとしてこんなCHECK制約があります。DBに保存できる値を制限するものです。
CHECK (configured_limit <= 45)
これを見たときは「DBでも45を超えないようにしてくれるなら安全じゃん」くらいの感覚で、特に疑問を持ちませんでした。
でも、その45は法改正で変わるかもしれない。しかも、この一行だけでは数字の根拠も読み取れません。法令で決まっているのか、システムの都合なのか。意味の説明がない数字、いわゆるマジックナンバーを、そのままDBのルールにしていたわけです。
CHECK制約そのものが悪いわけではありません。「数量はマイナスにならない」のような、データとして変わらない条件を守るには向いています。今回まずかったのは、将来変わる数字を、根拠や更新方法を決めないまま固定したことでした。
ゲーム側は新パッチ、DBは旧パッチ
例えば、今のゲームで攻撃速度の上限が2.5だとします。それに合わせてDBにも、次の制約を入れる。
攻撃速度は絶対に2.5以下
次のパッチで上限が3.0になっても、DBには「2.5以下」の制約が残る。ゲームでは使える数値なのに、保存しようとすると弾かれます。
DBだけ前のパッチのまま。こう考えると、困る理由がすぐ分かる。
攻撃速度なら、バランス調整で変わることを前提に考えられるんですよね。法令の数字になると、自分は「今の正しい値を守らせる」ことしか見ていませんでした。
数字を変えるだけのつもりが、DBの変更になる
もちろん、制約の45を50に直すことはできます。ただ、そのためにDBの構造やルールを定義するschemaを変更し、その変更を反映するmigrationを用意して、本番DBに適用する必要があります。
本番には実際のデータが入っているので、変更前の確認も必要です。上限値を見直すたびにDB側の変更まで必要になるのは、運用することを考えると面倒です。
ゲームでいえば、キャラの数値を調整するのに、保存する側のルールまで毎回直すようなもの。最初に制約を見たときは、そこまで考えていません。
変わる数字は、適用時点と一緒に持つ
では、45のような数字をどこに置くか。一案は、ルールを有効開始日・終了日と一緒に管理し、登録時点でどのルールを使ったかもデータに残す方法です。法改正後に上限が50になっても、改正前のデータには当時の45が適用されたことが分かります。
PostgreSQLのCHECK制約から、こうしたルール用の別テーブルを直接参照することはできません。アプリ側で適用するルールを選び、使った上限値を対象データにも保存します。DBでも守りたいなら、対象値と適用時の上限値を同じ行に持たせて、例えば次のように比較できます。
CHECK (actual_value <= applied_limit)
これが唯一の正解というわけではありませんが、少なくとも「現在の上限値だけ」を固定するより、過去のデータがどのルールで作られたかを追いやすくなります。
次に設計を見るときは
法令や料金、プランの上限は、今は正しくても後から変わる。ゲームの攻撃力やスキルの数値なら当たり前に意識することなのに、DB設計では抜けていました。
「数量はマイナスにならない」のように、そのデータの意味として守りたい条件もあります。何をDBで保証するか考えるときは、数字が正しいかに加えて、何を根拠に決めた数字なのか、変わったらどこを直すのかも見ておきたいです。
AIはこれからも使います。自分だけでは書けないコードまで作ってくれるので。ただ、動いていると、理解できていない部分もついそのままにしてしまう。
全部を一度に判断できるわけではないですが、まずは出てきた数字の意味を確かめるところから。そのときに「ゲームの次のパッチでこれが変わったら」と置き換えると、自分には考えやすそうです。
