Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RustでREST_APIを開発した話.pdf
Search
Kyosuke Awata
August 24, 2023
Programming
0
230
RustでREST_APIを開発した話.pdf
Kyosuke Awata
August 24, 2023
Tweet
Share
More Decks by Kyosuke Awata
See All by Kyosuke Awata
無理せずに みんなで作ろう 発信文化
wooootack
3
1.7k
雰囲気でSWRを使ったらハマった話
wooootack
0
36
マイクロサービスではなくモジュラモノリスを採用した理由
wooootack
4
2.3k
Other Decks in Programming
See All in Programming
時計仕掛けのCompose
mkeeda
1
300
Kubernetes History Inspector(KHI)を触ってみた
bells17
0
230
Amazon ECS とマイクロサービスから考えるシステム構成
hiyanger
2
560
GitHub Actions × RAGでコードレビューの検証の結果
sho_000
0
270
SwiftUIで単方向アーキテクチャを導入して得られた成果
takuyaosawa
0
270
PHP ステートレス VS ステートフル 状態管理と並行性 / php-stateless-stateful
ytake
0
100
ペアーズでの、Langfuseを中心とした評価ドリブンなリリースサイクルのご紹介
fukubaka0825
2
330
動作確認やテストで漏れがちな観点3選
starfish719
6
1k
Ruby on cygwin 2025-02
fd0
0
150
データの整合性を保つ非同期処理アーキテクチャパターン / Async Architecture Patterns
mokuo
47
17k
Unity Android XR入門
sakutama_11
0
160
Amazon Bedrock Multi Agentsを試してきた
tm2
1
290
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
244
12k
A Tale of Four Properties
chriscoyier
158
23k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Navigating Team Friction
lara
183
15k
Thoughts on Productivity
jonyablonski
69
4.5k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
Making Projects Easy
brettharned
116
6k
VelocityConf: Rendering Performance Case Studies
addyosmani
328
24k
Site-Speed That Sticks
csswizardry
4
380
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
46
2.3k
RailsConf 2023
tenderlove
29
1k
Transcript
RustでREST APIを開発した話
名前 粟⽥ 恭介(@wooootack) 経歴 2019年に異業種からエンジニアに転職し、2021年にプラハに⼊社。 仕事内容 フルサイクルエンジニアとしてプロダクト開発全般に従事。 約1年前からチームリーダーとして、マネジメントにも挑戦中。 趣味 ⾞(写真は愛⾞)、アイドルヲタク(歴⻑め)、ぷよテト(テトリス勢)
⾃⼰紹介
はじめに • Zennに書いたこちらの記事からRustの技術的な部分に関連する内容を抜粋し てお話しします。 ◦ 記事を書いたのが約半年前なので、最新情報に追従できていない可能性があります :bow: • 今⽇はREST APIを開発してみて得られた知⾒や感想を話します
◦ どうやって開発するかは話しません :bow: • サンプルリポジトリはこちら
使⽤技術 / 設計思想 使⽤技術 • Rust(1.64.0) • actix-web(4.1.0) • diesel(2.0.0)
設計思想 • DDD • オニオンアーキテクチャ • モジュラモノリス
ディレクトリ構造 • bin ◦ エントリーポイントとなるファイルを置く ◦ api.rs -> APIサーバー起動時のエントリーポイント ◦
seed.rs -> シードデータ投⼊時のエントリーポイント • modules/ ◦ 後述 • scenarios/ ◦ エンドポイントと1:1で紐づくシナリオを定義 ◦ 各モジュールを使って処理を⾏う ◦ オーケストレータ的な役割 • routers.rs ◦ RESTAPIのルーティング定義 • schema.rs ◦ dieselが⾃動⽣成するschemaファイル
ディレクトリ構造 • modules/common ◦ 共通処理の定義。エラー定義などが該当する。 • modules/diesel ◦ dieselの処理は複数モジュールで呼び出されるのでここに置く •
modules/user ◦ 単体のRESTAPIとして動かせるようにレイヤー分け ◦ DDD+オニオンアーキテクチャに従っている • modules/task ◦ userと同じなので省略
良かったところ 1. モジュールの可視性を細かく設定できる 2. エラーハンドリングを簡略化できる
1. モジュールの可視性を細かく設定できる • モジュールそのものをpublic/privateに宣⾔できる ◦ 内部で間違えてpublicにしてしまって外部に公開されるみたいなことを防げる • struct, fnごとにpublic/privateに宣⾔できる ◦
同じモジュール内でも呼ばせたくないみたいなこともできる • pub(crate), pub(super) のような構⽂がある ◦ どこまで公開するかを細かく設定できる 参考 • https://doc.rust-jp.rs/rust-by-example-ja/mod.html
実際の例 - モジュール単位の可視性の設定 各モジュールはpresentation層のみを 外部に公開することで疎結合に保たれている
良かったところ 1. モジュールの可視性を細かく設定できる 2. エラーハンドリングを簡略化できる
2. エラーハンドリングを簡略化できる • Result + ? + Fromトレイトを使えば、エラーハンドリングが楽になる ◦ エラーの詰め替え作業が激減
◦ match式でOkかErrかを判定して〜みたいなコードが消えて読みやすくなる 参考 • https://doc.rust-jp.rs/rust-by-example-ja/error/result.html
実際の例 - Fromトレイトの実装① 発⽣する全てのエラーがApiErrorに変換されるようにFromトレイトを実装
ApiErrorにはactix-webのResponseErrorトレイトを実装することで APIサーバーのResponseとして返せるように 実際の例 - Fromトレイトの実装②
実際の例 - 簡略化されたエラーハンドリング • ?演算⼦を書くだけで良くなる • 例:リポジトリでDieselErrorが発⽣ ◦ DomainError ◦
↓ ◦ UsecaseError ◦ ↓ ◦ ApiError ◦ ↓ ◦ Response(status_code: 500) • 他の層も同様にエラーは全部?でOK ↑(例)scenario層のコード
苦労したところ 1. 可変参照の扱いが(場合によっては)難しい 2. エコシステムが(まだ)充実していない
1. 可変参照の扱いが(場合によっては)難しい • Rustの可変参照は安全性を担保するために多くの制約がある ◦ 複数箇所から同時に参照できない ◦ データを変更できない など... •
今回の作りでは、scenario層でDBのトランザクションを管理する ◦ dieselでtransaction貼った時のコネクションオブジェクトは 可変参照 ◦ これを複数の場所に渡す必要が⽣まれてしまい、実装できなかった 参考 • https://doc.rust-jp.rs/book-ja/ch04-02-references-and-borrowing.html
実際の例 - トランザクションを張らない実装 (ツッコみどころはあると思いますが) • conn を1箇所にしか渡さないのでOK • outpuddingはasyncの戻り値の型を明 ⽰するための記述
◦ 詳細はこちら参照
実際の例 - トランザクションを張る実装 • こちらはコンパイルエラーになります • txは &mut なコネクションであるた め、execute関数の引数に2度渡されて
しまうことでエラーになっています • これをうまく解決する⼿段を私は⾒つ けられませんでした...
苦労したところ 1. 可変参照の扱いが(場合によっては)難しい 2. エコシステムが(まだ)充実していない
2. エコシステムが(まだ)充実していない • テストを書く時の良いライブラリがない ◦ Jestが恋しくなりました ... ◦ 単体テストならそこまで問題にならないが、統合テストを書く時に困った ◦
特に統合テストにおいては、セットアップ関数やクリーンアップ関数などを動かしたい • VSCodeで書いてるとマクロの内容までは理解してくれずに、型補完が効かな い時があった ◦ ビルドは通るけど、エディタ上では型が分からないみたいな ◦ 当時の話なので、今はさらに進化していると信じたい
実際の例 - テストを書く際に⼯夫したこと • 単体テストと統合テストを分けて動かせるようにした ◦ 標準のテスト機能とフィーチャーフラグ機能を使って実現した 参考 • https://doc.rust-jp.rs/book-ja/ch11-01-writing-tests.html
• https://doc.rust-lang.org/cargo/reference/features.html
実際の例 - テストを書く際に⼯夫したこと これは結構簡単にできます • Cargo.tomlにfeaturesを定義 • 統合テストを書く時は、featuresを指定 • cargo
test --feaures integration_test
気を付けた⽅が良さそうなところ • 構造体に参照を保持させると⼀気に難しくなるので、避けた⽅が無難 ◦ ただリポジトリはコネクションを持っておきたいなど、必要な場⾯もありそう • 特にテスト周りはまだ不便に感じる部分が多いかも • PrismaやActiveRecordレベルのORMはまだ存在しない(と思う)
まとめ RustでAPI開発、ありだと思います
We are Hiring 株式会社プラハの応募はこちらから ぜひ⼀緒に、ものづくりを楽しみましょう! 頭の中にしかないアイデアを形にしていく「ものづくり」はすごく楽しいことです。 しかし学ぶべきことも数多くあり、難しい局⾯に⽴ち向かうことも多々あることでしょう。 そんな時、⼀緒に切磋琢磨できる仲間が集まっていれば、どんな挑戦にも楽しく挑めるのではないでしょうか。 そのような素晴らしい環境で「ものづくり」をしたいと感じてくれた⽅がいましたら、ぜひお声がけください! 株式会社アガルートテクノロジーズの応募はこちらから
https://tech.agaroot.co.jp/#recruit https://www.praha-inc.com/recruit