Swagger 定義から goa の design を生成する ago という CLI を作りはじめた

これは Go (その2) Advent Calendar 2016 の 17 日目の記事です。

ここ半年ほど goa というフレームワークを気に入って使っているのですが、思うところがあって goa に関連する ago という CLI を作りはじめました。この記事では、簡単な goa の説明から、今回の開発に至った経緯と、このツールで行えることについて記述します。

goa とは

Go でマイクロサービスな Web API を作るためのフレームワークです。

github.com

goa の DSL で design と呼ばれる定義を書いたら、 goagen というジェネレータを使ってサーバやクライアントなど各種のコードを生成することができます。毎度リンクを貼らせて頂いているのですが @ikawaha さんによる連載記事が本当にオススメです。

ikawaha.hateblo.jp

goa 流行らない問題

そうなんです。私も良さを広めたいユーザの一人なんですがなんか流行らないんです。参考までに他の Web フレームワークGitHub のスター数を比較してみました。 (2016/12/17 時点)

Repository Since Stars
https://github.com/gin-gonic/gin 2014/06/15 8294
https://github.com/labstack/echo 2015/03/01 6034
https://github.com/goadesign/goa 2015/10/18 1613

そして Google Trends の人気度推移。

開発が開始された時期の違いはあるにしてもあまりにも大きな差ですね。

ではなぜ流行らないのか。この理由を定量的に説明するのは難しいですが、おそらく goa のユニークな開発アプローチがその参入障壁を高くしてしまっているのだと思います。

  • 専用の DSL で design と呼ばれる設計書を書く
  • design を元にアプリケーションコードの大部分を自動生成する

goa での開発においてこれらのステップは必須です。避けて通ることはできません。 Go の Web フレームワークを net/http, gin, echo, ..., goa と横に並べて比較したとき、 goa の毛色が他と大きく異なることは明らかです。 Go を長く使っているユーザほど、それが「シンプルで、信頼でき、効率的なソフトウェアを構築しやすくする」という Go の思想に反していると感じてしまうかもしれません。

しかし一度 DSL を覚えてしまえばアプリケーションのインタフェース (リクエストとレスポンス) はすべて design に記述されているという見通しの良さが手に入りますし、大規模にコード生成を活用している点なども含めて実際は実に Go らしいフレームワークだと思います。

既存の Swagger プロジェクトの goa への移行問題

少し話は変わって Open API Initiative への採用も記憶に新しい Swagger です。実際に Swagger を使っているプロジェクトも増えているような気がするのですが、既存の Swagger プロジェクトを goa に移行したいというニーズがあるようです。

goa は標準で Swagger をサポートしており、 Swager の公式ページにも記載されています。しかし、そのサポートの意味は「 Swagger 定義の出力」であり「 Swagger 定義からのコード生成」ではありません。 goa は Swagger とよく似たワークフローを採用していますが、その中心にあるものが違います。 Swagger を用いた開発の中心にあるのは「 Swagger 定義」であり、そこからアプリケーションコードを生成しますが、 goa を用いた開発の中心にあるのは「 goa の design 」であり「 Swagger 定義」はアプリケーションコードと同じ生成物のひとつに過ぎないのです。

goa を用いる以上 design を中心に据えた開発を行う必要がある、しかし Swagger ユーザに goa への移行パスは用意したい、それを可能にするにはどうすればいいか。 Swagger 定義から goa の design を生成するコマンドがあれば Swagger ユーザはスムーズに goa を使い始められるのではないでしょうか。

ago

ようやく本題です。 ago というコマンドを作り (はじめ) ました。

github.com

使い方は簡単です。

$ ago swagger swagger.json > design.go

このように swagger.json を引数として渡すと標準出力に goa の design が出力されます。本当はきちんと完成させたかったのですが間に合わなかったため完全な design は出力されません orz しかし design を構成する DSL の 1/3 程度は既にサポートしているので既存の Swagger 定義がある場合は goa 導入の助けになると思います。鋭意開発中なので近日中にすべての DSL がサポートされる予定です。

