Decomment (でこめんと) on Intro

Decommentとは?

こんなシチュエーションで使います

  1. ディベロッパーが、SchemaHTML見ながらテーブルやカラムのことで悩んでる
  2. ディベロッパーが、わからないことを誰かに質問して知る
  3. ディベロッパーが、"ちゃんとDBコメント書いてあったらすぐわかったのに..." と思う

ズバリなに?

SchemaHTML上で "DBコメント" を追加・修正する、DBFlute Intro の機能 です。

複数人で追加・修正してもgitコンフリクトを起こさずマージできる のが特徴です。

SchemaHTMLでデコメント DBFluteIntro Decomment OpenDialog

えっ、なに?

ERDツール (ERFluteなど) を開かなくても、普段開発中にでよく見ている SchemaHTML で、各ディベロッパーが "こんなコメントがあったらもっと早くわかったのになぁ" と思った瞬間にDBコメントを記録することができます。

gitのブランチも、わざわざ専用のDB変更ブランチなどに切り替える必要はなく、 それぞれのディベロッパーのトピックブランチで作業できます。(同じテーブル、同じカラムのコメントを複数人で修正しても、gitコンフリクトは発生しません: 後述)

ERDツールじゃダメなの?

通常、DBコメントの追加は、ERDドリブンの開発であればDDLを出力するERDツール (ERFluteなど) から追加します。ただ、ERDツールはDBコメントの 気軽な 追加にはあまり向いていません。

  • ERDの保存ファイルは一般的にマージはできない (専用のブランチに切り替える必要あり)
  • そもそもERDツールの起動してからテーブルとカラムまで行くまでとても気軽ではない

Introはどう関係しているの?

DBFlute Introが、入力されたDBコメントを受け付ける中継サーバーとなって、DBFluteクライアント内に保存をします。 詳しくは、また後で。

  1. ディベロッパーが、DBFlute Intro経由で SchemaHTML を開く
  2. ディベロッパーが、SchemaHTML でテーブルやカラムのDBコメントを追加・修正する

Decommentの使い方

DBFlute Introを起動

manage.sh|bat の 88 (intro) を実行して、Introを起動しましょう。

SchemaHTMLを起動

Intro の Operate 画面の、SchemaHTML リンクをクリックします。

Operate画面のドキュメントリンクあり DBFluteIntro Operate LinkDoc

すると、SchemaHTMLが表示されます。

SchemaHTMLのExample SchemaHTML Example

そもそも、まだ SchemaHTML が存在しないのであれば、自動生成しましょう。

デコメントの登録

SchemaHTML上の任意のテーブルやカラムのコメント欄をクリックすると、ダイアログが開きます。

デコメントのダイアログを開く DBFluteIntro Decomment OpenDialog

テキストエリアで何か入力して...

デコメントのダイアログで入力 DBFluteIntro Decomment Input

OKするとデコメントが登録され、すぐに反映されます。

デコメントが表示された! DBFluteIntro Decomment Displayed

gitでpieceファイルをコミット

登録されたデコメントは、DBFluteクライアント内に "pieceと呼ばれるファイル" (詳しくは後述) で保存され、そのpieceファイルをgitでコミットすることで他の人に共有されます。

ただし、この時点では、Intro経由で SchemaHTML を開いたときだけデコメント (追加した分のコメント) が表示されます。 ブラウザで直接SchemaHTMLを開いても表示されるようになるのは、まだこのあと "Docタスク" 叩いた後です。

DocタスクでSchemaHTMLに固定化

ブラウザで直接SchemaHTMLを開いても表示されるようにするためには、Docタスク 叩きます。 多くの人が、SchemaHTMLを閲覧するときはブラウザで直接開くと想定されるので、これにて本当に皆が参照する共有コメントとなります。

ただ、チーム開発の場合、DocタスクはDB変更専用のブランチ (alter_dbブランチなど) で実行するような運用になっていると思いますので、わざわざデコメントのために Doc を叩くのではなく、自然の流れに任せる で良いかと思います。 コメントですので、気付いたら反映されているくらいでいいかと。

コンフリクトするとどうなる?

gitコンフリクトはせず業務的なコンフリクト

