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]
というプログラムを書かれても、商品コードの仕様を知らない人にはピンとこないでしょう。
ベストプラクティス¶
アプリケーションの仕様上必要ないのであれば有意コードを定義しないのが理想です。 有意コードが必要な場合は、検索や制約の条件として使わないようにしましょう。 商品コードは、他に存在する情報から自動で作られる値にします。あくまでシステム運用上、人間が使うためだけに用意します。
(中略)詳細は書籍 自走プログラマー をご参照ください