データモデリング初学者がイミュータブルデータモデリングを実践してみて感じたこと

こんにちは、新卒エンジニアの川本です。

BUYMAのサーバーサイドを中心に開発しています。

この記事はEnigmo Advent Calendar 2022の12日目の記事です。

データモデリングについて学習中で、DB設計の入門書を読んで論理設計について第1~5正規化といった内容を学習しましたが、いざ個人開発でデータモデリングしようとしたらどうしたらいいのかよくわからず、手を動かすことはできませんでした。

そんな状況の時にイミュータブルデーモデリングというモデリング手法について知ったことをきっかけけに、データモデリングがイメージしやすくなりました。

この記事ではイミュータブルデーモデリングを実践してみて感じたことを紹介できればと思います。

目次

データと情報の違い

データと情報には以下の違いがあります。

  • データ
    • 客観的な事実を記録したもので、文脈や解釈がない
    • RDBに記録される
  • 情報
    • 文脈や解釈の与えられたデータ
    • SQLで抽出する

この違いから正確な情報が必要ならデータが正確に記録されていなければならないことがわかると思います。

イミュータブルデーモデリングとは

イミュータブルデーモデリングとは、データを失わずにRDBに正確に記録できるように、更新と削除がなるべく起きないようにデータモデリングすることです。

更新と削除が起きるということは、データが変更された、失われたということです。 つまり、正確なデータをすべてRDBに記録できていないことになり、必要な情報を抽出できない可能性が出てくるということです。

イミュータブルデーモデリングの手順

ここでは、イミュータブルデーモデリングを実践したことで、正規化について理解が深まった瞬間があったので例を交えて紹介できればと思います。

詳しい手順が知りたい方は以下の記事がすごくわかりやすいです。 scrapbox.io

エンティティはイベントとリソースにに分類される

分類の判断には、エンティティが日時属性を持つかどうかで判断できます。 日時属性を持つエンティティはイベントエンティティに分類されます。

エンティティに対して、「~する」という動詞をつけてみると識別しやすいです。 例えば「会員する」という日本語は不自然ですけど、「注文する」という日本語は自然です。 ここから注文はイベントエンティティで会員はリソースエンティティであることがわかります。

今回はこのイベントエンティティについて少し深ぼって説明していきます。

イベントエンティティには日時属性を1つだけ持つようにする

イベントは1つの日時属性を持ちます。 例えば、注文エンティティなら注文日時を持ちます。

ここで以下のような設計の注文テーブルがあったとします。

上記の注文テーブルは、注文日時の他に請求日時、入金日時、更新日時を持ってしまっています。 これはこの注文テーブルの中に、以下の異なるイベントが混在していることを示しています。

  • 請求
  • 入金

これらは別のイベントエンティティである請求エンティティ、入金エンティティとして分解することができます。

そうすると以下のように設計することができます。

こうすることで、請求や入金が発生しても注文テーブルをUPDATEする必要なく、それぞれのテーブルへのデータのINSERTのみでデータを記録することができます。

ここまでの流れは実はOne Fact in One Place(1つの事実は1つの場所に)という正規化の行為そのものとなっています。

第1~5正規化を意識しながら初学者が正しく正規化するのは難しいと思いますが、ここまで紹介した手順だとまだイメージがつきやすいのではないでしょうか。

普段Railsで開発していて感じたこと

Railsで普段開発をしていると更新日時をもたないことは違和感があるかもしれません。

Railsでscaffoldすると更新日時カラム(updated_at)が自動で入ると思います。

order(注文)リソースをscaffoldする。

$ rails g scaffold order amount:integer

自動的に作成日時(created_at), 更新日時(updated_at)が入る。

# == Schema Information
#
# Table name: orders
#
#  id             :bigint           not null, primary key
#  amount         :integer          not null
#  created_at     :datetime         not null
#  updated_at     :datetime         not null
#
class Order < ApplicationRecord
end

これはRailsがWEBシステムで必要なのは、最新のデータだけであるという制約を設けていて、UPDATEが起こること前提の設計になっているからだと思われます。

この強い制約を設けることでUPDATEやDELETEを許容する代わりに、たいていのことはデータベースと1対1となったModelのCRUDで表現できるというシンプルさを手に入れることができます。

Modelに書くことができず、Serviceクラスが肥大化したりするのはデータモデリングの設計が悪い可能性が高いそうです。

このあたりは以下のPodcastで詳しく説明されているので、聞いてみてください。 anchor.fm

イミュータブルデーモデリングとの向き合い方

イミュータブルデーモデリングで考えると、イベントをエンティティとして捉えることからエンティティの数も増え、INSERTのみで記録することからデータ量も増えます。

そうすると、論理設計の段階では問題なかったかもしれませんが、いざ物理設計する際に実装を考慮するとパフォーマンスの問題に直面することもあるかと思います。

イミュータブルデーモデリングはデータモデリングにおける正解ではなく、一種の論理設計をする際の制約として捉えるといいと思います。

考え方としては以下のような順番かと思います。

  1. イミュータブルデーモデリングで論理設計する。
  2. 物理設計の段階で実装を考慮するとパフォーマンス的に厳しい箇所が見つかる。
  3. 問題となる箇所に対してUPDATEを許容する。

最後に

イミュータブルデーモデリングはデータモデリングにおける正解ではなく、一種の考え方です。

私のように初学者でデータモデリングに対して苦手意識がある人は一度イミュータブルデーモデリングについて調べて実践してみるといいかもしれません。

興味がある人は、WEB+DB PRESS Vol.130のデータモデリング特集を面白いので読んでみてください。 gihyo.jp

こちらの楽々ERDレッスンという書籍も実践的な内容が多くおすすめです。 www.shoeisha.co.jp

明日の記事の担当は インフラエンジニア の 山口 さんです。お楽しみに!


株式会社エニグモ すべての求人一覧

hrmos.co