Slide 1

Slide 1 text

RustでREST APIを開発した話

Slide 2

Slide 2 text

名前 粟⽥ 恭介(@wooootack) 経歴 2019年に異業種からエンジニアに転職し、2021年にプラハに⼊社。 仕事内容 フルサイクルエンジニアとしてプロダクト開発全般に従事。 約1年前からチームリーダーとして、マネジメントにも挑戦中。 趣味 ⾞(写真は愛⾞)、アイドルヲタク(歴⻑め)、ぷよテト(テトリス勢) ⾃⼰紹介

Slide 3

Slide 3 text

はじめに ● Zennに書いたこちらの記事からRustの技術的な部分に関連する内容を抜粋し てお話しします。 ○ 記事を書いたのが約半年前なので、最新情報に追従できていない可能性があります :bow: ● 今⽇はREST APIを開発してみて得られた知⾒や感想を話します ○ どうやって開発するかは話しません :bow: ● サンプルリポジトリはこちら

Slide 4

Slide 4 text

使⽤技術 / 設計思想 使⽤技術 ● Rust(1.64.0) ● actix-web(4.1.0) ● diesel(2.0.0) 設計思想 ● DDD ● オニオンアーキテクチャ ● モジュラモノリス

Slide 5

Slide 5 text

ディレクトリ構造 ● bin ○ エントリーポイントとなるファイルを置く ○ api.rs -> APIサーバー起動時のエントリーポイント ○ seed.rs -> シードデータ投⼊時のエントリーポイント ● modules/ ○ 後述 ● scenarios/ ○ エンドポイントと1:1で紐づくシナリオを定義 ○ 各モジュールを使って処理を⾏う ○ オーケストレータ的な役割 ● routers.rs ○ RESTAPIのルーティング定義 ● schema.rs ○ dieselが⾃動⽣成するschemaファイル

Slide 6

Slide 6 text

ディレクトリ構造 ● modules/common ○ 共通処理の定義。エラー定義などが該当する。 ● modules/diesel ○ dieselの処理は複数モジュールで呼び出されるのでここに置く ● modules/user ○ 単体のRESTAPIとして動かせるようにレイヤー分け ○ DDD+オニオンアーキテクチャに従っている ● modules/task ○ userと同じなので省略

Slide 7

Slide 7 text

良かったところ 1. モジュールの可視性を細かく設定できる 2. エラーハンドリングを簡略化できる

Slide 8

Slide 8 text

1. モジュールの可視性を細かく設定できる ● モジュールそのものをpublic/privateに宣⾔できる ○ 内部で間違えてpublicにしてしまって外部に公開されるみたいなことを防げる ● struct, fnごとにpublic/privateに宣⾔できる ○ 同じモジュール内でも呼ばせたくないみたいなこともできる ● pub(crate), pub(super) のような構⽂がある ○ どこまで公開するかを細かく設定できる 参考 ● https://doc.rust-jp.rs/rust-by-example-ja/mod.html

Slide 9

Slide 9 text

実際の例 - モジュール単位の可視性の設定 各モジュールはpresentation層のみを 外部に公開することで疎結合に保たれている

Slide 10

Slide 10 text

良かったところ 1. モジュールの可視性を細かく設定できる 2. エラーハンドリングを簡略化できる

Slide 11

Slide 11 text

2. エラーハンドリングを簡略化できる ● Result + ? + Fromトレイトを使えば、エラーハンドリングが楽になる ○ エラーの詰め替え作業が激減 ○ match式でOkかErrかを判定して〜みたいなコードが消えて読みやすくなる 参考 ● https://doc.rust-jp.rs/rust-by-example-ja/error/result.html

Slide 12

Slide 12 text

実際の例 - Fromトレイトの実装① 発⽣する全てのエラーがApiErrorに変換されるようにFromトレイトを実装

Slide 13

Slide 13 text

ApiErrorにはactix-webのResponseErrorトレイトを実装することで APIサーバーのResponseとして返せるように 実際の例 - Fromトレイトの実装②

Slide 14

Slide 14 text