同じテーブル同じカラムのコメントを複数人で同時に修正しても、gitコンフリクトはしないように作られていますが、 (当然のことながら)業務的なコンフリクトは発生します。

SchemaHTML上でコンフリクトの表現

SchemaHTMLのコメント上で、コンフリクトが表現されます。

  • コメント表示が "赤字" になる
  • デリミタ "=======" つなぎで複数のコメントが連結表示される

デコメントのコンフリクト DBFluteIntro Decomment ConflictView

コンフリクトの解消方法

クリックすれば、同じようにダイアログが開き、同じ要領でそのままコンフリクトしたコメントを修正することができます。 (自動マージは一切されず、必ず人間が目で見て修正する方式です)

テーブル名が変更されるとどうなる?

一時的に、存在しないテーブルへのデコメント

テーブル名やカラム名が変更されると、一時的に登録されたデコメントは切り離されてしまいます。 存在しない古い名前に紐づくデコメントということで、どこにも表示されません。

DBFluteからすると、テーブルが削除されたのか、新しい名前に変更されたのかが自動で判別できないので、どうしても人が教えて上げる必要があります。

新しいテーブルへマッピング

そこで、DBFlute Introは、古いテーブル (いま存在しないテーブル) を参照しているデコメントを発見すると、 SchemaHTMLのトップにマッピングのための操作領域を表示します。

"その古いテーブル名は、新しいテーブルだとどの名前?" というのを選択すると、DBFlute Introがデコメントをマージし、新しいテーブルに紐付けられるようになります。

以下は、MEMBER_LOGIN を MEMBER_SEA_LAND に変更した例です。

デコメントのかぼマッピング DBFluteIntro Decomment CaboMapping

マッピングファイルのgitコミット

このマッピング結果自体も、DBFluteクライアント内のファイル (decomment-mappingファイル) として保存され、gitでコミットすることで共有されます。

※e.g. decomment-mapping-MEMBER_LOGIN-MEMBER_SEA_LAND-20180520-165122-463-jflute-1bf2eaa4.dfmap

マッピング自体のコンフリクト

マッピング自体のコンフリクトが発生したら、再度マッピングを求められるだけなので、デコメント自体と同様にトピックブランチで気軽にマッピングできます。

デコメントはどう保存される?

DBFluteクライアントに保存される

DBFluteクライアントの schema/decomment にテキストファイルとして保存されます。

e.g. pickup for decomment @Directory
[Project Root]
 |-...
 |
 |-dbflute_maihamadb // client
 |  |-dfprop
 |  |-...
 |  |-schema
 |  |  |-decomment // decomment resources
 |  |  |  |
 |  |  |  |-pickup // decomment pickup
 |  |  |  |  |-decomment-pickup.dfmap
 |  |  |  |
 |  |  |  |-piece // decomment pieces
 |  |  |  |  |-decomment-piece-MEMBER_SECURITY-20171229-173339-978-ryohei-339d5b82.dfmap
 |  |  |  |  |-decomment-piece-PURCHASE-PURCHASE_PRICE-20171229-172847-616-jflute-6dd20e16.dfmap
 |  |  |  |  |-...
 |  |-manage.bat
 |  |-manage.sh
 |
 |-...

デコメントごとにpieceファイルが保存される

一つ一つのデコメントを piece と呼んでいます。 (一回のOKボタンに付き、一ファイルが作成されます)

pieceファイルは、schema/decomment/piece 配下に保存されます。

e.g.  @Directory
[Project Root]
 |-...
 |
 |-dbflute_maihamadb // client
 |  |-dfprop
 |  |-...
 |  |  |-decomment // decomment resources
 |  |  |  |
 |  |  |  |-pickup // decomment pickup
 |  |  |  |  |-decomment-pickup.dfmap
 |  |  |  |
 |  |  |  |-piece // decomment pieces
 |  |  |  |  |-decomment-piece-MEMBER_SECURITY-20171229-173339-978-ryohei-339d5b82.dfmap
 |  |  |  |  |-decomment-piece-PURCHASE-PURCHASE_PRICE-20171229-172847-616-jflute-6dd20e16.dfmap
 |  |  |  |  |-...
 |  |-manage.bat
 |  |-manage.sh
 |
 |-...

Docタスクでpickupファイルが作成・更新される