あとがき

実際このツールのニーズはかなり局所的な気もしているのですが、既に Swagger を使っている方は試してみていただけたら嬉しいです。また何より、 goa に少しでも興味を持った方はこのフレームワークに触れてみて、その素晴らしさを体感してみて欲しいと思います。

Riot.js を使ってみた

少し前ですが、ちょっとウェブアプリケーションを作る機会があったので使ってみました。

Riot.js とは

http://riotjs.com/ja/riotjs.com

A React-like user interface micro-library の謳い文句通り React ライクなライブラリです。つい最近 v3 がリリースされたみたいです。私が使ったバージョンは v2.5.0 でした。公式のガイドで大枠を掴んだら examples で具体例を見ることができます。

Riot.js でウェブアプリケーションを作る

Riot は MVC でいう View のためのライブラリでありフレームワークではありません。アプリケーションを作る際には自分で枠組みを考える必要があります。

tag の分類

React (Redux) ではコンポーネントを Presentational components と Container components に分類する考え方があるようなのでこれを取り入れてみました。前者は表示のみを行うステートレスな (= 状態を持たない) コンポーネントで、後者はそれらに具体的なデータを与えるステートフルな (= 状態を持つ) コンポーネントです。

qiita.com

今回は各画面のルートコンポーネントのみを Container Components とし、残りはすべて再利用可能な Presentational Components として実装しました。

ディレクトリ構成

以下の構成としました。

    .
    ├── config
    ├── public
    │   ├── assets
    │   │   └── images
    │   │   └── js
    │   │       └── bundle.js
    │   └── index.html
    └── src
         ├── stores
         └── tags
             ├── components
             ├── containers
             └── mixins
  • src/

    Riot の tag は tags/ に配置しています。汎用的な機能はミックスインにしておいて各々の tag から利用しています。 stores/ にはバックエンドの API と通信を行う処理全般を配置しています。

  • public/

    画像などの静的ファイルを配置しています。 assets/js/bundle.jssrc/ 配下のファイルをコンパイルしたものです。

  • config/

    config のための JSON を配置しています。

ビルド

ES5 で書いているのでトランスパイラ (Babel) は使っていません。タスクランナー には gulp.js を使用しました。

  1. configconfig/ から設定を取得して src/stores/ 内の API の URL を置換
  2. riotsrc/ 配下のファイルを public/assets/js/bundle.jsコンパイル
  3. superstatic でサーバを立てて public/ のファイルを配信
  4. run-sequence で 1 から 3 を 順番に実行

上記のような task を作って gulp run で実行できるようにしています。また、開発中は都度コンパイルするのが面倒なので gulp.watch()src/ を監視して変更があったらリコンパイルするようにしていました。

感想

View のためのライブラリとして見たとき Riot は学習コストも少なく扱いやすい印象でした。 tag は見慣れた HTML / CSS / JavaScript が集合しただけのものなので、初見でも心理的抵抗が少ないように思います。共同で作業したデザイナ (非エンジニア) も 10 分ほどの説明ですぐに理解してくれました。ただウェブアプリケーションを作ろうと思ったとき参考になる情報が少なくて苦労する場面も多かったです。同じ View のためのライブラリである React には FLUX というアーキテクチャがあり、そのポピュラーな実装として Redux があります。 Riot でもそのあたりの話が多くなるとよりユーザが採用しやすくなるのではないかと思いました。

Swagger 仕様を複数ファイル出力する goa プラグイン Multiswagger を作った

作りました。

github.com

goa とは

Go でマイクロサービスな Web API を作るためのライブラリです。

github.com

goa の DSL で design と呼ばれる定義を書いたら、 goagen というジェネレータを使ってサーバやクライアントなど各種のコードを生成することができます。日本語だと @ikawaha さんによる連載記事が非常にわかりやすくてオススメです。

