56:有意コードをなるべく定義しない

仕様的に必要とされる「 有意コード 」にも罠が潜んでいます。 この問題と解決方法を見ていきましょう。

具体的な失敗

ここでは有意コードとは「商品コード」のような一意な値を決めるときに「1桁目は商品の区分、それ以降が商品ごとの数値」のようにコードの桁数によって複数の意味を持たせることを言います。 たとえば次のようなものです。

  • FD10001: FDが商品の区分、10001が商品の番号

  • A2019101: Aが記事のカテゴリー、201910が作成の年と月、1が記事ごとの番号

商品(Item)のカラムとして「商品コード」という値が必要とします。

class Item(models.Model):
    code = models.CharField("商品コード", max_length=16, unique=True,
                            help_text="1桁目が商品区分、2〜7桁目が登録日、残りが一意な番号")

ここで、以下のように有意コードに依存したプログラムを書いてはいけません。

Item.objects.filter(code__startswith="A")  # 商品区分がA(家電)の商品を取り出し
Item.objects.filter(code__contains="201105")  # 20年11月5日に登録された商品の取り出し

有意コードの「桁の意味」を使って検索するとLIKE検索になるので遅いのが問題です。 INDEXが効かなくなる場合もあるので、プログラムしないよう気をつけましょう。 有意コードには外部キー制約が使えないので、「商品区分から商品一覧を取得する」処理も遅くなります。

また単純に、有意コードから値を取り出す処理が頻発してプログラムが汚くなります。 商品区分を意味して item.code[:2] というプログラムを書かれても、商品コードの仕様を知らない人にはピンとこないでしょう。

ベストプラクティス

アプリケーションの仕様上必要ないのであれば有意コードを定義しないのが理想です。 有意コードが必要な場合は、検索や制約の条件として使わないようにしましょう。 商品コードは、他に存在する情報から自動で作られる値にします。あくまでシステム運用上、人間が使うためだけに用意します。

cover

(中略)詳細は書籍 自走プログラマー をご参照ください