pieceたちを集荷した情報を pickup と呼んでいます。

pickupファイルは、Docタスクを叩くと schema/decomment/pickup 配下に保存されます。

e.g.  @Directory
[Project Root]
 |-...
 |
 |-dbflute_maihamadb // client
 |  |-dfprop
 |  |-...
 |  |  |-decomment // decomment resources
 |  |  |  |
 |  |  |  |-pickup // decomment pickup
 |  |  |  |  |-decomment-pickup.dfmap
 |  |  |  |
 |  |  |  |-piece // decomment pieces
 |  |  |  |  |-// pieces are deleted
 |  |-manage.bat
 |  |-manage.sh
 |
 |-...

pickupには、pieceファイルたちの情報がすべて含まれています。 これらの情報は SchemaHTML にも反映されるので、ブラウザで直接 SchemaHTML を開いたときでも、登録されたデコメントたちが表示されるようになります。

一方で、集荷されたpieceファイルたちは不要になりますので削除されます。

Decommentのアーキテクチャマップ

DBFlute Intro と piece と pickup の関係などを表現したモデルがこちら。

図 : Decommentのアーキテクチャマップ Decommentのアーキテクチャマップ

デコメントの環境構築

必要なDBFluteのバージョン

DBFlute と DBFlute Intro が以下のバージョン以降である必要があります。

DBFlute
1.1.6 (2018/1/1リリース)
DBFlute Intro
0.2.0 (2018/1/1リリース)

DBFluteが先にある場合

すでに DBFlute の環境が整っている場合は、DBFluteタスクの manage.sh|bat の 88 (intro) を実行すれば、プロジェクト直下に DBFlute Intro がダウンロードされ、自動的に起動します。

e.g. DBFlute Intro のjarファイルを dbflute-intro ディレクトリ配下に @Directory
[Project Root]
 |-...
 |
 |-dbflute_maihamadb // client
 |  |-dfprop
 |  |-...
 |  |-manage.bat
 |  |-manage.sh
 |
 |-mydbflute
 |  |-dbflute-1.1.6 // engine
 |
 |-dbflute-intro.jar // downloaded by manage task
 |-...

一度ダウンロードしておけば、ダウンロードは発生しないので、実行するだけのコマンドとして manage の 88 が利用できます。

DBFlute Introが先にある場合

DBFlute Intro の機能を使って、DBFluteをセットアップしましょう。

DBFlute Introのアップグレード

削除してダウンロードです。

  1. dbflute-intro.jar を削除
  2. manage.sh|bat の 88 (intro) を実行 (jarがなければダウンロードされる)

DBFlute Introはgitignoreする?

どちらでも構いません。ディベロッパーからすれば、manage を叩いて起動することには変わりはないので、どちらであっても利用してる分には意識しません。

Introのバージョンを強制させたい場合は、コミット対象にしておけば横展開が簡単にはあります。 ただ、それなりのサイズではあるので、やはりignoreにしてIntroのアップグレードは各自に任せるのも良いでしょう。 (LastaFluteのExampleでは、デフォルトでignoreになっています)

デコメントサーバー

各々のディベロッパーが Intro をつどつど起動するのではなく、Intro を社内サーバーなどに常駐させて、手軽にデコメントを登録するやり方もあります。

単純に常駐させると?

ただ、単純に Intro を常駐させると、以下のような不都合があります。

  • デコメントの author が、すべてサーバーのアカウントになってしまう
  • Introの別の機能で、複数人同時実行してはいけないものがあって不安

デコメントのためのモード

そこで、デコメント登録を目的としたサーバーとしての起動モード をサポートしています。

Javaの起動パラメーターで intro.decomment.server を指定します。

e.g. DBFlute Intro をデコメントサーバーとして起動 @Command
java -Dintro.decomment.server=true -jar dbflute-intro.jar

すると、以下のような挙動になり、安心してデコメントを利用することができます。

  • 初回デコメント登録時だけauthorを入力すると、クッキーに保存されて自動的に利用される
  • Introの別の機能で、複数人同時実行してはいけないものは実行できないようになる

こちらを利用するためには、以下のバージョンが必要です。

DBFlute
1.1.8 (patch 2018/06/30) 以上
DBFlute Intro
0.2.2 以上