ikawaha.hateblo.jp

Multiswagger とは

Swagger 仕様を出力するための goagen のプラグインです。 goagen に内蔵されているデフォルトの Swagger ジェネレータと互換性がありますが、Description() という DSLJSON のとき、そのキー毎に Swagger 仕様を出力します。

apidsl.Description(`{
    "key1": "value1",
    "key2": "value2"
}`)

例えば上記のような design を入力としたとき

swagger.key1.json と swagger.key1.yaml

description: value1

が、 swagger.key2.json と swagger.key2.yaml

description: value2

が出力されます。

i18n のために各言語の説明を書いてそれぞれ別のファイルに出力する、という使い方が考えられます。

apidsl.Description(`{
    "en": "This is an english description.",
    "ja": "これは日本語の説明です。"
}`)

というか他のユースケースが思いつきませんでした🤔

非常にニッチなコードですがよければ使ってみてください。

golang: goa 勉強会で発表してきた

発表してきました。

connpass.com

春頃から goa を使ってきて自分なりのノウハウが溜まってきたところだったので、このような場で発表させて頂けてありがたかったです。スライドのボリューム不足を心配していたんですが 20 分というのは思ったよりも短くて、結果的には少しオーバーしてしまいました。 (すみません ...) もしまた発表する機会があったらもっとペース配分に気をつけようと思いました。

How I create a Microservice using goa - Slideck

他の方の発表も実践的な内容が多くて勉強になりました。使ったことないライブラリを知れることは勉強会に参加する意義のひとつですね。

参加した皆さま、特に主催の @ikawaha さんお疲れさまでした。

ほんと骨身に沁みますね。

2016 年上半期振り返り

カンファレンス

せっかくゴーコン行ったのに書き忘れてたなぁ ...

Go Conference 2016 Spring gocon.connpass.com

OSS

半年で 13 件のプルリクエストを出しました。

Search · author:tchssk created:2016-01-01..2016-06-30 · GitHub

数字にするととても少なく感じるなぁ。下半期はもう少しやりたいですね。

後半は GitHub - goadesign/goa: Design-based microservices in Go がほとんどだったけど、これはとても気に入っているので今後も貢献して行きたいと思っています。日本ではあまり使われていない (ような気がする) けど、ドキュメントの翻訳でもしたら利用者増えるだろうか。

仕事

twitter.com

ツラい。

Shibuya.go#2 に行ってきた

