🦍

DBスキーマはtblsのViewpointsで整理しよう

2023/12/05に公開

tbls はいいぞ 🦍

筆者は tbls の大ファンであり、特に Viewpoints 機能が他のツールとは一線を画していると思っています。今回はその良さをお伝えできればと思います。

TL;DR

  1. tbls は実際のスキーマから DB のドキュメントを生成するツール
  2. ER 図が巨大化しても、tbls の Viewpoint ごとに分割することで DB の全体像が理解可能になる
  3. Viewpoint の粒度に困ったら一旦トランザクションと集計の単位に設定する
  4. 個別のテーブルと Viewpoint は相互に参照できる
  5. CI に組み込むことでドキュメンテーション忘れを防げる

なんのために DB のドキュメンテーションを行うか

DB のドキュメンテーションはそれなりにコストがかかるため、おざなりにされることも少なくありません。
しかし、下記のようなケースを考えるとドキュメンテーションは必須であると言えるでしょう。

  • 再来月の全て忘れた自分が思い出すため
  • 開発チームに新規参加したメンバーがキャッチアップするため
  • 運用チームが SQL で DB にアクセスしてトラブルシュートするため
  • 解析チーム、データ基盤チームが既存の DB の内容を理解するため

よくある DB ドキュメンテーションの課題

DB のドキュメンテーションは下記のような課題を抱えていることが多いです。

  • メンテナンスされない
  • 存在が知られていない
  • ER 図が大きすぎて読めない
  • そもそも存在しない

tbls というツールを使うと上記のような問題が軽減され、簡単に有用なドキュメントをメンテナンスできます。

tbls を使う

tbls とは

https://github.com/k1LoW/tbls
https://speakerdeck.com/k1low/phpconfuk-2023?slide=7

  • 既存の DB スキーマから ER 図、テーブル一覧、テーブル詳細などのドキュメントを生成
  • Markdown 形式なので GitHub のリポジトリから参照でき、ホスティングが不要
  • カラムコメント、テーブルコメントの有無などを検証
  • CI への組み込みが容易
  • Viewpoints 機能が非常に強力

tbls によって生成されるドキュメント

tbls docコマンドを実行すると、DB スキーマからドキュメントが生成されます。
実際に生成されたドキュメントは下記のような形で見えます。
(※今回のスキーマは架空の通販サービスの DB を想定しています。筆者は通販サービスの設計をしたことがないため、ドキュメント内の内容についてはご容赦ください。)

リポジトリはこちらです。
https://github.com/majimaccho/prisma-tbls

トップのドキュメント

最も上位の全体観を表すドキュメントがREADME.mdという名前で生成されます。
トップのドキュメントには Viewpoints とテーブル一覧、ER 図が含まれます。
下では説明のために分割していますが、Viewpoints〜ER 図まで 1 つの README.md ファイルです。
ひとつのファイルとしてみたい方はぜひ上のリポジトリのリンクからご確認ください。

Viewpoints

viewpoints

Viewpoints というのは tbls 独自の概念で、DB のスキーマを任意のまとまりに分割できます。
DDL での設定ではなく、tbls の設定ファイルの YAML に記述します。
この Viewpoints 機能が非常に強力で、DB のスキーマを理解するのに役立ちます。
この機能は他のツールにはない機能で、tbls を使う大きなメリットの 1 つです。

Viewpoints を設定している場合、生成された README.md の最上部に Viewpoint の一覧が来ます。
Viewpoints には任意のテーブルのまとまりを定義でき、tbls の設定ファイルの YAML に記述することで自由に追加できます。
Viewpoint の一覧を見ることで、その DB に格納されているデータの概要を理解するのに役立ちます。

テーブル一覧

tables

ER 図

ER 図のフォーマットは svg, png, mermaid などから選べます。今回は mermaid 形式にしています。

erd

トップのドキュメントの ER 図はテーブル数が非常に大きくなりやすく、プロジェクトの早期にも理解が難しくなります。この問題は Viewpoints 機能が解消してくれます。

個別の Viewpoint のドキュメント

