ERD(Entity Relationship Diagram)を記述するための erd-go と周辺ツールを作りました

# ERD(Entity Relationship Diagram) って何？

* 日本語訳だと [実体関連図(wikipedia)](https://ja.wikipedia.org/wiki/%E5%AE%9F%E4%BD%93%E9%96%A2%E9%80%A3%E3%83%A2%E3%83%87%E3%83%AB)
* エンティティ同士の1対多や多対多などの関連性を俯瞰することができます

# どういうもの？

とりあえずデモをご覧くださいませ。
[erd-go](https://github.com/kaishuu0123/erd-go) + [graphviz-dot.js](https://github.com/kaishuu0123/graphviz-dot.js) + vscode プラグインの [ERD Preview](https://marketplace.visualstudio.com/items?itemName=kaishuu0123.vscode-erd-preview#overview) の組み合わせで実現しています

![vscode-erd-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/19717/39e496d2-95b4-2bb7-1327-78b15563004d.gif)


# 書き方

```
# Entities are declared in '[' ... ']'. All attributes after the entity header
# up until the end of the file (or the next entity declaration) correspond
# to this entity.
[Person]
*name
height
weight
+birth_location_id

[Location]
*id
city
state
country

# Each relationship must be between exactly two entities, which need not
# be distinct. Each entity in the relationship has exactly one of four
# possible cardinalities:
#
# Cardinality    Syntax
# 0 or 1         0
# exactly 1      1
# 0 or more      *
# 1 or more      +
Person *--1 Location
```

* `[]` の中に名前を記載するとテーブル名と認識します
* テーブル名の後にカラム名を記載します
* テーブル名同士を `1--*` (1対多) や `*--*` (多対多) と記載することで、テーブル同士を関連付けることができます

# 作った動機

大きく分けて２つあります

1. WEB システム設計時のモデル設計を楽にしたい
    * 大体 WEB システムを実装する時にはモデルの関連設計をすると思います
        * Twitter っぽいものを作る場合には、「User が複数の Tweet を持っていて、Tweet は返信機能があるから Reply というテーブルがあって ...」 といったようなお話
    * また、既存のモデルから ER図を起こすツールというのは存在しています ( [rails-erd](https://github.com/voormedia/rails-erd) etc)
    * ですが、実装を始める前の設計段階のツールはあるにしてもコレジャナイ感はありました
    * そこで「初期設計時にラフに1対多や多対多を設計するにはどうしたもんかな？ 
:thinking:」と悩んだ結果作ることにしました
1. BurntSushi さんが作った [erd](https://github.com/BurntSushi/erd) というツールを改善したい
    * お手軽さを重視したい
        * インストールは不要にして、シングルバイナリで使いたい
    * erd コマンド自体を OS 問わずにマルチプラットフォームで使いたい
        * Windows/Mac/Linux で使いたかったためです
        * Windows/Mac は執筆するために利用
        * また、Jenkins で定期的に図を生成したいので Linux にも対応した方がいいと考えたためです
    * 1対他の表現をもう少し分かりやすくしたい
        * 単なるスタイル調整ですが、重視したいと思った次第です

# 各種ツールで使っている技術
## erd-go

* GO言語
* [pointlander/peg](https://github.com/pointlander/peg)

ここでは入力された構文を Graphviz の dot 言語に変換する役割を担うため、[PEG(Parsing Expression Grammar)](https://ja.wikipedia.org/wiki/Parsing_Expression_Grammar) 自体の学習も兼ねて pointlander/peg を利用しました

## graphviz-dot.js

erd-go で吐き出した DOT 言語を SVG に変換するためのツールです。graphviz の dot コマンド相当です

* JavaScript
* Emscripten
    * Graphviz ライブラリを JS に変換するために Emscripten を利用しています
    * コマンドラインオプションの処理は別途 dot.js として実装しています
* [zeit/pkg](https://github.com/zeit/pkg)
    * Node.js 実行環境と JS を実行ファイルにパッケージするためのツールです
    * upx に対応していないため、バイナリサイズがデカイのが難点

## ERD Preview (Visual Studio Code 拡張)

* JavaScript
* こちらは素直に `erd` コマンドと `dot` コマンドをハンドリングするだけです
* [VScode の拡張機能チュートリアル](https://code.visualstudio.com/docs/extensions/example-hello-world) を参考にしつつ実装しました
* インストール後、`settings.json` に以下の設定が必要です

    ```
    // erd と dot コマンドへのパス。Windows の場合はC:\\Users ... というような形
    "erd-preview.erdPath": "...",
    "erd-preview.dotPath": "...",
    ```

# 最後に

* まだまだ改善点が目立ちますが、とりあえずラフな設計ができるようになって幸せになりました :sparkles: 
* 自作ツールを使ってモデル設計をした後に rails-erd で現状のコードで図を記述するという使い方をしています
* この記事によって他の方にも使っていただけると幸いです