Rustを学び始めたきっかけ

tommy氏:よろしくお願いします。Fablicという会社で働いてたんですけど……7月から吸収合併により楽天社員として働いています。よろしくお願いします。たぶん今日のメンバーの中では1番ライトなトークだと思うので、リラックスして聞いていただければと思います。

僕がなんでRustを使おうと思ったかという話なんですが、この『達人プログラマー』に、「毎年1つの言語を学習する」っていうことが書いてあって。

なるほど、と。僕が当時まともに使ったことのある言語ってこんな感じだったんですけど、「新しいことがしたい!」と思って。

新装版 達人プログラマー 職人から名匠への道

GoとRustをぼんやり検討したんですが、「Goならこの先仕事でふつうに使うんじゃないか」と。……ホントかわかりませんが、思いました。

(会場笑)

時代はRustだ、ということでRustを勉強し始めました。

まず「Rustを使う準備」ですね。準備とはなんぞや、ということなんですけど……。みなさんこのページ見覚えがあると思います。

これを読みながらやっていたんですが、「フムフムなるほど……」以上の感想が出てこなくて。「僕が作りたかったものは動くものだ」ということで、2chのまとめサイトをRustで作ってみました。最近ワールドカップがあったので、自分的には活躍していたんですけど。

やっていることはものすごく単純で、xmlを取ってきてDBに保存して、それをJSONで出力するという。ふだんやっているのですごくイメージできる……Webサービスをどう作ればいいかのイメージはすでに僕の中にあるので、新しい言語を勉強するところで「これを実現するためにはRustではどうすればいいのか」という視点で考えることができて、けっこう勉強にはよかったかなと思います。

そして、これが僕がそのWebサーバーとして使ったRustのライブラリですね。

実装を意識すればいいだけのライブラリは、Rustでは既に用意されています。ですので、僕がやることは、僕が実現したいことを素直にやっていくこと。そうすると、Webサービスと言うか……JSONを返すくらいのWebサーバーなら簡単に作ることができます。便利です。

Rustを導入した理由

「Rust導入のきっかけ」ですね。これまでは趣味のアレなので、業務でどうやって使ったかということなんですが。

僕は今、ラクマというサービスを開発しているんですが、僕がジョインした当時、チームの人数が大きく変わり始めていました。業務の自動化の機運が高くなってきてたんですね。

その1つとして、弊社はRubyを主に採用していて、マイクロサービスみたいな感じで、アプリケーションが複数分かれています。アプリケーションから共通で呼ばれる、社内で使うgemみたいなものを作っていて、こういうフローで自動化をしました。

ここで、Herokuに乗せたときに問題が発生しました。もともとローカルのマシンでRubyを実行してGitHubのタグを切っていたんですけど、これHerokuで都度デプロイするようになると、bundle installに2分くらいかかって、「自動化の意味ねぇ」という状態に陥りました。

ここで社内のSlackでなぜ遅いのかという理由を説明してたら、ある人から「node.jsで書き直す・Rustで書き直す・goで書き直す」みたいな提案があって。なるほどね、と。

(会場笑)

僕がこの作業をやっているとき、つまりcircle CIが回ってる間完全に遊んでいたので、別の言語でやろっかな、と。でもRustを導入しても、みんなわからないしどうしましょうか、みたいな。ここで、「僕が例外をキャッチしてレスキューするモデルであれば可能なんじゃないか」ということで、改めてRustの機運が高まります。

(会場笑)

Rustの運用とその後

次に、「運用とその後」ですね。無事Rustでスクリプトを組んで、バイナリを用意してあげて、Heroku上で実行したことで早くなりました。みんなけっこう気付いてくれて、無事、当初チームで問題としていたものもRustで解決することができました。

しかし、当然運用していると、問題が発生しました。なにかが動いていない。でも、みんなRustを知らないのでぜんぜんわからない。「ぜんぜんわからん。でも雰囲気ですらすら読めます」みたいな。

(会場笑)

ここで、僕の会社でもRustを書ける人が僕しかいないということが問題になる……かと思ってたんですけど、みんなわりと、短いスクリプトだったらすらすら読んでくれました。「だいたいあってる」。「ぜんぜんわからんけどこれでいいですか」っていうプルリクが飛んできて……。