デコメントサーバーでgitと自動連携

git管理のプロジェクトの場合、登録されたデコメントをgitで共有したいですし、また、(定期的に)git上の最新のDBの状態を取り込んだ方が良いです。

まず、サーバー上でgitからcheckoutされた、デコメント対象のDBFluteクライアントが存在するディレクトリで、DBFlute Intro を実行するようにしましょう。 (gitのDBFluteクライアントと連携するために)

そして、サーバーにどんどん溜まっていくpieceファイルを、例えば Jenkins などを使って、定期的にgitにコミットされるようにすると良いでしょう。

実際に利用されている現場より、参考コードを頂きました。(U-NEXTさん、ありがとうございます!)

e.g. decommentサーバーで、pieceファイルを自動でコミットするスクリプトの参考コード @Bash
#!/bin/sh
today=`date +%Y%m%d%H`
should_commit=false
echo "[START SCRIPT]    piece file同期スクリプトを開始します : `date '+%F-%T'`"
echo "git refresh and checkout alter_db branch"
git fetch
git checkout master
git branch -D alter_db
git checkout alter_db

for i in "$@"
do
  dbname=$i
  if test -z "`git status ./${dbname}/schema/ --porcelain`"; then # 変更がないと文字列が還らずtrue
    echo "[NO PIECE:${dbname}] piece fileがありません"
  else
    #処理
    git add ./"$i"/schema/decomment/piece/
    git add ./"$i"/schema/hacomment/
    echo "[ADD PIECE:${dbname}] piece fileをaddします"
    should_commit=true
  fi
done
if $should_commit; then
  echo "[PUSH TO REMOTE] 収集したpieceをpushします"
  git commit -m"DBFluteIntro piece file を収集反映 ${today}00"
  git push origin alter_db
else
  echo "[NO PIECE TO COMMIT] piece fileの変更がありませんでした"
fi
echo "[START END] piece file同期スクリプトを終了します : `date '+%F-%T'`"

IPアドレスやポート番号を変更したい場合

IPアドレスは、Javaのシステムプロパティ intro.port で、変更することができます。(@since 0.2.3)

e.g. DBFlute Intro をIPアドレス 999.999.999.999 で起動 @Command
java -Dintro.decomment.server=true -Dintro.host=999.999.999.999 -jar dbflute-intro.jar

ポート番号は、Javaのシステムプロパティ intro.host で、変更することができます。(@since 0.2.3)

e.g. DBFlute Intro をポート番号 9999 で起動 @Command
java -Dintro.decomment.server=true -Dintro.port=9999 -jar dbflute-intro.jar

コミッター向け情報

Githubリポジトリ

Github Page
https://github.com/dbflute/dbflute-intro
Pull Request Branch
develop

Decommentのクラス概観マップ

図 : Decommentのクラス概観マップ Decommentのクラス概観マップ

無言のデータベースほど寡黙なものはない

データベースは単なる構造で、武士のようなものです。

プログラムの世界は、"コメントを書こう" という習慣が(まあまあ)世界的に浸透しているように思えます。 でも、データベースの世界では "コメントを書こう" という意識があまり一般化していないように思えます。 ですが、テーブルやカラムこそコメントが欲しいと思う場面が多々あります。

月並みですが、データベースはアプリよりも一般的に長生きで、分析が非常にしづらいものです。 データを見ればある程度は予測付くこともありますが、テストデータでは情報量が少なく、本番データは容易に見れません。 データベースこそ技術的負債の温床と言えるでしょう。

ただ、DBコメントの追加はプログラム上のコメント追加に比べて、仕組み的に非常に面倒になりがちです。 なので、"DBコメントを入れよう" というキャンペーンを打ち出しても中々成立しません。

そこで、ディベロッパーのみんなが見ている SchemaHTML でそのままコメントが登録できたらいいのになぁと考えました。 ただ、壁は大きく二つ、HTMLから直接ローカルファイルにはアクセスできないことと、gitでコンフリクトしてしまうと元も子もないこと。 DBFlute Introを使うことでこれを乗り越えました。

まだまだ課題はありますが、Introのデコメント機能を使って、無言のデータベースが少なくなればいいなと夢見ています。