先週にGopher Night に行ったばかりですが、また Go のイベント (Shibuya.go#2) に行って来ました。

shibuyago.connpass.com

RDBを叩くだけのRuby製バッチプログラムをgoにしただけで20倍速くなった件

by ajiyoshi さん (Voyage Group)

https://dl.dropboxusercontent.com/u/31719381/shibuya.go.pdf

Ruby のバッチを Go にリプレースした話。ORM は使わず variadico/scaneosql.Rows.Scan() する関数を生成しているということでした。構造体にメソッドを生やすときは埋め込みじゃなくてユーザ定義型でも大丈夫な気がした。

type Int struct {
    sql.NullInt64
}

func (i Int) Method() {
// Do something.
}

じゃなくて

type Int sql.NullInt64

func (i Int) Method() {
// Do something
}

こういう感じ。

Slackのプロキシサーバ( github.com/cubicdaiya/slackboard )をGoで書いた話

by cubicdaiya さん (Mercari)

speakerdeck.com

Slackboard という Slack 用プロキシサーバの話。 Warning や Critical みたいに通知レベルを設けて出力時に色をつけられるのが便利そうでした。

stretcherの実装について

by fujiwara さん (Kayac)

speakerdeck.com

Pull 型のデプロイツール Strecher の話。ちょうどデプロイ周りのスクリプトを綺麗にしようと思っていたので興味深々でした。「実装について」とタイトルについているだけあってコードの細かい話が多かったです。知らないライブラリやコードの書き方がいくつかあって、非常にお得感のある発表でした。

Redisの調査についてとrmlp (LT)

by Konboi さん (Kayac)

speakerdeck.com

Redis の調査のノウハウとログ整形ツールの話。 LT だからというのもあると思いますが非常にテンポのいい発表でした。ときどき小笑を挟んで来てズルい。

Sparc Solaris向けにGoのクロスコンパイル環境を作った話 (LT)

by snowcrush さん

https://tanstaafl.0pt.jp/slides/solaris-gccgo/

Go のサポートに Solaris は含まれているが Sparc は含まれていないらしいです。珍しい環境だと情報も少なくて大変そうでした。Solaris ユーザはいますか、という問いかけに手を挙げたのは 1 人だけ (!) でした。

イベント全体の感想

会場のみならずピザと飲み物まで提供して下さって Voyage Group さんは太っ腹ですね。広々としたシンプルな会議室でしたが、エントランスや他の部屋は装飾が施されていてオシャレな雰囲気でした。機会があれば覗いてみたいですね。

Gopher Night #1 に行ってきた

Eureka さん主催の Gopher Night #1 に行って来ました。

eure.connpass.com

社内の画像変換サーバーを Goで置き換えた話

by ieee0824 さん (Livesense)

www.slideshare.net

仕事のコードを Go にリプレースしたという実践的な内容でした。画像関係のライブラリなども紹介されていました。何をするにもだいたい既にライブラリがあるということで、 Go はライブラリがない、というのはもう過去の話ですね。

ExcelとGo

by shibukawa さん

www.slideshare.net

Excelスプレッドシートから Go のコードをジェネレートする話。ネタといいつつもちゃんと AST 取得したりしている凝り様。どこの会社にも何人かいる Excel エキスパートおばちゃんが Gopher 化する可能性を期待させる LT でした。

asynchronous workloads via beanstalkd

by Louis さん (Orb)

スライド見つからず。 beanstalkd でキューイングするライブラリの話でした。

DB.SetConnMaxlifetime()

by methane さん (KLab)

docs.google.com

sql/database のコネクションプール周りのパッチがマージされるまでの経緯を説明されていて個人的にすごく面白かったです。 この機能は Go 1.6 から入っているらしいので試してみようと思いました。 (まだ 1.6 にしていないのでまず upgrade しなければ ...)

SensorBeeのご紹介

by disktnk さん (Preferred Networks)

スライド見つからず。 SensorBee という IoT 向けのストリーム処理エンジンの紹介でした。途中、ラブライブの映像に笑い男を合成するデモがあり、当日一番とも言える盛り上がりを見せました。

例えば、正規表現を避ける

by songmu さん (Hatena)

例えば、正規表現を避ける

正規表現は便利だけど strings パッケージの関数などで代替できる場合も多いという話。これは普段から心がけているので頷いてしまう内容でした。後半はコマンドラッパーの horenso について。これは cron などで実行するコマンドをラッピングしてレポーティングを行うコマンドだそうです。便利そうなので今度使ってみようと思いました。

go-plugin の紹介

by morikawa さん (Eureka)

スライド見つからず。 hashicorp/go-plugin のコードリーディングをした感想という感じでした。冒頭、 hashicorp 嫌いな人いたらすみません、という前置きで笑いが起きました。みんな大好き hashicorp 。

イベント全体の感想

写真を撮り忘れてしまったのですが、会場となった Eureka さんのセミナースペースは広くて綺麗でした。ただ私の尻が薄いこともあって椅子の座面の固さがちょっと辛かったです。発表では Gopher くんの可愛さに触れている方が多く Gopher くん (と Go) 愛されてるなと思いました。Eureka さんは Go を盛り上げようと色々イベントを企画されていて素晴らしいですね。 Go 盛り上がってる ʕ◔ϖ◔ʔ

f:id:tchssk:20160318132045j:plain