(会場笑)

「完璧です」と。

(会場笑)

本番で動いてるとはいえデプロイスクリプトの一端で、間違っても潰しが効くっていうことで、わりとみんな積極的にやってくれました。これはもうチームメンバーにありがとうございます、っていう感じですね。

で、真の問題はクロスコンパイルで。

参加者:この絵文字ヤバいっスね……(笑)。

tommy:そっすね(笑)。

(会場笑)

滅多にいじらないので、バイナリを作るとこは僕が手動でやっています。vagrantを立ててHerokuと同じ環境でコンパイルしました。チームで運用していくことを考えるとマストなので反省していますが、これ以降修正の機会がなくて、まだ着手してないという感じですね。

自分が手を動かしてイメージできるもので練習

まとめです。Rustを業務で使ってみようかな、というときに僕がやったら良さそうだと思ったのは、自分が手を動かしてイメージができるもので練習すると便利かなと思います。僕の場合は簡素なWebサービスだったんですが、Rustはまだチュートリアルみたいなものも少ないので、そういうことは有効なんじゃないかと思います。

僕の場合は転職したばかりだったので、事業ドメインにあまり関係のないところをやらせてもらえるチャンスがありました。そんなときに、先ほどのWebサービスみたいなものを作ってGitHubで公開もしていて「Rust使えます」ってアピールしてたので、そういう機会があるたびに「Rust、いいんじゃない」みたいな支援をしてもらうことができました。

「不具合が起きたら自分に任せろ」というスタイルでやるのは、わりと新しいことをやるときはアリかなと思うんですが、その後のケアをするのもセットかなと思います。

あとは、「チームの懐の深さと新しい技術の導入に対する理解度」は僕にコントロールできるところではないので、改めてチームメンバーに感謝したいなと思います。

テストにおけるTips

おまけで、エモかったので少しだけ、テストのTipsを。僕がちょっと「あれ?」と思ったことを共有します。

まず1個目、Rustのテストってデフォルトでマルチスレッドで実行されるんですよね。これがDBとか、同じファイルを書き換えるみたいなことは、単純にそういうテストとの相性悪いので。実質的にWebサービスでテストしようと思った場合、このオプション。test-threads=1として、そのままでいこうかなと思いました。

次。「Private methodのテストは同ファイル内に書く」。テストって、テストデータ書いたらもう十何行とかやったりするので、個人的には分けて書きたかったんですけど。「プライベートなメソッドにそのファイルからしかアクセスできない」というのは、言われてみれば1つの答えな気もしました。

あとは、行数が増えて見通しが悪くなったら設計を見直せ、ということかなと。言語仕様上でそういうところが考えられるかどうかということを思ったりしました。

次。Mocking LibraryのMockitoというライブラリがあるんですが、これがちょっと、僕が想像してたのと違っていたので共有します。仕様書読めば書いてあるんですが、ローカルマシン上でHTTPサーバーを裏で立ち上げてくれるっていうライブラリです。

コード内で指定しているURLでアクセスする先をMockitoで立ち上げたサーバーに向ける、みたいな感じで。PHPやRubyでふだん使っているモックみたいな仕組みとはまるで違うので、注意したほうがいいかなと思いました。

これですね。もともとのスクリプトってRubyで書いてあったんで、単純に置き換えたんで比較してみました、というのもあるので、よかったら見てみてください。

楽天で大企業の恩恵を享受しつつ、こういうアットホームな雰囲気のチームで働けるので、ぜひよろしくお願いします。

ご清聴ありがとうございました。

(会場拍手)

司会者:ありがとうございました。質問ある方いらっしゃいますか?

(会場挙手)

質問者:テストのところの、「プライベートメソッドだと分けられない」っていうやつなんですけど。プライベートのやつって、その下のモジュールの中からはアクセスできるから、ふつうに分離できるかなと思ったんですけど。

tommy:なるほど。今回作ったものが簡素すぎて、そんなに階層構造が複雑じゃなかったのでその検証ができてなかったです。

質問者:なるほど、わかりました。

tommy:ありがとうございます。