2019/08/16

APIの設計書をMarkdownで書いてみたい

なんでやろうと思ったのか

会社で基本設計書といえば、ExcelとかWordとかPPTとか、Office系のアプリを使って作成することが多い。
その場合、下記の点でいつも悩ましい状態になる。
  • バージョン管理
  • バージョン間の差分管理
    • レビュー指摘票と行数のマッピングのズレ(指摘が複数ある場合に行数や連番がずれて、どこの指摘の修正がどこに行ったのかわからなくなる)
  • レビューのクローズ状況の追跡
最近はMarkdownとPlantUMLを組み合わせて、シーケンス図やシステムコンテキスト図の概要を作ってみている。
(最終的には画像化してPPTに貼っているけど。。。)
なので、上記の悩ましい状態の解決方法として、最近慣れてきているMarkdownでの基本設計書の作成をしていきたいと考えていた。
ということで、試してみたので、その備忘録です。

で、どうだった?

記述ルールは簡単で、モックサーバをローカルに立てみて、
  • 設計と実装意図があっているか確認できる
  • 実コードが無くてもローカルでAPIを利用して、利用者側の実装ができそう
というところまで確認できたので、かなりいい感じ、という印象でした。
HTML出力したレイアウトも結構きれいで、好みでした。
ただし、レビュー指摘票の行数のマッピングのズレについては、GithubのPullRequestを利用しないと解決できないので、今後の課題ということで。。。
あれ?VSCodeに入れたExtentionを使っていない。
ま、いっか〜

実装内容の公開

今回作成したMarkdownのファイルは下記のGithubで公開します。
不備などありましたら、ご指摘いただけますと幸いです。
o310yusuke/APIBlueprint_Tutorial

何を使うのか

  • テキストエディタ:VSCode
    • 理由:使い慣れてきたし、軽いし。
  • エディタ拡張機能:vscode-apielements
    • 理由:公式サイトapiblueprintに乗っていたから
  • 設計書記述方法:API Blueprint
    • 理由:参考サイトを参考に(記述ルールがシンプルそうだったから)
  • レンダリング:Aglio
    • 理由:参考サイトを参考に(node.jsでnpmで導入できるから)
  • モックサーバ:Drakov
    • 理由:参考サイトを参考に(node.jsでnpmで導入できるから)

参考サイト

やったこと(環境構築)

実施したOSはMacです。
Node.jsは7.10.0です(古かった。。。)。

VSCodeに拡張機能をインストール

  • apielementで検索してインストール
  • workspaceとして、「apiblueprint_trial」のディレクトリ作成

npmのインストール状況を確認

$ npm ls --depth=0 -g
/usr/local/lib
├── generator-code@1.2.0
├── npm@4.2.0
└── yo@3.1.0
generator-codeとyoは、VSCodeのExtensionを作ってみたくていらたものなので、関係無し。

Aglioをインストール

参考サイトではグローバルにインストールしていたけど、今回はローカルのみにインストールを行う。
# node.jsのグローバルにインストールする場合
npm install -g aglio
# 特定ディレクトリにインストールする場合
cd 特定ディレクトリまで移動
npm install aglio
# インストール確認(直下のものだけ)
npm ls --depth=0
npm ls -g --depth=0
結果
$ npm ls --depth=0
/apiblueprint_trial
└── aglio@2.3.0
$ npm ls --depth=0 -g
/usr/local/lib
├── generator-code@1.2.0
├── npm@4.2.0
└── yo@3.1.0

Drakovをインストール

こちらもローカルのみにインストール
npm install drakov
結果
$ npm ls --depth=0
/apiblueprint_trial
├── aglio@2.3.0
└── drakov@1.0.4

$ npm ls --depth=0 -g
/usr/local/lib
├── generator-code@1.2.0
├── npm@4.2.0
└── yo@3.1.0

やったこと

API Blueprintの公式サイトにチュートリアルがあったので、そちらを参考に実施。

Markdownで書いてみる

  • tutorial.mdを作成する。
  • まず、API名とメタデータを決める。
    FORMAT: 1A ←Blueprintのバージョン
    
    # Polls ←API名
    サンプルAPIの名前を「Polls」にします。 ←APIの説明
    
  • リソースグループを「# Group」で記載する。
    • チュートリアルでは、「質問」に関する複数のAPIの章立てのイメージみたい。
    # Group 質問 ←グループ名
    「質問」に関するAPIのリソースを集約する。 ←グループの説明
    
  • リリースを定義する。
    ## 質問コレクション [/questions] ←「質問」のリソースグループ内の質問のリスト。[]内にURLテンプレートを記述可能。
    
  • アクションを定義する。
    • 1つのリソースに必ず1つのアクションを定義すること。
    ### 一覧取得 [GET] ←リソース内の1つのメソッド。[]内にHTTPメソッドを記載する。
    - Response 200 (application/json)
     [
      {
       "question": "Favourite programming language?",
       "published_at": "2014-11-11T08:40:51.620Z",
       "url": "/questions/1",
       "choices": [
        {
         "choice": "Swift",
         "url": "/questions/1/choices/1",
         "votes": 2048
        },{
         "choice": "Python",
         "url": "/questions/1/choices/2",
         "votes": 1024
        }
       ]
      }
     ]
    
    ※チュートリアルでは、2つめのアクションを記載しているが割愛
    ※チュートリアルでは、2つめのリソースを記載しているが割愛

