Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Cargo Workspaces のススメ
Search
nawa
July 16, 2024
Programming
1.6k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Cargo Workspaces のススメ
https://uniquevision.connpass.com/event/323686/
の発表スライドです。
nawa
July 16, 2024
More Decks by nawa
See All by nawa
大規模プロダクトのための Cargo Workspaces ベストプラクティス
mnawa
0
440
Rust で型安全な SPA 開発
mnawa
0
890
Other Decks in Programming
See All in Programming
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
310
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
170
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
150
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
1.2k
Event is what happens
moro
2
2.8k
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
1.3k
AI Augmentation Techniques with Liberty
ivargrimstad
0
260
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
120
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
330
AI時代のTerminal環境を UNIX哲学で設計・運用する
yasunori0418
1
330
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
180
Featured
See All Featured
Optimizing for Happiness
mojombo
378
71k
The Limits of Empathy - UXLibs8
cassininazir
2
760
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
340
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
Producing Creativity
orderedlist
PRO
348
41k
For a Future-Friendly Web
brad_frost
184
11k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
Exploring anti-patterns in Rails
aemeredith
4
560
Building Adaptive Systems
keathley
44
3.3k
Writing Fast Ruby
sferik
630
63k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Transcript
Cargo Workspaces のススメ UV Study : Rust LT会 2024-07-17 Fairy
Devices株式会社 nawa ※ https://speakerdeck.com/mnawa/cargo-workspaces-nosusume
Cargo Workspaces 使ってますか? Cargo Workspaces ってなんや?って話があります。 詳しくは https://doc.rust-jp.rs/book-ja/ch14-03-cargo-workspaces.html に書いてるの でツラーっと読んでいきますと。
2
Cargo Workspaces 使ってますか? Cargo Workspaces ってなんや?って話があります。 詳しくは https://doc.rust-jp.rs/book-ja/ch14-03-cargo-workspaces.html に書いてるの でツラーっと読んでいきますと。
「ワークスペースの作り方」はあるけど、なにができるのか、なにがうれしい のか、がない!?!? 3 ※ "The Cargo Book" にも Workspaces のページがありますが、似たように設定項目の説明です : https://doc.rust-lang.org/cargo/reference/workspaces.html
「まとめ」を先出し (多い) • Cargo Workspaces を使うとモノレポ的に複数クレートを管理できます • 責務をクレートで分けるとわかりやすいです • 複数クレートあるあるの
Orphan Rule の回避法は book に載ってます • レイヤードアーキテクチャーとかいろんな種類のツールとか作りやすいです • プライベートなクレートに依存するときに、依存の依存を減らせます • Cargo.toml の値を共通で指定できます • サブクレートを 1 つのディレクトリーに入れると指定しやすいです • クレート名に共通の接頭辞をつけると、Docker レイヤーキャッシュを効かせやすい です 4
book の概説を使った Cargo Workspaces の説明 (1/4) add/ ├── Cargo.lock ├──
Cargo.toml ├── add-one/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── adder/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── target/ 要は「外側のクレート」の中に「内側のクレート (サブクレート)」を分けること ができる機能です。 5 ※ `add` 自体は src/ を持たない ([package] を持たない) から virtual workspace というやつ (src/ を持つこともできる): https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
book の概説を使った Cargo Workspaces の説明 (2/4) add/ ├── Cargo.lock ├──
Cargo.toml ├── add-one/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── adder/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── target/ 要は「外側のクレート」の中に「内側のクレート (サブクレート)」を分けること ができる機能です。 `add` の中で、`add_one` と `adder` という複数の異なるクレートを管理で きます。つまりモノレポです。 6 ※ `add` 自体は src/ を持たない ([package] を持たない) から virtual workspace というやつ (src/ を持つこともできる): https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
book の概説を使った Cargo Workspaces の説明 (3/4) add/ ├── Cargo.lock ├──
Cargo.toml ├── add-one/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── adder/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── target/ 要は「外側のクレート」の中に「内側のクレート (サブクレート)」を分けること ができる機能です。 `add` の中で、`add_one` と `adder` という複数の異なるクレートを管理で きます。つまりモノレポです。 `add_one` と `adder` それぞれに Cargo.toml があって、クレートごとに依 存を管理できます。 7 ※ `add` 自体は src/ を持たない ([package] を持たない) から virtual workspace というやつ (src/ を持つこともできる): https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
book の概説を使った Cargo Workspaces の説明 (4/4) add/ ├── Cargo.lock ├──
Cargo.toml ├── add-one/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── adder/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── target/ 要は「外側のクレート」の中に「内側のクレート (サブクレート)」を分けること ができる機能です。 `add` の中で、`add_one` と `adder` という複数の異なるクレートを管理で きます。つまりモノレポです。 `add_one` と `adder` それぞれに Cargo.toml があって、クレートごとに依 存を管理できます。 クレートは複数ありますが、中間生成物とか実行可能バイナリーは単一の `target/` ディレクトリーに入ります。 8 ※ `add` 自体は src/ を持たない ([package] を持たない) から virtual workspace というやつ (src/ を持つこともできる): https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
責務を分けやすい 9
別のクレートになるので責務を分けやすい 10 Web アプリケーションを作るときなどを考えると、 HTTP な部分、DB な部分、コア部分、とか分かれている方が 見通しが良いです。HTTP 部分が分かれてると、 CLI
のツールを作るとかもやりやすいです。 foo-core foo-server 色々 foo-db foo-auth0 foo-tools (CLI) ↳clap ↳serde, axum ↳serde, reqwest ↳diesel
クレートが分かれると Orphan Rule がつらい 11 Orphan Rule: 外部のクレートの型に impl できないやつ
→ newtype idiom で回避できます impl foo_core::TypeX { fn some_method(&self) -> i32 { todo!() } } ※1 book の Orphan Rule の説明: https://doc.rust-jp.rs/book-ja/ch10-02-traits.html?highlight=orphan#...... ※2 解消方法: https://doc.rust-jp.rs/book-ja/ch19-03-advanced-traits.html#........ struct TypeX(foo_core::TypeX); impl TypeX { fn some_method(&self) -> i32 { todo!() } } できないやつ newtype idiom で自分のクレートの型にする
すべてが依存するデータ型用のクレートがあると良い? 12 クレート間ごとに色々な From<T> を実装することになる?データ型用のクレートを作って、すべてのクレートか ら依存させ、それぞれの newtype 同士は中身だけ渡す。とかできると From<T> の実装が薄くなって嬉しそう。
foo-core foo-server 色々 foo-db foo-auth0 foo-tools (CLI) foo-types ※ diesel の FromSql / ToSql など、db でも types でも要りそうな型は、 types で実装して features で出し分けできると良さそう。
設計の話 13
レイヤードアーキテクチャを作りやすい レイヤードアーキテクチャーみたいな標準的な設計パターンを上手く当てはめられます。 14 ※ https://medium.com/swlh/clean-architecture-a-little-introduction-be3eac94c5d1
依存方向がこうなってますが…… 15 DIP (依存性逆転の原則) を考えると、 foo-core foo-server 色々 foo-db foo-auth0
foo-tools (CLI)
依存方向は本来はこうであるべき……? 16 DIP (依存性逆転の原則) を考えると、core から外に依存するのは良くないのでは? (弊社の問題です。) foo-core foo-server 色々
foo-db foo-auth0 foo-tools (CLI)
そうは言っても、core から分けたサブクレートへ依存したい状況もある 17 すべての SDK が crate.io にあるわけではないので (e.g. Auth0、社内の別システム
)、自分である程度の実装 が必要なものは lib 層、DIP 層とかに分ける必要がある。 (types クレートを用意していた場合でも、 types と lib の依存が必要。) foo-core foo-server foo-auth0-lib foo-auth0-dip データ型だけ依存したい 特化処理だけ依存したい core が要求する処理 (trait) を impl する DIP 層 システムに特化した処理を実装 する lib 層 ※ 社内の別システムも Rust で書かれているなら、そのシステムのサブクレートとしてクライアントライブラリーがあると便利そう
余談 18
余談: Workspaces に git 依存する 19 社内のクレートなどに git で依存するときは、個々のクレートに依存できます。 サーバーアプリケーションだと、クライアントライブラリーを
Workspaces でクレートとして用意して、別のシステ ムから依存するのがやりやすいです。 (単一のクレートになっていると、こういうときに依存ライブラリーが爆発的 に増えます。) [dependencies] foo-types = { git = "
[email protected]
/FairyDevices/foo.git" } foo-client = { git = "
[email protected]
/FairyDevices/foo.git" } Cargo.toml ※ https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories ※※ path 依存するときは個々のクレートへのパスを指定します。
共通の Cargo.toml の設定ができる 20
共通の Cargo.toml の設定ができる: 例1: 依存クレート 21 例えば serde のような、いろんなクレートから依存するクレートのバージョンや features
を 1 箇所で管理できる [workspace.dependencies] my-crate = { path = "my-crate/" } serde = { version = "1.0.203", features = ["derive"] } [dependencies] serde.workspace = true ./Cargo.toml 各クレートの Cargo.toml ※ https://doc.rust-lang.org/cargo/reference/workspaces.html の各項目が便利だよくらいの話が続きます。
共通の Cargo.toml の設定ができる: 例2: [packages] 22 crate.io に publish するクレートでより便利ではありますが、以下みたいな使い方もあります。
- version を個々に書かなくて良くなる - rust-version (Rust 処理系の最小バージョン ) が一箇所になる [workspace.packages] version = "0.1.0" rust-version = "1.79.0" [packages] version.workspace = true rust-version.workspace = true ./Cargo.toml 各クレートの Cargo.toml
Workspaces のオススメの使い方 23
サブクレートを一つのディレクトリーに入れよう 24 [workspace.members] では `*` が使えるので、サブクレートをすべて同じディレクトリーにおいておくと記述が楽 になります。 [workspace] members =
[ "./crates/*/", ] ./Cargo.toml my-crate/ ├── Cargo.lock ├── Cargo.toml ├── crates/ │ ├── sub_crate_a/ │ │ ├── Cargo.toml │ │ └── src/ │ │ └── lib.rs │ └── sub_crate_b/ │ ├── Cargo.toml │ └── src/ │ └── main.rs └── target ディレクトリー構造
クレート名に同一の接頭辞を付けよう 25 Docker Image をビルドするときに、依存クレートだけレイヤーにするとかがやりやすくなります。 FROM rust:1-bookworm AS builder COPY
Cargo.toml ./ COPY crates/my-crates-foo/Cargo.toml ./crates/my-crates-foo/ RUN mkdir ./crates/my-crate-foo/src/ \ && touch ./crates/my-crate-foo/src/lib.rs \ && cargo build --release \ && rm -r ./crates/my-crate-foo/src/ \ ./target/release/deps/my_crate* \ ./target/release/deps/libmy_crate_*.rlib COPY ./crates/my-crate-foo/src ./crate/my-crate-foo/src RUN cargo build --release Dockerfile 中間生成物の削除が楽
まとめ • Cargo Workspaces を使うとモノレポ的に複数クレートを管理できます • 責務をクレートで分けるとわかりやすいです • 複数クレートあるあるの Orphan
Rule の回避法は book に載ってます • レイヤードアーキテクチャーとかいろんな種類のツールとか作りやすいです • プライベートなクレートに依存するときに、依存の依存を減らせます • Cargo.toml の値を共通で指定できます • サブクレートを 1 つのディレクトリーに入れると指定しやすいです • クレート名に共通の接頭辞をつけると、Docker レイヤーキャッシュを効かせやすい です 26
終 27