恥ずかしながらOpenAPIという規格を初めて知ったので、いっちょやってみっか!と意気込んでみたものの、挫折した話です。
APIの規格を先に決め、そこから派生するように実装コードを生やすと実装と仕様書がぶれない、という発想は素晴らしいと思います。APIでやりとりするデータの型も定義するため、API仕様から自動でコードを起こすことができればクライアントサイドもサーバーサイドも同一の型を使って安全にやり取りできます。
動的型のjavascriptでやると恩恵が大きいのでは?と思い、
・Swagger-node
・OpenApi-Generator
・Typescript
の3本建てで簡単なAPIサーバーを作成してみました。
package.jsonはこんな感じ。
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.3.3",
"@types/express": "^4.17.12",
"@types/node": "^15.12.1",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"eslint": "^7.28.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-import": "^2.22.1",
"prettier": "^2.3.1",
"should": "^7.1.0",
"supertest": "^1.0.0"
},
"dependencies": {
"express": "^4.12.3",
"swagger-express-mw": "^0.1.0",
"typescript": "^4.3.2"
}
swagger-nodeのapiフォルダ等をルートフォルダから動かす場合(src以下に移すなど)は
appRoot以外も指定してあげる必要あり。
const config = {
appRoot: __dirname,
configDir: `${__dirname}\\config`,
swaggerFile: `${__dirname}\\api\\swagger\\swagger.yaml`,
};
OpenApiのyamlを自力で書くのはしんどいため、Spotlight studioを使います。
https://stoplight.io/studio/
これでサクサクyamlが生成できます。
作成したyamlをOpenApi-Generatorを通して自動生成されるクラス(ts)を生成します。
が、ここで軽い違和感。なんか自動生成されるfunctionとinterfaceが気持ち悪い。
思ってるんと違う、、、
パラメータ類をdefinitionに切り出さずに書くと自動生成される名前が当たるので、これは全部切り出さないとダメそう。切り出すのめんどいから自動生成させてるんじゃ、、、 いやいや、郷に入っては郷に従えか。
同一プロパティを持つけど別APIのパラメータは別の名前付けようか?同じでいい?などくだらないことに悩みながら長い長い巨大なyamlを書く。definitionに切り出すせいでAPI部分と定義部分がどんどん離れていく。一覧性も悪い。
Swagger-UIから見る画面は確かに仕様がきちんと確認でき、apiも叩けるので便利ではある。便利ではあるが、うーん、これプロトタイピングに向いてないのでは?というか作りながら仕様を決めるようなパターンだと破綻するわ、確実に。yamlに起こした仕様が確定的でほとんど変更がない時は使えそうな感触だけど、プロジェクトの全体像がそこまではっきりしない場合は雑に作ってほぼ完成してから移し替える方がいいんじゃないかと思う。
Swagger部分はそんなに不満はないので、おそらく自動でコードを生成するってことが大きな制約になるんだと思う。yamlの書き方を生成されるコードを見越して書かなければいけない。自動生成されるコードが気に食わなくても、そこに手を入れてしまうと自動生成する意味がなくなってしまうためyamlを弄ることしかできない。yaml改変を通して目的のコードが生成されるように変更するなんて、手を使わずにコーディングするみたいなもんで限界がある。
加えてtypescriptでやろうとしたことで型を細かく考えなければならず良くも悪くも煩雑だ。正直静的に型を扱うことで得るメリットが払う手間と見合ってない。1-3人くらいのプロジェクトなら素のjavascriptでササっと書いちゃった方がよっぽど早いし見通しよく書ける気がする。型がある方が助かるケースも多いけど、小規模なapi程度ならなくても何とでもなる。
ということでOpenApiで自動化して楽になるかも?っていう野望はあきらめることにしました。
Swagger-node自体は使えるのですが、コードを自動生成は諦めた方がよさそう。
javascriptに限らない問題だと思うので、generatorだけでやりくりしようとすると徒労になりそう。とりあえずgeneratorでざっくり作成して、コードはバンバン弄るのが正義かな。
コメント