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.5k
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
430
Rust で型安全な SPA 開発
mnawa
0
880
Other Decks in Programming
See All in Programming
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
330
パーソナライズPodcastを作った話
repunit11
0
140
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
250
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
490
パスワード再設定メールのURLについて知っておこう
uyuki234
0
140
CodeRabbitの効果検証と過ごしてみた3ヶ月
armondando
0
230
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
150
ChromeでローカルLLM
ryu1013
0
120
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
160
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
590
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
170
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Rails Girls Zürich Keynote
gr2m
96
14k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
330
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
520
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Darren the Foodie - Storyboard
khoart
PRO
4
4k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
630
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
730
Test your architecture with Archunit
thirion
2
2.4k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
A designer walks into a library…
pauljervisheath
211
25k
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