1. はじめに
こんばんは、キャディでバックエンドエンジニアをしている kuwana-kb(@kuwana_kb_)と申します。
キャディでは Rust を用いたプロダクト開発をしています。Rust は安全性・速度・並行性に秀でた言語ですが、まだ国内での採用事例は少なくWeb アプリケーションの開発事例もあまり見受けられません。この事実は採用にも影響していて、はじめから Rust ができる人を採用するのはなかなか厳しいのが現状です。そこで弊社では Rust 未経験の人でも Rust を使って開発できるようにオンボーディングを工夫しています。私自身も会社に入るまで Rust を使ったことがなかったのですが、おかげさまで今では毎日 Rust で開発をしています。
今回はキャディのバックエンドチームの Rust オンボーディングについてお話したいと思います。
[toc]
2. 簡単な自己紹介
まず、オンボーディングを受けた私のバックグラウンドを軽くご紹介します。
私は2019年8月にキャディにジョインしました。入社当時のキャリアとしては、Webディレクターを3年、エンジニアを1年ほど経験していて、それまでは Go を用いたバックエンドの API の実装、クラウドインフラの構築をしていました。Rust については全く経験がなく、せいぜい名前を聞いたことがある程度でした。
現在はキャディでバックエンドエンジニアとして Rust を用いた API の実装や GCP を中心としたインフラの構築をしています。
3. Rust のオンボーディング
① 「The Book」 で基礎を学ぶ
「The Rust Programming Language」
Rust を学ぶ上ではじめに手をつけたのが「The Book」です。The Book とは 「The Rust Programming Language(TRPL)」の通称で、Rustプロジェクトが公式でメンテナンスしている入門書です。本書はネット上で無料で公開されています。また、PDF に出力することもできるので電子書籍として持ち歩くことも可能です。本書には Rust の基本的なことが詰まっていまして、入門に最適な書籍です。
ちなみに弊社の Rustacean に入門で使った書籍のアンケートをとってみました。The Book が一番人気で、オライリー本や「実践Rust入門(通称:自転車本)」を使った人もいますね。書籍は使っていないという猛者もいましたw また、アンケートには公式の docs や使いたい crate の example を読んで勉強した、というコメントもありました。
② 雛形ソースコードでプロダクトの実装を理解する
さて、「The Book」で基礎を身に着けたら、少しずつ業務に入っていきます。
私のチームの場合、業務アプリケーションに慣れていくための手段として、 業務アプリケーションの雛形を用意しています。雛形がどういったものかというと、以下の役割を満たす必要最小限のソースコードになります。
- 業務アプリケーションで扱う crate(Rustにおけるパッケージ)に慣れる
- 業務アプリケーションのアーキテクチャを理解する
Rust オンボーディングの観点でいうと1つめが重要です。TRPL では基礎的な crate しか使わないため、業務で扱う crate の学習が別途必要になってきます。一例を挙げると、ORM のdiesel、 grpc サーバーの tower-grpc 、 シリアライズ・デシリアライズの serde などです。いきなりプロダクトのソースコードを読むと知らない crate や記法の多さに困惑する可能性があるため、この雛形でワンクッション置く形にしています。
私のチームでは以下のような構成のソースコードを使用しています。 雛形が読めるようになったらいよいよAPIの実装です。
src/
├ domain/
│ └user.rs
├ usecase/
│ ├ input/
│ │ └get_user_input.rs
│ ├ input.rs
│ └ get_user.rs
├ infrastructure/
│ ├ grpc/
│ │ ├ convert/
│ │ │ └ get_user.rs
│ │ ├ covert.rs
│ │ └ server.rs
│ ├ grpc.rs
│ └ postgres.rs
│
├ domain.rs
├ usecase.rs
├ infrastructure.rs
├ error.rs
└ lib.rs
③ API を自分で書く
いよいよ業務アプリケーションの実装に着手します。最初は API を一本作ることを目標にしました。
ここまでくると、「The Book」と雛形ソースコードの読み込みで実装に必要な知識はある程度身についています。多少詰まることもあるので最初の方はペアプロで実装をすすめていきます。また、レイヤードアーキテクチャのレイヤー単位で PR を作成し、段階的に独り立ちしていきます。
API 一本をひとりで作れるようになればオンボーディングは終了です。「The Book」の読み込みから API の実装に至るまで、オンボーディングの期間としては、おおよそ3週間くらいでした。
4. Rust で躓いた点
ここではRustを学ぶ上で私が躓いた点を共有します。
Trait
Trait
は抽象型の一種で、他言語でいうInterfaceや型クラスのようなものです。Rust入門当初の私は、 parse()
や try_into()
といったメソッドがなぜ意図した型に変換できるのか、仕組みがよくわかっていませんでした。
これは FromStr
, TryFrom
といったTraitと型推論の理解が浅かったことが原因のように思います。上述の FromStr
や TryFrom
といった基礎的な Trait
の実装を実際に自分の手で書いてみるのが理解につながると感じました。
Option と Result 型
Option
とResult
はそれぞれ「存在しないかもしれない」、「失敗するかもしれない」という文脈を表す型です。これまで自分が触ってきた言語にはない概念だったので理解に苦労しました。また、付随するメソッドも多いのでケースによってうまく使い分けることが難しかったり、メソッドの存在を知らずに車輪の再発明をしてしまうことがありました。
こちらは実装に迷ったら Option
や Result
のdocsを見て、少しずつ使い方に慣れていくのがよいと思います。
特殊な構文
エラー変換の糖衣構文である ?
や アノテーション ::<>(turbofish)
など、初見では理解しづらく詰まりました。こういった記号ってネット上で検索しづらいので、わかる人にすぐ聞ける環境だったのはよかったと思います。
所有権システム
Rustの大きな特徴の1つである所有権システムですが、難しいです。今でも詰まります。概念の理解も必要ですが、ルールも結構複雑です。まずは、clone()
等を使って動かすことを優先し、慣れてきたら少しずつ理解していくという形でもよいかな、と個人的には思ってます。
今振り返ってみると、Rust特有の難しさは所有権システムだけなのではないでしょうか。構文への慣れはどの言語でもありますし、Trait
や Option
, Result
なんかは Haskell や Scala で似たような概念があります。当たり前かもしれませんが、Rust に対して感じる難易度は、それまで経験してきた言語によって左右されるように思います。
5. Rust の学習に効果的だったこと
コンパイラ駆動開発
Rustのコンパイラはとても優秀です。コンパイルが通らないコードを書いた時、cargo check
コマンドで誤っている点を優しく教えてくれます。また、cargo clippy
コマンドによるlintによって、冗長な記述やより最適な関数の提案をしてくれます。
例として上記のスクリーンショットでは、変数が使われていないことの警告と変数を可変にすべきというエラーが表示されています。開発者はコンパイラとの対話を通じて Rust のコードが書けるようになっていくでしょう。
Rust Playgroundを活用する
Rust Playground とは、 Rust をWebブラウザ上で気軽に使えるサイトです。Go の Playground と同じようなものです。関数や derive の挙動などで不明な点ががあれば、とりあえず Rust Playground で動かしてみることで簡単に動作確認ができます。また、 Rust Playground でサンプルコード書いてURLを共有することもできるのでレビューでもたまに使います。
ペアプロでRustのコーディングを学ぶ
Rust に限った話ではないですが、やはりペアプロは有効です。少しでも気になった点はその場で解決できる点がよいです。また、レビューでは伝えづらい Rust コーディングのコツなんかも学べると思います。例えば、実装途中の関数は unimplemented()
でコンパイルを通すようにする、とかは一緒にコーディングしないと得づらい知見なんじゃないでしょうか。ちなみに私のチームではペアプロ時に VS codeの LiveShare 機能を使っています。それぞれのモニターで共通のソースコードを編集できて便利です。
日報で非同期に解決
入社して1ヶ月間は毎日日報を書いていました。この日報では、その日詰まったことを書いてわかる人がそれに回答する、という運用をしていました。日報というとちょっとめんどくさい雰囲気がするかもしれませんが、以下の点で良かったです。
- 疑問を非同期的に解決できる
- 疑問をログとして残せるので後から入ったメンバーが参考にできる
非同期に解決できて過去ログを遡れればよいので、日報という形ではなく疑問解消用のslackチャンネルを作るといった運用でもいいかもしれません。
まとめ
以上がキャディのバックエンドチームにおける Rust オンボーディングでした。 Rust を始めたい方や Rust の導入を検討している方の参考になれば幸いです。