トップのドキュメントにある、Viewpoint 一覧のそれぞれの名前は個別の Viewpoint のドキュメントへのリンクになっています。
個別の Viewpoint のドキュメントには下記の内容が含まれています。

  • 概要
  • 内包するテーブルの一覧
  • 内包するテーブルの ER 図

テーブル一覧のコメントの列には実際に DB のスキーマ上に DDL で定義されているテーブルコメントが入ります。

viewpoint1
viewpoint2

DB 全体のテーブル数が膨大になり、テーブル一覧や ER 図自体を読み解くことが難しくなっても、Viewpoints を糸口に全体像を理解し、個別のテーブルに意識を向けることが自然とできるようになります。

個別のテーブルのドキュメント

各ドキュメントのテーブル一覧の各テーブル名は個別のテーブルのドキュメントのリンクになっています。
個別テーブルのドキュメントは下記の内容を含んでいます。

  • 概要(テーブルコメント)
  • カラム一覧
  • Viewpoints
  • 制約一覧
  • インデックス一覧
  • ER 図

また、親テーブルや子テーブル、Index やその他の制約が確認でき、各カラムにはカラムコメントが対応して表示されています。

table1
table2
table3

ここで強調したいのは個別のテーブルからそのテーブルを含む Viewpoint を一覧で見られる点です。[1]
複数文脈で利用されるテーブルがどのように参照されるかを一箇所見るだけで把握できるようになります。
これは作成や参照のユースケースを知ったり、Viewpoints 同士の関係性を理解するのに役立ちます。

Viewpoints の設定の仕方

Viewpoints は tbls の設定ファイルの YAML(.tbls.yml)に下記のような形で記述します。

キー 説明
name Viewpoint の名前
desc Viewpoint の説明
tables Viewpoint に含まれるテーブルの一覧
# .tbls.yml
# 他の設定は省略
viewpoints:
  - name: 書籍の購入
    desc: >
      書籍を購入する際に関連するテーブルのまとまり。
      顧客が購入できるためには、配送先が設定される必要がある。
      配送時に参照される製品コードはproductsテーブルから取得される。
    tables:
      - books
      - products
      - customers
      - shipping_addresses
      - orders
      - order_items
  -  # 省略

上記の設定以外にも group を設定したり、ラベルを設定したりできます。

Viewpoints 機能を(筆者は)どのように使うのか

Viewpoints を設定する単位

Viewpoints を設定する単位は組織やプロダクトの規模や構成によって異なります。
個人的には Viewpoint はトランザクションと集計の単位で設定すると悩まずに設定できると考えています。
トランザクションと集計の範囲ごとに Viewpoint があることで、作成時の整合性の担保しなければいけない範囲を明示できます。
テーブルごとの Viewpoint 一覧を見るときにもある程度、細かく、かつ意味のある単位になっている方が、変更時の影響範囲を特定するときなどに有用です。

プロジェクトの規模が大きいときにはこの粒度では小さすぎることもあります。
その場合、全体観がわかりやすいようにするためにより大きい粒度で Viewpoints を設定することを検討してください。

Viewpoints を通して DB を"みる"

Viewpoints は以下の内容のために役立ちます。

  • 全体像の把握
  • テーブルの意味的なまとまりの理解
  • 個別のテーブルの参照され方の理解

全体像の把握

巨大化したプロジェクトにおいて、テーブル一覧と ER 図をそのまま理解することは困難です。
テーブル数が 3 桁になるとノート PC のモニターで ER 図を見るとテーブル名を見ることも難しいでしょう。
その代わりに、Viewpoints の一覧が全体像の理解を進めます。テーブルよりも大きな粒度でデータを認識できるため、認知負荷が低いです。個別のテーブルを見に行く前の入り口の役目もはたします。

テーブルの意味的なまとまりの理解

Viewpoints はデータのまとまりを表現できます。
個別のテーブルとその親子テーブルが見えるというのは他のツールでもありますが、任意のまとまりを設定できることでドキュメンテーションの柔軟性が高まります。

個別のテーブルの参照され方の理解

