はじめに
大きな開発をする際に開発内容の説明するのって難しいですよね。
もしかすると世間にはいい感じのドキュメントの作り方があるかもしれないし、
なんなら自分好みのドキュメント生成用アプリなんかを作るのも1つの手だと思います。
ただできるだけ素早く手軽に手間も抑えたい!
という気持ちでたまたま最近使い始めていたSwaggerを使っていい感じにドキュメントが作成できないかと考えたので
今回はJavaの開発内容をSwaggerを使ってドキュメント化してみたいと思います。
Swaggerについて
Swaggerについては公式ドキュメントやほかにもいろいろな記事があるので詳細は省きますが、
簡単にまとめるとOpenAPI仕様のAPIについて設計やドキュメントの作成などが可能なツールのセットとなります。
ツールのセットということで実際どういったツールがあるかというと下記のようなツールがあるようです。
名称 | 概要 |
---|---|
Swagger Editor | OpenAPI定義を作成できるブラウザベースのエディター |
Swagger UI | OpenAPIの定義をブラウザで見やすく表示するツール |
Swagger Codegen | OpenAPI定義から実際のコードを生成するツール |
Swagger Editor Next | OpenAPIとAsyncAPIの定義を作成したりレビューできるブラウザベースのエディター |
Swagger Core | OpenAPI定義の作成、操作することができるJavaのライブラリ |
Swagger Parser | OpenAPI 定義を解析するためのスタンドアロン・ライブラリ |
Swagger APIDom | APIの言語(OpenAMIやRAMLなど)、シリアライズ形式(xmlやyamlなど)によらず形式を統一した構造を提供する |
今回は主にSwagger EditorとSwagger UIを使うことになります。
定義の作成
ドキュメントの作成にはSwagger EditorとSwagger UIを使用するためにセットアップが必要になります。
具体的なセットアップ手順は下記が参考になるかと思います。
セットアップが完了すると下記のような画面になり、ドキュメントの作成が可能になります。
最初の起動時には公式で用意されている例のようなドキュメントが表示されているので、
まずはこの例を参考に書いていくのがいいと思います。
もう一度この例の状態に戻したい場合は、Edit > Load PetStore OAS 3.0 を実行することで実現可能です。
次に実際にドキュメントを書くステップに移りますが、
今回は下記のような条件を例にしてまずドキュメントを作成します。
- 会員情報を管理するクラス
- データの登録、データの取得、データの更新、データの削除を実装する
実際に必要な情報を埋めていったものが下記になります。
実際のswagger定義
openapi: 3.0.3
info:
title: Memberクラス
description: |-
メンバーの管理をするクラス
termsOfService: http://swagger.io/terms/
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.0
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: http://localhost:8080
paths:
/register:
post:
tags:
- Member
summary: メンバーの登録処理
description: 登録に必要なデータを引数に渡すことでメンバーの登録が実行されます。
operationId: register
parameters:
- name: name
in: query
description: メンバーの名前
required: true
explode: true
schema:
type: string
example: swagger name
- name: age
in: query
description: メンバーの年齢
required: true
explode: true
schema:
type: integer
example: 25
- name: adress
in: query
description: メンバーの住所
required: true
explode: true
schema:
type: string
example: 東京都〇〇区 ××
- name: gender
in: query
description: メンバーの性別
required: true
explode: true
schema:
type: string
example: 男
- name: mail
in: query
description: メンバーのメールアドレス
required: true
explode: true
schema:
type: string
example: qiitaro.xxx.xxx
responses:
200:
description: コンソール出力
content:
application/json:
schema:
type: object
properties:
登録者ID:
example: m12345
/getMember:
get:
tags:
- Member
summary: メンバーの取得処理
description: 登録者IDを引数に渡すことで該当するのメンバー情報を取得します。
operationId: getMember
parameters:
- name: id
in: query
description: 登録者ID
required: true
explode: true
schema:
type: string
example: m12345
responses:
200:
description: メンバー情報 Map<String>
content:
application/json:
schema:
type: object
properties:
name:
type: string
example: swagger name
age:
type: integer
example: 25
adress:
type: string
example: 東京都〇〇区 ××
gender:
type: string
example: 男
email:
type: string
example: qiitaro.xxx.xxx
/updateMember:
put:
tags:
- Member
summary: メンバーの更新処理
description: 登録者IDを引数に渡すことで該当するのメンバー情報を更新します。
operationId: updateMember
parameters:
- name: id
in: query
description: 登録者ID
required: true
explode: true
schema:
type: string
example: m12345
- name: columnNm
in: query
description: 更新対象のカラム名
required: true
explode: true
schema:
type: string
example: adress
- name: updateData
in: query
description: 更新後のデータ
required: true
explode: true
schema:
type: string
example: 埼玉県〇〇市 ××
responses:
200:
description: コンソール出力
content:
application/json:
schema:
type: object
properties:
更新データ:
example: adress:埼玉県〇〇市 ××
/deleteMember:
delete:
tags:
- Member
summary: メンバーの削除処理
description: 登録者IDを引数に渡すことで該当するのメンバー情報を削除します。
operationId: deleteMember
parameters:
- name: id
in: query
description: 登録者ID
required: true
explode: true
schema:
type: string
example: m12345
responses:
200:
description: コンソール出力
content:
application/json:
schema:
type: object
properties:
削除完了:
example: m12345
サーバー作成
Swagger定義の記述が完了したので次はこれを参照しやすいようにdockerコンテナ化します。
サーバーファイル作成
まずはSwagger定義からnode.js用サーバーファイルを出力します。
下記画像のようにGenerate Server > nodejs-serverから出力可能です。
サーバーファイルの出力が完了するとzipファイルがダウンロードされるので、
このzipファイルを任意のディレクトリに解凍します。
解凍後のディレクトリ構成としては下記のようになっています。
nodejs-server-server-generated
├ .swagger-codegen
├ api
├ controllers
├ service
├ utils
├ .swagger-codegen-ignore
├ index.js
├ package.json
└README.md
Dockerfileの作成
サーバーファイルの作成まで完了したので実際にサーバーをたてていきます。
今回はnode.jsになるため詳細な手順は下記のページが参考になります。
上記手順を通してDockerfileと.dockerignoreファイルの作成が完了した後は、
これらを先ほど解凍したサーバーファイルのディレクトリに配置します。
最終的なのディレクトリ構成としては下記のようになっています。
nodejs-server-server-generated
├ .swagger-codegen
├ api
├ controllers
├ service
├ utils
├ .dockerignore
├ .swagger-codegen-ignore
├ Dockerfile
├ index.js
├ package.json
└README.md
サーバーの作成
ここまででnode.jsサーバーの作成準備が整ったのでサーバーの作成をしていきます。
下記コマンドを実行していくことでサーバーの作成ができます。
$ cd /nodejs-server-server-generated 作成したサーバーファイルのディレクトリ
$ docker build . -t {任意のタグ}
$ docker run -name {任意の名前} -p {使用するポート}:{使用するポート} -d {任意のタグ}
例)
$ docker build . -t member-doc
$ docker run --name member -p 8080:8080 -d member-doc
サーバーの起動確認後ブラウザからに下記にアクセスして画像ようなページが開けば完了です。
http://localhost:8080/docs/
Swaggerを利用したことによる特徴として、POSTやGETなどで色分けした部分が処理と対応していると視覚的にもわかりやすい状態になっていたりします。
POST:データの登録
GET:データの取得
PUT:データの更新
DELETE:データの削除
各メソッドについても下記画像のように展開することで必要な引数についてや実行結果について確認できるようになっています。
また今回Swagger定義を作成したクラスを実際のソースに起こすと下記のようなイメージになります。
package jp.test.Member;
public class Member {
public void register( String name, int age, String adress, String gender, String mail ) {
String memberId;
// 登録処理
System.out.println("登録者ID:" + memberId);
}
public HashMap<String> getMember(String sql) {
HashMap<String> memberMap = new HashMap<String>();
// データ取得処理
return memberMap;
}
public void updateMember(String id, String columnNm, String updateData) {
// データ更新処理
System.out.println("更新データ:" + columnNm + "=" + updateData);
}
public void deleteMember(String id) {
// データ削除処理
System.out.println("削除完了:" + id);
}
}
メリットとデメリット
今回Swaggeを利用してJavaのクラスをドキュメント化してみて個人的に感じたメリットとデメリットを下記にまとめてみました。
メリット
- 実装内容をある程度整理してかつそれを説明資料に残せる
- メソッドを網羅しつつ確認したいメソッドにフォーカスできるドキュメントになる
- Swagger自体の勉強にもなる
デメリット
- 書き方が縛られる(引数の型やresponse部分など)
- Swaggerを普段から使う場合混同する可能性がある
- 複雑なクラスやメソッドの場合はわかりづらい
おわりに
今回はSwaggerを使ってJavaのドキュメントを作成してみましたが、
個人的にはソースに説明を書くよりも説明には使いやすいように感じたのと、ある種フォーマットが決まっていることで表記ゆれのようなものもなくなりドキュメント化の1つとしてありなように感じました。
またSwagger自体オープンソースなので、それこそドキュメント用にカスタマイズしたものを作ってみたりとか、
あとはyamlで書く形式なのでjavadocからSwagger定義を生成するツールとかも作れなくはないんじゃないかと思ったりといろいろと試してみる価値があるように思います。