実際の例 - 簡略化されたエラーハンドリング ● ?演算⼦を書くだけで良くなる ● 例:リポジトリでDieselErrorが発⽣ ○ DomainError ○ ↓ ○ UsecaseError ○ ↓ ○ ApiError ○ ↓ ○ Response(status_code: 500) ● 他の層も同様にエラーは全部?でOK ↑(例)scenario層のコード

Slide 15

Slide 15 text

苦労したところ 1. 可変参照の扱いが(場合によっては)難しい 2. エコシステムが(まだ)充実していない

Slide 16

Slide 16 text

1. 可変参照の扱いが(場合によっては)難しい ● Rustの可変参照は安全性を担保するために多くの制約がある ○ 複数箇所から同時に参照できない ○ データを変更できない など... ● 今回の作りでは、scenario層でDBのトランザクションを管理する ○ dieselでtransaction貼った時のコネクションオブジェクトは 可変参照 ○ これを複数の場所に渡す必要が⽣まれてしまい、実装できなかった 参考 ● https://doc.rust-jp.rs/book-ja/ch04-02-references-and-borrowing.html

Slide 17

Slide 17 text

実際の例 - トランザクションを張らない実装 (ツッコみどころはあると思いますが) ● conn を1箇所にしか渡さないのでOK ● outpuddingはasyncの戻り値の型を明 ⽰するための記述 ○ 詳細はこちら参照

Slide 18

Slide 18 text

実際の例 - トランザクションを張る実装 ● こちらはコンパイルエラーになります ● txは &mut なコネクションであるた め、execute関数の引数に2度渡されて しまうことでエラーになっています ● これをうまく解決する⼿段を私は⾒つ けられませんでした...

Slide 19

Slide 19 text

苦労したところ 1. 可変参照の扱いが(場合によっては)難しい 2. エコシステムが(まだ)充実していない

Slide 20

Slide 20 text

2. エコシステムが(まだ)充実していない ● テストを書く時の良いライブラリがない ○ Jestが恋しくなりました ... ○ 単体テストならそこまで問題にならないが、統合テストを書く時に困った ○ 特に統合テストにおいては、セットアップ関数やクリーンアップ関数などを動かしたい ● VSCodeで書いてるとマクロの内容までは理解してくれずに、型補完が効かな い時があった ○ ビルドは通るけど、エディタ上では型が分からないみたいな ○ 当時の話なので、今はさらに進化していると信じたい

Slide 21

Slide 21 text

実際の例 - テストを書く際に⼯夫したこと ● 単体テストと統合テストを分けて動かせるようにした ○ 標準のテスト機能とフィーチャーフラグ機能を使って実現した 参考 ● https://doc.rust-jp.rs/book-ja/ch11-01-writing-tests.html ● https://doc.rust-lang.org/cargo/reference/features.html

Slide 22

Slide 22 text

実際の例 - テストを書く際に⼯夫したこと これは結構簡単にできます ● Cargo.tomlにfeaturesを定義 ● 統合テストを書く時は、featuresを指定 ● cargo test --feaures integration_test

Slide 23

Slide 23 text

気を付けた⽅が良さそうなところ ● 構造体に参照を保持させると⼀気に難しくなるので、避けた⽅が無難 ○ ただリポジトリはコネクションを持っておきたいなど、必要な場⾯もありそう ● 特にテスト周りはまだ不便に感じる部分が多いかも ● PrismaやActiveRecordレベルのORMはまだ存在しない(と思う)

Slide 24

Slide 24 text

まとめ RustでAPI開発、ありだと思います

Slide 25

Slide 25 text

We are Hiring 株式会社プラハの応募はこちらから ぜひ⼀緒に、ものづくりを楽しみましょう! 頭の中にしかないアイデアを形にしていく「ものづくり」はすごく楽しいことです。 しかし学ぶべきことも数多くあり、難しい局⾯に⽴ち向かうことも多々あることでしょう。 そんな時、⼀緒に切磋琢磨できる仲間が集まっていれば、どんな挑戦にも楽しく挑めるのではないでしょうか。 そのような素晴らしい環境で「ものづくり」をしたいと感じてくれた⽅がいましたら、ぜひお声がけください! 株式会社アガルートテクノロジーズの応募はこちらから https://tech.agaroot.co.jp/#recruit https://www.praha-inc.com/recruit