また、個別のテーブルがどの Viewpoint から参照されているかがわかることも読み手にとって有益です。これにより、個別のテーブルに関連する部分を変更する際の DB レベルでの影響範囲を確認できます。

テーブルコメントに何を書くか

tbls を利用している場合は特に下記のような内容をテーブルコメントに設定すると有用です。

  • テーブル名の補足(和訳/どの画面/機能の名前と対応するなど)
  • 親テーブルとの関係
  • テーブル名からは推測できない周辺の文脈

これらがコメントとして設定されていると、上述の各ドキュメントで参照される際に、内容を理解しやすくなります。
特にテーブルコメントは tbls のドキュメント生成においては重要な位置を占めます。
トップのドキュメントや Viewpoints のドキュメントのテーブル一覧でも表示されますし、個別のテーブルのドキュメントの概要の部分に当たります。

カラムコメントに何を書くか

筆者がカラムコメントを設定する際には、下記のような内容を設定することが多いです。こちらは一般的な内容かと思います。

  • カラム名の説明(和訳/どのフォーム・表示の項目と対応するかなど)
  • 入る値の期待値、ルール
  • カラム名からは推測できない周辺の文脈

リント機能

tbls はドキュメントの生成だけでなく、tbls lint コマンドを使うことで DB スキーマに対してリントを行うことができます。
こちらで、筆者のおすすめのリントルールを 3 つご紹介します。
これらのリントルールを活用することで、ドキュメントのメンテナンスが忘れられてしまうことを防ぎ、tbls から生成されるドキュメントをより充実させることができます。

requireColumnComment(カラムコメントの必須化)

カラムコメントが設定されていないカラムがあるとリントエラーになります。
どのカラムに設定されていないかを出力してくれます。
オプションでid, created_atなど任意の名前のカラムを対象外にできます。

requireTableComment (テーブルコメント必須化)

requireColumnComment のテーブルコメント版です。
テーブルコメントが設定されていないテーブルがあるとリントエラーになります。

requireViewpoints (Viewpoints 必須化) [2]

こちらはスキーマのリントではありませんが、Viewpoint の設定を検証してくれます。
全てのテーブルがそれぞれ 1 つ以上の Viewpoint に属していなければリントエラーになります。

これらの他にも、カラム数の制限や、制約のコメントの必須化などいくつかリントルールがあるので詳しくは公式 README をご確認ください。

https://github.com/k1LoW/tbls?tab=readme-ov-file#lint

CI への組み込み

tbls は CI に組み込むことでより有効に活用できます。
上記のリント機能はもちろん、tbls diffコマンドで既存のドキュメントと、実際の DB のスキーマから生成されるべきドキュメントの差分を検出してくれるため、コミット忘れを防ぐことができます。

GitHub Actions を利用する場合、下記のようにするとリントと差分の検出が行えます。

# .github/workflows/doc.yml
jobs:
  runs-on: ubuntu-latest
  steps:
    - name: Checkout .tbls.yml
      uses: actions/checkout@v3
    #
    # SET UP YOUR DATABASE AND RUN ALL MIGRATION
    #
    - uses: k1low/setup-tbls@v1
    - name: check diff of tbls documents
      run: tbls diff # ドキュメントのコミット忘れの検出
    - name: lint your schema
      run: tbls lint # リントの実行

最後に

tbls の Viewpoints は競合のドキュメント生成ツールと比較しても、一線を画す機能です。導入〜CI 構築までもかなりお手軽にできるので読者の皆様も試していただけると 1 人の tbls のファンとして嬉しいです。


MICIN ではメンバーを大募集しています。
「とりあえず話を聞いてみたい」でも大歓迎ですので、お気軽にご応募ください!

https://recruit.micin.jp/

脚注
  1. この機能は筆者が Viewpoints 機能のことを好きすぎてコミットした機能です。(その 1)
    https://github.com/k1LoW/tbls/pull/532 ↩︎

  2. この機能は筆者が Viewpoints 機能のことを好きすぎてコミットした機能です。(その 2)
    https://github.com/k1LoW/tbls/pull/517 ↩︎

GitHubで編集を提案

Discussion