Markdown→HTML変換してみる

  • 作成したtutorial.mdから、aglioを使ってHTMLを作成する
    • aglioをローカルインストールしたので、下記のコマンドでは実行できなかった。
      $ aglio -o tutorial.md -o tutorial.html
      
    • 下記のコマンドを実行し、npxをグローバルインストールし、npmの初期化を実施した(デフォルト値で実行した)。
      $ npm install -g npx
      # 結果
      $ npm ls --depth=0 -g
      /usr/local/lib
      ├── generator-code@1.2.0
      ├── npm@4.2.0
      ├── npx@10.2.0
      └── yo@3.1.0
      # 初期化
      $ npm init
      
    • npxを利用することで、ローカルインストールしたパッケージも利用可能にできた。
      $ npx aglio -i tutorial.md -o tutorial.html
      
    • 表記のエラーがあると、コンパイルエラーとなり、修正方法も提示してくれる。それに合わせて修正することで、コンパイルしてくれる。
  • 下記コマンドを実行しておけば、mdファイルを保存したタイミングでリアルタイムで変換してくれる。
    npx aglio -i tutorial.md --server
    # 結果
    Server started on http://127.0.0.1:3000/
    Rendering tutorial.md
    # 終了方法
    Ctrl + C
    

Mockサーバを試してみる

  • drakovでMockサーバを起動する。
    npx drakov -f tutorial.md --watch
    # 結果
    [INFO] No configuration files found
    [INFO] Loading configuration from CLI
       DRAKOV STARTED
    [LOG] Setup Route: GET /questions 一覧取得
    [LOG] Setup Route: POST /questions 新規投稿
    [LOG] Setup Route: GET /questions/:question_id 質問詳細取得
    [LOG] Setup Route: DELETE /questions/:question_id 削除
       Drakov 1.0.4      Listening on port 3000
     FILE SPY   ACTIVE
     # 終了方法
     Ctrl + C
    
  • ブラウザで、一覧を取得してみる。
    • URL: http://localhost:3000/questions
    • 結果(コンソール)
      [LOG] GET /questions
      [MATCHING] by url pattern: /questions/:question_id NOT_MATCHED
      [MATCHING] by url pattern: /questions MATCHED
      [DRAKOV] GET /questions 一覧取得
      
    • 結果(ブラウザ)
      [
          {
              "question": "好きな開発言語はなんですか?",
              "published_at": "2014-11-11T08:40:51.620Z",
              "url": "/questions/1",
              "choices": [
                  {
                      "choice": "Swift",
                      "url": "/questions/1/choices/1",
                      "votes": 2048
                  },{
                      "choice": "Python",
                      "url": "/questions/1/choices/2",
                      "votes": 1024
                  }
              ]
          }
      ]
      
  • cURLを使った確認
    • 入力画面
      # 一覧取得(HeaderとBodyを表示するため「-i」を付与)
      $ curl -i http://localhost:3000/questions
      # 新規登録
      $ curl -i -X POST -H "Content-type: application/json" -d '{"question":"好きな開発言語はなんですか?","choices":["Swift","Python"]}' http://localhost:3000/questions
      # 削除
      curl -i -X DELETE http://localhost:3000/questions/1
      
    • ウォッチ画面(Drakovを起動したコマンドプロンプト)
      # 一覧取得
      [LOG] GET /questions
      [MATCHING] by url pattern: /questions/:question_id NOT_MATCHED
      [MATCHING] by url pattern: /questions MATCHED
      [DRAKOV] GET /questions 一覧取得
      # 新規登録
      [LOG] POST /questions
      [MATCHING] by url pattern: /questions/:question_id NOT_MATCHED
      [MATCHING] by url pattern: /questions MATCHED
      [MATCHING] by request content type: application/json actual: application/json MATCHED
      [MATCHING] by request body content MATCHED
      [DRAKOV] POST /questions 新規投稿
      # 削除
      [LOG] DELETE /questions/1
      [MATCHING] by url pattern: /questions/:question_id MATCHED
      [DRAKOV] DELETE /questions/{question_id} 削除
      

0 件のコメント:

コメントを投稿