SendGrid公式ライブラリの今

この記事はSendGrid Advent Calendar 2016の11日目の投稿です。
マシンのキーボードに関しては保守派の佐藤です。最近、新しいMacBook Proを手に入れましたが、もちろん物理ESCキー付きです。

## はじめに
SendGridは現在7つのプログラミング言語（[C#](https://github.com/sendgrid/sendgrid-csharp), [Go](https://github.com/sendgrid/sendgrid-go), [Java](https://github.com/sendgrid/sendgrid-java), [PHP](https://github.com/sendgrid/sendgrid-php), [Node.js](https://github.com/sendgrid/sendgrid-nodejs), [Ruby](https://github.com/sendgrid/sendgrid-ruby), [Python](https://github.com/sendgrid/sendgrid-python)）向けにWeb APIにアクセスするためのライブラリを提供しています[^1]。ソースコードはいずれもGitHubで公開されており、誰でも参照、フォーク、修正、Issue報告が可能です。いつからかもう忘れてしまいましたが少なくとも2年くらいにはなるでしょうか、趣味で全リポジトリをウォッチし続けてきたので[^2]、これまでの歴史や最新状況をまとめてみたいと思います。

## 過去
元々公式ライブラリは、メール送信のみ可能なものでした。概ねWeb API v2経由でしたが、中にはSMTP経由での送信が可能なものもあったり、Ruby向けライブラリが存在しなかったり、言語毎に機能やインターフェイスに互換性がなく混沌としていました。その後、SMTP経由のメール送信機能は一律排除され、[Web API v2のメール送信エンドポイント+SMTP API](https://sendgrid.kke.co.jp/blog/?p=3598)に特化するようになりました。[^3]

## 現在
直近で大きな変化があったのは、2016年6月に[Web API v3のメール送信用のエンドポイント](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/Mail/index.html)が追加されたタイミングです。このタイミングでv2のサポートをやめ、v3のみをサポートするよう変更されました。これに伴い、v3の全エンドポイントが利用可能になりました。これは破壊的な変更で、それ以前のバージョンとの互換性は全くありません。また、[C#](https://sendgrid.com/blog/using-c-to-implement-a-fluent-interface-to-any-rest-api/), [PHP](https://sendgrid.com/blog/using-php-to-implement-a-fluent-interface-to-any-rest-api/), [Python](https://sendgrid.com/blog/using-python-to-implement-a-fluent-interface-to-any-rest-api/), [Ruby](https://sendgrid.com/blog/using-ruby-to-implement-a-fluent-interface-to-any-restful-api/)ではFluent Interfaceが採用されています。一方、[Go](https://sendgrid.com/blog/building-a-dependency-free-http-client-in-go/), Java, Node.jsについては今のところFluent Interfaceの採用は見送られています。また、コード管理プロセス上の大きな変化として、マージ前のコードレビューがちゃんと行われるようになりました。[^4]

ライブラリの開発は[3ステップ進められている](https://github.com/sendgrid/sendgrid-nodejs/issues/335)らしく、現在はステップ2とのことです。

1. [済]7言語に対する全v3エンドポイントのサポート
2. [途中]メール送信エンドポイント向けのヘルパーの整備
3. [未][USE_CASES](https://github.com/sendgrid/sendgrid-python/blob/master/USE_CASES.md)に実用的なサンプルを蓄積



## ライブラリの構成
現在のライブラリは、2段構成になっています。各ライブラリ名の**\***部分にはプログラミング言語名(rubyやjavaなど)が入ります。

- **\*-http-client**
コアとなる汎用のHTTPクライアントライブラリです。SendGridがイチから作ったもので、[可能な限り依存ライブラリをなくす方針](https://sendgrid.com/blog/building-a-dependency-free-http-client-in-go/)で開発されています。[^5] 通常は、後述する「**sendgrid-***」を使うので、こちらのライブラリを直接使うことはあまりないと思います。

- **sendgrid-***
「**\*-http-client**」に薄い皮を被せて、SendGridのWeb API v3にアクセスできるようにしたライブラリです。通常はこちらのライブラリを自身のアプリケーションから直接呼び出して使います。核となるコードは非常にシンプルで、このリポジトリに含まれているコードのほとんどは、サンプルコードと複雑なメール送信周りのパラメータを構築するためのヘルパー機能の実装です。

## サンプルコード
各リポジトリに含まれています。まずはこれを見ると雰囲気がわかると思います。[^6]
[C#](https://github.com/sendgrid/sendgrid-csharp/tree/master/examples), [Go](https://github.com/sendgrid/sendgrid-go/tree/master/examples), [Java](https://github.com/sendgrid/sendgrid-java/tree/master/examples), [PHP](https://github.com/sendgrid/sendgrid-php/tree/master/examples), [Node.js](https://github.com/sendgrid/sendgrid-nodejs/tree/master/examples), [Ruby](https://github.com/sendgrid/sendgrid-ruby/tree/master/examples), [Python](https://github.com/sendgrid/sendgrid-python/tree/master/examples)

## 今後
実際使ってみると感じると思いますが、まだ未成熟なものが多く、現在も活発に更新が続いています。小さな変更は随時行われていますが、大きな変更は[Project](https://github.com/sendgrid/sendgrid-csharp/projects)という単位で管理されています。次のようなものがあります。

- **Inbound Parse Helper**
[Inbound Parse Webhook](https://sendgrid.kke.co.jp/docs/API_Reference/Webhooks/parse.html)の受信機能の追加を目指しているプロジェクトです。

- **Mail helper Enhancement**
メール送信エンドポイント向けのヘルパーを整備するプロジェクトです。

他にもC#ライブラリでは[.NET Core対応のプロジェクト](https://github.com/sendgrid/sendgrid-csharp/projects/3)などもあります。（と、書いてたら2日前にDoneしてました。人柱が必要だ。）
今後の方向性についてはissueを確認するとなんとなく見えてくるでしょう。例えば、[今後発生する破壊的変更についても議論](https://github.com/sendgrid/sendgrid-csharp/issues/317)されています。

## トラブル時の対処方法
ライブラリ提供についてのSendGridの姿勢は[こちらの記事](https://sendgrid.com/blog/apis-perfection-vs-reality/)で感じ取れるのではないかと思いますが、最終的なとりまとめはSendGridがやるけど、**あくまでもコミュニティーが主体**、みたいなノリです。ライブラリを使っていて問題に遭遇した場合、この点を理解しておくことがとても重要になります。この点を踏まえて、問題を発見した場合は次の手順で対処するとスムーズかと思います。

1. ライブラリを使用せずに[Web APIを直接叩いて](https://www.getpostman.com/)、同じ問題が再現するか確認して、問題の原因を**ライブラリかWeb APIかに切り分ける**。
2. ライブラリを使用せずに問題が再現する場合（Web APIの問題と確信が持てる場合）、SendGridサポートに問い合わせる。
3. ライブラリを使用した場合に限り問題が再現する場合（ライブラリの問題と確信が持てる場合）、

    1. **サンプルコードを確認**してやりたいことと同じコードがないか探す。あったら真似をする。  
    2. GithubのIssueを確認し、同様のものがあったら+1するなどして「**修正してほしいアピール**」をする。
    3. 同様のものがない場合は、[**現象の再現に必要な情報を添えて**](http://www.chiark.greenend.org.uk/~sgtatham/bugs-jp.html)Issueをあげる。

サービスの一時的な障害やアカウント固有の問題など、ライブラリに起因しないものは「[サポートに問い合わせて欲しい](https://github.com/sendgrid/sendgrid-ruby/issues/127)」と返されてしまうので、キッチリ切り分けないと[無駄な時間を取られる](https://github.com/sendgrid/sendgrid-php/issues/304)ことになります。逆にSendGridサポートにライブラリのバグを報告しても対応してくれることはないでしょうし、使い方を聞いてもREADMEとソースコードを見て欲しいと返されるでしょう。

また、Issueで「**status: help wanted**」のタグがついているものは着手されていません。修正要望が多数あるものは比較的早く対応されますが、そうでないものは後回しになるので、+1するなどのアクションをするか、それも待てない場合は、コードを修正してプルリクエストを出すのが早道だと思います。プルリクを出す場合はCLA/CCLAという契約書にサインする必要があります。詳しくは[README](https://github.com/sendgrid/sendgrid-csharp#how-to-contribute)を参照してください。

あと、ライブラリの改善に寄与すると[何か良い物をもらえることもあるようです](https://github.com/sendgrid/sendgrid-csharp/pull/342)。

## 雑感
各リポジトリを見るとわかると思いますが、最近の管理はほぼ全て[この人](https://github.com/thinkingserious)がやっています。たまに書き込まれる酷いコメントや、サッパリ状況が読み取れないコメントにも常に前向きな回答を返せる精神的タフさはちょっと真似できません[^7]。毎日大量のIssueをさばいて、コード修正やプルリクのレビューもやっているので、黒子がいるんじゃないかと思って中の人に聞いてみたらガチで一人でやってる、とのことでした。[^8] 大変そうだなぁ、というわけで、自分もたまにプルリク送ったりコメント入れたりして少しでも改善する方向で動いています。

- https://github.com/sendgrid/ruby-http-client/pull/5
- https://github.com/sendgrid/sendgrid-python/pull/240
- https://github.com/sendgrid/sendgrid-ruby/pull/114
- https://github.com/sendgrid/sendgrid-ruby/issues/119

### 補足
[^1]: [Perl向けのライブラリ](https://github.com/sendgrid/sendgrid-perl/)もありますが、Web API v2対応バージョンのみです。現在はサポートを終了しており、Web API v3対応も行われていません。
[^2]: SendGridの公式ドキュメントも[Github](https://github.com/sendgrid/docs)で公開されており、これもウォッチし続けています。SendGridの新機能や非公式機能をチェックするにはこっちがお薦め&楽しいです。
[^3]: Suppressionリストの取得やAPIキーの発行など、メール送信以外の一部のエンドポイントに対応したものもありました。
[^4]: なに言ってんだって感じですが、裏を返せば、以前はテストさえ通ればゆるくマージされていたということですw そのせいでライブラリごとにインターフェイスや機能が統一感のないものになっていたと感じています。
[^5]: これを初めて見たとき、正直目眩がしました。世の中には実績のあるHTTPクライアントライブラリはいくらでもあるのにいまさらイチから作る必要があるのか、と。やりたいことを実現するための判断ということなのだと思います。
[^6]: Fluent Interfaceを採用していないものは正直残念な感じがします。
[^7]: 世の中にはいろんな人がいます。[コーディング規約が気に食わない人](https://github.com/sendgrid/sendgrid-php/pull/319)、[インターフェイスが気に食わない人](https://github.com/sendgrid/sendgrid-csharp/issues/303)、[とにかく新しいライブラリは全部気に食わない人](https://github.com/sendgrid/sendgrid-nodejs/issues/335)...修正リクエストを投げてくれる人はとても前向きですね。まぁ、本当に気に食わなければ公式ライブラリなんて使わずにAPIを直接叩けば良いと思います。API自体はとても[シンプル](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/index.html)なので。
[^8]: SendGridの[Web API v3のエンドポイントは233ある](https://sendgrid.com/blog/stoplight-io-to-test-api-endpoints/)そうです。その後も増え続けています。これをサポートするライブラリを一人で7言語分面倒みるとなると今の管理方法はやむを得ないということなのだろうか。